6.1-键盘之综合示例

第六章—–键盘

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值