标题:windows sdk编程-处理键盘输入消息
只看楼主
tsjoy
Rank: 1
等 级:禁止访问
帖 子:13
专家分:0
注 册:2008-8-5
 问题点数:0 回复次数:1 
windows sdk编程-处理键盘输入消息
相关网站:http://edu.

因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它。WINDOWS 将负责把击键消息送到具有输入焦点的那个应用程序中去。尽管屏幕上可能同时有几个应用程序窗口,但一个时刻仅有一个窗口有输入焦点。有输入焦点的那个应用程序的标题条总是高亮度显示的。 实际上您可以从两个角度来看键盘消息:一是您可以把它看成是一大堆的按键消息的集合,在这种情况下,当您按下一个键时,WINDOWS就会发送一个WM_KEYDOWN给有输入焦点的那个应用程序,提醒它有一个键被按下。当您释放键时,WINDOWS又会发送一个WM_KYEUP消息,告诉有一个键被释放。您把每一个键当成是一个按钮;另一种情况是:您可以把键盘看成是字符输入设备。当您按下“a”键时,WINDOWS发送一个WM_CHAR消息给有输入焦点的应用程序,告诉它“a”键被按下。实际上WINDOWS 内部发送WM_KEYDOWN和WWM_KEYUP消息给有输入焦点的应用程序,而这些消息将通过调用TranslateMessage翻译成WM_CHAR消息。WINDOWS窗口过程函数将决定是否处理所收到的消息,一般说来您不大会去处理WM_KEYDOWN、WM_KEYUP消息,在消息循环中TranslateMessage函数会把上述消息转换成WM_CHAR消息。在我们的课程中将只处理WM_CHAR。

#include "Windows.h"
#include "tchar.h"

HWND hWinMain;
TCHAR szClassName[] = _T("MyClass");
TCHAR szCaptionMain[] = _T("My First Window!");
TCHAR FontName[] = _T("script");
WNDCLASSEX stdWndClass;
WPARAM keyChar = 0x20; //0x20是空格的ascii码,保证没有按键的时候程序正常显示。
LRESULT CALLBACK ProcWinMain(   HWND hWnd,
                       UINT Msg,
                       WPARAM wParam,
                       LPARAM lParam
)
{
    PAINTSTRUCT stPs;
    HDC hDC;
    HFONT hFont,hOldFont;
    switch(Msg)
    {
        case WM_PAINT:
        {
            hDC = BeginPaint(hWnd,&stPs);
            hFont = CreateFont(24,16,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,
                CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_SCRIPT,FontName);

            hOldFont = (HFONT)SelectObject(hDC,hFont);
            SetTextColor(hDC,RGB(200,200,50));
            SetBkColor(hDC,RGB(0,0,255));
            TextOut(hDC,0,0,(char *)&keyChar,1);
            SelectObject(hDC,hOldFont);
            EndPaint(hWnd,&stPs);
        }
        break;

        case WM_CHAR:
            {
                keyChar = wParam;
                InvalidateRect(hWnd,NULL,TRUE);
            }
            break;
        case WM_DESTROY:
        {
            PostQuitMessage(NULL);
        }
        break;

        default:
            return DefWindowProc(hWnd, Msg, wParam, lParam );
    }
    return 0;
}

int WINAPI WinMain(     HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine,
                        int nCmdShow
)
{
    MSG stMsg;
    WNDCLASSEX stdWndClass;
    RtlZeroMemory(&stdWndClass, sizeof(stdWndClass));
    stdWndClass.hCursor = LoadCursor(0,IDC_ARROW);
    stdWndClass.cbSize = sizeof(stdWndClass);
    stdWndClass.style = CS_HREDRAW|CS_VREDRAW;
    stdWndClass.lpfnWndProc = ProcWinMain;
    stdWndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
    stdWndClass.lpszClassName = szClassName;
    stdWndClass.hInstance = hInstance;

    RegisterClassEx(&stdWndClass);

    hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,szCaptionMain,\
       WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);

    if(!hWinMain)
        return 0;
   
    ShowWindow(hWinMain,SW_SHOWNORMAL);
    UpdateWindow(hWinMain);


    while(GetMessage(&stMsg,NULL,0,0))
    {
        TranslateMessage(&stMsg);
        DispatchMessage(&stMsg);
    }

    return stMsg.wParam;
}



分析:


WPARAM keyChar = 0x20;
这个变量将保存从键盘接收到的字符。因为它是在窗口过程中通过WPARAM型变量传送的,所以我们简单地把它定义为WPARAM型。由于我们的窗口在初次刷新时(也即刚被创建的那一次)是没有键盘输入的所以我们把他设成空格符(20h),这样显示时您就什么都看不见。

           case WM_CHAR:
            {
                  keyChar = wParam;
                  InvalidateRect(hWnd,NULL,TRUE);
            }
这一段是用来处理WM_CHAR消息的。它把接收到的字符放入变量keyChar 中,接着调用InvalidateRect,而InvalidateRect使得窗口的客户区无效,这样它会发出WM_PAINT消息,而WM_PAINT消息迫使WINDOWS重新绘制它的客户区。该函数的语法如下:

BOOL InvalidateRect(

                                 HWND hWnd, // handle to window


                                 CONST RECT* lpRect, // rectangle coordinates


                                 BOOL bErase // erase state


                                );

lpRect是指向客户区我们想要其无效的一个正方形结构体的指针。如果该值等于NULL,则整个客户区都无效;布尔值bErase告诉WINDOWS是否擦除背景,如果是TRUE,则WINDOWS在调用BeginPaint函数时把背景擦掉。 所以我们此处的做法是:我们将保存所有有关重绘客户区的数据,然后发送WM_PAINT消息,处理该消息的程序段然后根据相关数据重新绘制客户区。尽管这么做事有点像走了弯路,但WINDOWS要处理那么庞大的消息群,没有一定的规矩可不行。 实际上我们完全可以通过调用GetDC 获得设备上下文句柄,然后绘制字符,然后再调用ReleaseDC释放设备上下文句柄,毫无疑问这样也能在客户区绘制出正确的字符。但是如果这之后接收到WM_PAINT消息要处理时,客户区会重新刷新,而我们这稍前所绘制的字符就会消失掉。所以为了让字符一直正确地显示,就必须把它们放到WM_PAINT的处理过程中处理。而在本消息处理中发送WM_PAINT消息即可。

    TextOut(hDC,0,0,(char *)&keyChar,1);

在调用InvalidateRect时,WM_PAINT消息被发送到了WINDOWS窗口处理过程,程序流程转移到处理WM_PAINT消息的程序段,然后调用BeginPaint得到设备上下文的句柄,再调用TextOut在客户区的(0,0)处输出保存的按键字符。这样无论您按什么键都能在客户区的左上角显示,不仅如此,无论您怎么缩放窗口(迫使WINDOWS重新绘制它的客户区),字符都会在正确的地方显示,所以必须把所有重要的绘制动作都放到处理WM_PAINT消息的程序段中去。

相关网站:http://edu.
搜索更多相关主题的帖子: sdk windows 键盘 输入 
2008-11-06 09:08
smallmoon521
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:517
专家分:1373
注 册:2008-4-21
得分:0 
好帖,支持楼主!WINDOWS编程对C来说是分不开的!

为游戏狂~~!!    大家努力编哈!
2008-11-10 10:59



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-242659-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.070847 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved