6.1-键盘之综合示例

来源:互联网 发布:三挫仑在淘宝上叫什么 编辑:程序博客网 时间:2024/05/15 20:03

第六章—–键盘

windows程序中,对于键盘消息的处理,分为击键消息和字符消息。

击键消息
包括WM_KEYDOWM,WM_KEYUP,WM_SYSKEYDOWM,WM_SYSKEYUP,其中windows会自动处理WM_SYSKEYDOWM,WM_SYSKEYUP,应用程序则负责其他两种。

字符消息
也分为四种。
这里写图片描述

大多数情况下,我们只用处理非系统字符消息WM_CHAR就行。

综合示例之typer源程序。下面是一些核心代码。

宏定义:

#define BUFFER(x,y) *(pBuffer+y*cxBuffer+x)        //表示光标所在处的内容

常量和一些变量定义

    static DWORD dwCharSet=DEFAULT_CHARSET; //默认字体    static int   cxChar,cyChar,cxClient,cyClient,cxBuffer,                 cyBuffer,xCaret,yCaret;    static TCHAR *pBuffer=NULL;    HDC          hdc;    int          x,y,i;    PAINTSTRUCT  ps;    TEXTMETRIC   tm;

核心窗口处理过程:

case WM_CREATE:        hdc=GetDC(hwnd);        SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,                        dwCharSet,0,0,0,FIXED_PITCH,NULL));        GetTextMetrics(hdc,&tm);        cxChar=tm.tmAveCharWidth;        cyChar=tm.tmHeight;        DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)));        ReleaseDC(hwnd,hdc);

详解CreateFont函数,
这里写图片描述

nHeight,nWidth参数为0 ,表示的取默认高度和宽度,即SYSTEM _FONT。

同时由于该函数动态分配了内存,所以在获取字体属性不再使用后就释放掉,DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)))

    case WM_SIZE:                                  //发送WM_Paint的前期工作        if(message==WM_SIZE)        {            cxClient=LOWORD(lParam);            cyClient=HIWORD(lParam);        }        cxBuffer=max(1,cxClient/cxChar);            //只要尺寸发生改变,就要更新一次cxClient,cyClient,cxBuffer,cyBuffer        cyBuffer=max(1,cyClient/cyChar);        if(pBuffer!=NULL)                           //同时释放之前的内容所占的内存空间,重新开辟            free(pBuffer);        pBuffer=(TCHAR*)malloc(cxBuffer*cyBuffer*sizeof(TCHAR));        for(y=0;y<cyBuffer;y++)            for(x=0;x<cxBuffer;x++)                BUFFER(x,y)=' ';        //设置光标为左上角        xCaret=0;        yCaret=0;        if(hwnd==GetFocus())            SetCaretPos(xCaret*cxChar,yCaret*cyChar);        InvalidateRect(hwnd,NULL,TRUE);        return 0;

为什么要在焦点集中窗口时,创建和显示插入符号,而不是即使一个程序中有多个窗口就同时创建多个插入符号?咋听着就很别扭了,的确。
第一,没必要多个窗口都闪烁着插入符号,插入符号的作用是提示用户焦点在该窗口。
第二,一个消息队列仅能够支持一个插入符号,如果你的应用程序有多个窗口,那么也只能共享一个插入符号。

case WM_SETFOCUS:        //创建和显示插入符号        CreateCaret(hwnd,NULL,cxChar,cyChar);        SetCaretPos(xCaret*cxChar,yCaret*cyChar);        ShowCaret(hwnd);        return 0;    case WM_KILLFOCUS:        //隐藏和干掉插入符号        HideCaret(hwnd);        DestroyCaret();        return 0;

处理击键消息 WM_KEYDOWM,表示某个键的按下。VK_表示虚拟键盘的意思

    case WM_KEYDOWN:        switch(wParam)        {        case VK_HOME:            xCaret=0;            break;        case VK_END:            xCaret=cxBuffer-1;            break;        case VK_PRIOR:                                  yCaret=0;            break;        case VK_NEXT:                                   yCaret=cyBuffer-1;            break;        case VK_LEFT:            xCaret=max(xCaret-1,0);         //最小值为0            break;        case VK_RIGHT:            xCaret=min(xCaret+1,cxBuffer-1);   //最大值为cxBuffer-1            break;        case VK_UP:            yCaret=max(yCaret-1,0);                    break;        case VK_DOWN:            yCaret=min(yCaret+1,cyBuffer-1);            break;        case VK_DELETE:            for(x=xCaret;x<cxBuffer-1;x++)                BUFFER(x,yCaret)=BUFFER(x+1,yCaret);            BUFFER(cxBuffer-1,yCaret)=' ';          //向前移动后完,末尾要补空白            HideCaret(hwnd);            hdc=GetDC(hwnd);            SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,                dwCharSet,0,0,0,FIXED_PITCH,NULL));            TextOut(hdc,xCaret*cxChar,yCaret*cyChar,        //上面只是改变了数组的内容,这一步是显示,刷新客户区的内容                &BUFFER(xCaret,yCaret),                     //&BUFFER(xCaret,yCaret)取当前位置的地址,表示当前位置到末尾的内容                cxBuffer-xCaret);            DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)));            ReleaseDC(hwnd,hdc);            ShowCaret(hwnd);              break;        }        SetCaretPos(xCaret*cxChar,yCaret*cyChar);        //这里统一刷新插入符号的位置        return 0;

这里主要观察窗口过程如何处理message,wParam,lParam,可见message主要表名消息类型,wParam,lParam则具体消息内容

case WM_CHAR:            for(i=0;i<(int)LOWORD(lParam);i++)            {                switch(wParam)                {                case '\b':                              //空格 ,但这里是删除后流出空格                    if(xCaret>0)                    {                        xCaret--;                        SendMessage(hwnd,WM_KEYDOWN,VK_DELETE,1);                    }                    break;                case '\t':                              //tab键,也是删除后继内容,而不是整体移动。                    do                    {                        SendMessage(hwnd,WM_CHAR,' ',1);                    }                    while(xCaret%8!=0);                    break;                case '\n':                    if(++yCaret==cyBuffer)            //换行                        yCaret=0;                    break;                case '\x1B':                    for(y=0;y<cyBuffer;y++)                        for(x=0;x<cxBuffer;x++)                            BUFFER(x,y)=' ';                    xCaret=0;                    yCaret=0;                    InvalidateRect(hwnd,NULL,FALSE);                    break;                default:                    BUFFER(xCaret,yCaret)=(TCHAR)wParam;           //字母输入                    HideCaret(hwnd);                    hdc=GetDC(hwnd);                    SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,                        dwCharSet,0,0,0,FIXED_PITCH,NULL));                    TextOut(hdc,xCaret*cxChar,yCaret*cyChar,        //单个字母                        &BUFFER(xCaret,yCaret),1);                    DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)));                    ReleaseDC(hwnd,hdc);                    ShowCaret(hwnd);                    if(++xCaret==cxBuffer)                    {                        xCaret=0;                        if(++yCaret==cyBuffer)                            yCaret=0;                    }                    break;                }            }            SetCaretPos(xCaret*cxChar,yCaret*cyChar);            return 0;
    case WM_PAINT:            hdc=BeginPaint(hwnd,&ps);            SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,                dwCharSet,0,0,0,FIXED_PITCH,NULL));            for(y=0;y<cyBuffer;y++)                                     //更新客户区所有内容                TextOut(hdc,0,y*cyChar,&BUFFER(0,y),cxBuffer);            DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)));            EndPaint(hwnd,&ps);            return 0;

完整示例程序:http://download.csdn.net/detail/u014034497/8918517

0 0