⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-tutorial06.htm

📁 内有一些代码
💻 HTM
字号:
<html>

<head>
<link rel="stylesheet" href="../../asm.css">

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>

<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">Tutorial 6: Keyboard Input</p>
<hr size="1">
We will learn how a Windows program receives keyboard input. 
<p>Download the example <a href="files/tut06.zip">here</a>. 
<h3> Theory:</h3>
Since normally there's only one keyboard in each PC, all running Windows programs 
must share it between them. Windows is responsible for sending the key strokes 
to the window which has the input focus. <br>
Although there may be several windows on the screen, only one of them has the 
input focus. The window which has input focus is the only one which can receive 
key strokes. You can differentiate the window which has input focus from other 
windows by looking at the title bar. The title bar of the window which has input 
focus is highlighted. <br>
Actually, there are two main types of keyboard messages, depending on your view 
of the keyboard. You can view a keyboard as a collection of keys. In this case, 
if you press a key, Windows sends a WM_KEYDOWN message to the window which has 
input focus, notifying that a key is pressed. When you release the key, Windows 
sends a WM_KEYUP message. You treat a key as a button. Another way to look at 
the keyboard is that it's a character input device. When you press "a" key, Windows 
sends a WM_CHAR message to the window which has input focus, telling it that the 
user sends "a" character to it. In fact, Windows sends WM_KEYDOWN and WM_KEYUP 
messages to the window which has input focus and those messages will be translated 
to WM_CHAR messages by TranslateMessage call. The window procedure may decide 
to process all three messages or only the messages it's interested in. Most of 
the time, you can ignore WM_KEYDOWN and WM_KEYUP since TranslateMessage function 
call in the message loop translate WM_KEYDOWN and WM_KEYUP messages to WM_CHAR 
messages. We will focus on WM_CHAR in this tutorial. <br>
&nbsp; 
<h3> Example:</h3>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</b> 
<p><b>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</b> 
<p><b>include \masm32\include\windows.inc</b> <br>
  <b>include \masm32\include\user32.inc</b> <br>
  <b>include \masm32\include\kernel32.inc</b> <br>
  <b>include \masm32\include\gdi32.inc</b> <br>
  <b>includelib \masm32\lib\user32.lib</b> <br>
  <b>includelib \masm32\lib\kernel32.lib</b> <br>
  <b>includelib \masm32\lib\gdi32.lib</b> 
<p><b>.data</b> <br>
  <b>ClassName db "SimpleWinClass",0</b> <br>
  <b>AppName&nbsp; db "Our First Window",0</b> <br>
  <b>char WPARAM 20h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ; the character the program receives from keyboard</b> 
<p><b>.data?</b> <br>
  <b>hInstance HINSTANCE ?</b> <br>
  <b>CommandLine LPSTR ?</b> 
<p><b>.code</b> <br>
  <b>start:</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke GetModuleHandle, NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hInstance,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke GetCommandLine<br>
  &nbsp;&nbsp;&nbsp;&nbsp;mov CommandLine,eax</b><br>
  <b>&nbsp;&nbsp;&nbsp; invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; invoke ExitProcess,eax</b> 
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL wc:WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL msg:MSG</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL hwnd:HWND</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.style, CS_HREDRAW or CS_VREDRAW</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpfnWndProc, OFFSET WndProc</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbClsExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbWndExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; push&nbsp; hInst</b> <br>
  <b>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp; wc.hInstance</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hbrBackground,COLOR_WINDOW+1</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszMenuName,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszClassName,OFFSET ClassName</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIcon,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIconSm,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadCursor,NULL,IDC_ARROW</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hCursor,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke RegisterClassEx, addr wc</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hInst,NULL</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; hwnd,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke ShowWindow, hwnd,SW_SHOWNORMAL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke UpdateWindow, hwnd</b> <br>
  <b>&nbsp;&nbsp;&nbsp; .WHILE TRUE</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  invoke GetMessage, ADDR msg,NULL,0,0</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  .BREAK .IF (!eax)</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  invoke TranslateMessage, ADDR msg</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  invoke DispatchMessage, ADDR msg</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .ENDW</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,msg.wParam</b> <br>
  <b>&nbsp;&nbsp;&nbsp; ret</b> <br>
  <b>WinMain endp</b> 
<p><b>WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL hdc:HDC</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL ps:PAINTSTRUCT</b> 
<p><b>&nbsp;&nbsp;&nbsp; .IF uMsg==WM_DESTROY</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke PostQuitMessage,NULL</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; .ELSEIF uMsg==WM_CHAR</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push wParam</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop&nbsp; char</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke InvalidateRect, hWnd,NULL,TRUE</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; .ELSEIF uMsg==WM_PAINT</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke BeginPaint,hWnd, ADDR ps</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hdc,eax</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke TextOut,hdc,0,0,ADDR char,1</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke EndPaint,hWnd, ADDR ps</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; .ELSE</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke DefWindowProc,hWnd,uMsg,wParam,lParam</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret</b> <br>
  <b>&nbsp;&nbsp;&nbsp; .ENDIF</b> <br>
  <b>&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp; eax,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; ret</b> <br>
  <b>WndProc endp</b> <br>
  <b>end start</b> <br>
  &nbsp; 
<h3> Analysis:</h3>
<p><br>
  <b>char WPARAM 20h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ; the character the program receives from keyboard</b> 
<p>This is the variable that will store the character received from the keyboard. 
  Since the character is sent in WPARAM of the window procedure, we define the 
  variable as type WPARAM for simplicity. The initial value is 20h or the space 
  since when our window refreshes its client area the first time, there is no 
  character input. So we want to display space instead. 
<p><b>&nbsp;&nbsp;&nbsp; .ELSEIF uMsg==WM_CHAR</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push wParam</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop&nbsp; char</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke InvalidateRect, hWnd,NULL,TRUE</b> 
<p>This is added in the window procedure to handle the WM_CHAR message. It just 
  puts the character into the variable named "char" and then calls InvalidateRect. 
  InvalidateRect makes the specified rectangle in the client area invalid which 
  forces Windows to send WM_PAINT message to the window procedure. Its syntax 
  is as follows: 
<p><b>InvalidateRect proto hWnd:HWND,\</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  lpRect:DWORD,\</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  bErase:DWORD</b> 
<p><b>lpRect</b> is a pointer to the rectagle in the client area that we want 
  to declare invalid. If this parameter is null, the entire client area will be 
  marked as invalid. <br>
  <b>bErase</b> is a flag telling Windows if it needs to erase the background. 
  If this flag is TRUE, then Windows will erase the backgroud of the invalid rectangle 
  when BeginPaint is called. 
<p>So the strategy we used here is that: we store all necessary information relating 
  to painting the client area and generate WM_PAINT message to paint the client 
  area. Of course, the codes in WM_PAINT section must know beforehand what's expected 
  of them. This seems a roundabout way of doing things but it's the way of Windows. 
  <br>
  Actually we can paint the client area during processing WM_CHAR message by calling 
  GetDC and ReleaseDC pair. There is no problem there. But the fun begins when 
  our window needs to repaint its client area. Since the codes that paint the 
  character are in WM_CHAR section, the window procedure will not be able to repaint 
  our character in the client area. So the bottom line is: put all necessary data 
  and codes that do painting in WM_PAINT. You can send WM_PAINT message from anywhere 
  in your code anytime you want to repaint the client area. 
<p><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke TextOut,hdc,0,0,ADDR char,1</b> 
<p>When InvalidateRect is called, it sends a WM_PAINT message back to the window 
  procedure. So the codes in WM_PAINT section is called. It calls BeginPaint as 
  usual to get the handle to device context and then call TextOut which draws 
  our character in the client area at x=0, y=0. When you run the program and press 
  any key, you will see that character echo in the upper left corner of the client 
  window. And when the window is minimized and maximized again, the character 
  is still there since all the codes and data essential to repaint are all gathered 
  in WM_PAINT section. 
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -