WIN32汇编: 6.处理键盘消息

原创 2001年06月17日 20:14:00

第六课 处理键盘输入消息


在本课中,我们将要学习WINDOWS程序是如何处理键盘消息的。

理论:

因为大多数的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。

例子:

.386
.model flat,stdcall
option casemap:none

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
include /masm32/include/gdi32.inc
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/gdi32.lib

.data
ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0
char WPARAM 20h                         ; the character the program receives from keyboard

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
    invoke GetModuleHandle, NULL
    mov    hInstance,eax
    invoke GetCommandLine
    mov CommandLine,eax

    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInst
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,/
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,/
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,/
           hInst,NULL
    mov   hwnd,eax
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
    .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    LOCAL hdc:HDC
    LOCAL ps:PAINTSTRUCT

    .IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL
    .ELSEIF uMsg==WM_CHAR
        push wParam
        pop  char
        invoke InvalidateRect, hWnd,NULL,TRUE
    .ELSEIF uMsg==WM_PAINT
        invoke BeginPaint,hWnd, ADDR ps
        mov    hdc,eax
        invoke TextOut,hdc,0,0,ADDR char,1
        invoke EndPaint,hWnd, ADDR ps
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF
    xor    eax,eax
    ret
WndProc endp
end start
 

分析:


char WPARAM 20h               ; the character the program receives from keyboard

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

  .ELSEIF uMsg==WM_CHAR
        push wParam
        pop  char
        invoke InvalidateRect, hWnd,NULL,TRUE

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

InvalidateRect proto hWnd:HWND,/
                                 lpRect:DWORD,/
                                 bErase:DWORD

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

invoke TextOut,hdc,0,0,ADDR char,1

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

Windows键盘消息处理

文大部分来自MSDN和网友的博客,我在实践的基础上再作了一些总结。 1. 虚拟键(VK_*) 键盘上每一个键对应一个扫描码,扫描码是OEM厂商制定的,不同的厂商生产的键盘同样一个按键的扫描...
  • leehong2005
  • leehong2005
  • 2013年02月26日 11:52
  • 9148

[Win32]键盘消息

1. 为Sysmets3程序添加击键消息:     1) 主要是添加了Page Up、Page Down、
  • Lirx_Tech
  • Lirx_Tech
  • 2014年10月28日 14:42
  • 1571

原谅我今天才学会使用win32的按键消息处理!

之前一直写directX的程序,用到的win32消息并不多,而且大部分的按键捕获都是有directInput完成的,因为能捕获到手柄那样的按键(而且据说还是实时的消息捕获)。。。 今天当我想...
  • zengraoli
  • zengraoli
  • 2013年04月18日 10:19
  • 2692

WIN32学习——鼠标消息

1 基本鼠标消息     WM_LBUTTONDOWN - 鼠标左键按下     WM_LBUTTONUP - 鼠标左键抬起     WM_RBUTTONDOWN - 鼠标右键按下     W...
  • bimabushihaodongxi
  • bimabushihaodongxi
  • 2017年04月29日 00:47
  • 278

WIN32汇编: 7.处理鼠标输入消息

第七课 处理鼠标输入消息本课中我们将学习如何在我们的窗口过程函数中处理鼠标按键消息。示例程序演示了如何等待左键按下消息,我们将在按下的位置显示一个字符串。 理论:和处理键盘输入一样,WINDOWS将捕...
  • GodDragon
  • GodDragon
  • 2001年06月17日 20:16
  • 919

[Win32]Win32 SDK编程系列文章——键盘输入消息

理论 因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它。WINDOWS 将负责把击键消息送到具有输入焦点的那个应用程序中去。尽管屏幕上可能同时有几个应用程序窗口,但一个...
  • ouyangshima
  • ouyangshima
  • 2013年06月05日 17:21
  • 1631

Win32 SDK基础(13)—— 键盘和鼠标消息

一、键盘消息 1、键盘消息 WM_KEYDOWN —— 键盘按键按下时产生。 WM_KEYUP —— 键盘按键弹起时产生。 WM_SYSKEYDOWN —— 系统按键按下时产生,如ALT、F1...
  • lzhui1987
  • lzhui1987
  • 2017年05月31日 09:35
  • 858

c语言 windows程序设计之键盘消息处理

首先说明 WM_KEYDOWN 、WM_KEYUP 或者 WM_SYSKEYDOWN、WM_SYSKEYUP是成对出现的,所以一般wo...
  • u014620925
  • u014620925
  • 2014年05月23日 18:43
  • 998

Win32 键盘事件 - 击键消息、字符消息、插入符号(光标)

分类: Win32 SDK 2012-11-11 01:50 4093人阅读 评论(0) 收藏 举报 Win32击键消息字符消息插入符号光标 目录(?)[+] 注:...
  • jolin678
  • jolin678
  • 2015年09月15日 21:14
  • 284

Win32 SDK开发中对话框控件消息处理

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ switch (message)...
  • wjt_bc
  • wjt_bc
  • 2010年05月28日 10:45
  • 1198
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:WIN32汇编: 6.处理键盘消息
举报原因:
原因补充:

(最多只允许输入30个字)