这次我们将学习如何在我们的窗口过程函数中处理鼠标按键消息。例子演示了如何等待鼠标左键按下消息,我们将在按下的位置显示一个字符串。

理论:

和处理键盘输入一样,WINDOWS将捕捉鼠标动作并把它们发送到相关窗口。这些活动包括左、右键按下、移动、双击、滚轮消息WM_WHEEL等。WINDOWS并不像处理键盘输入那样把所有的鼠标消息都导向有输入焦点的窗口,任何鼠标经过的窗口都将接收到鼠标消息,无论有否输入焦点。另外,窗口还会接收到鼠标在非客户区移动的消息(WM_NCMOVE),但大多数的情况下我们都会将其忽略掉。当鼠标在某窗口客户区移动时,该窗口将接收到WM_MOUSEMOVE消息。一个窗口若想处理WM_LBUTTONDBCLKWM_RBUTTONDBCLK,那么它的窗口类必须有CS_DBLCLKS风格,否则它就会接受到一堆的按键起落(WM_XBUTTONDOWNWM_XBUTTONUP)的消息。 对于所有的消息,窗口过程函数传入的参数lParam包含了鼠标的位置,其中低位为x坐标,高位为y坐标,这些坐标值都是相对于窗口客户区的左上角的值,wParam中则包含了鼠标按钮的状态。

例子:

.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
MouseClick db 0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hitpoint POINT <>

.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 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_LBUTTONDOWN mov eax,lParam and eax,0FFFFh mov hitpoint.x,eax mov eax,lParam shr eax,16 mov hitpoint.y,eax mov MouseClick,TRUE invoke InvalidateRect,hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT invoke BeginPaint,hWnd, ADDR ps mov    hdc,eax .IF MouseClick invoke lstrlen,ADDR AppName invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax .ENDIF invoke EndPaint,hWnd, ADDR ps
.ELSE invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret
.ENDIF
xor    eax,eax
ret 

WndProc endp
end start

分析:

.ELSEIF uMsg==WM_LBUTTONDOWN mov eax,lParam and eax,0FFFFh mov hitpoint.x,eax mov eax,lParam shr eax,16 mov hitpoint.y,eax mov MouseClick,TRUE invoke InvalidateRect,hWnd,NULL,TRUE 

窗口过程处理了WM_LBUTTONDOWN消息,当接收到该消息时,lParam中包含了相对于窗口客户区左上角的坐标,我们把它保存下来,放到一个结构体变量(POINT)中,该结构体变量的定义如下:

POINT STRUCT x   dd ? y   dd ?
POINT ENDS 

然后我们把标志量MouseClick设为TRUE,这表明至少有一次在客户区的左键按下消息。

        mov eax,lParam and eax,0FFFFh mov hitpoint.x,eax 

由于lParam是一个32位长的数,其中高、低16位分别包括了y、x坐标所以我们做一些小处理,以便保存它们。

        shr eax,16 mov hitpoint.y,eax 

保存完坐标后我们设标志MouseClickTRUE,这是在处理WM_PAINT时用来判断是否有鼠标左键按下消息。然后我们调用InvalidateRect函数迫使WINDOWS重新绘制客户区。

        .IF MouseClick invoke lstrlen,ADDR AppName invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax .ENDIF 

绘制客户区的代码首先检测MouseClick标志位,再决定是否重绘。因为我们在首次显示窗口时还没有左键按下的消息,所以我们在初始时把该标志设为FALSE,告诉WINDOWS不要重绘客户区,当有左键按下的消息时,它会在鼠标按下的位置绘制字符串。注意在调用TextOut函数时,其关于字符串长度的参数是调用lstrlen函数来计算的。

转载于:https://www.cnblogs.com/Akkuman/p/8435590.html

Win32汇编学习(7):鼠标输入消息相关推荐

  1. Win32汇编学习——windows汇编语法(小甲鱼教程)

    Win32汇编学习--windows汇编语法(小甲鱼教程) 1)指令集 .386 语句是汇编语句的伪指令,类似指令有:.8086 . .186  ..286  ..386/.386p  . .486/ ...

  2. Win32汇编学习笔记之基础篇

    基础篇 第一章 背景知识 1.1 Win32的软硬件平台 1.1.1    80x86系列处理器简史 Win32可以在多种硬件平台上运行,但使用最广泛的硬件平台是基于Intel公司80x86系列处理器 ...

  3. win32汇编学习的一些摘要

    sizeof 变量名,数据类型或数据结构 lengthof 变量名.数据类型或数据结构名 sizeof 伪指令可以取得变量.数据类型或数据结构以字节为单位的长度,lengthof可以取得变量中数据的项 ...

  4. Win32汇编学习——windows基础知识(小甲鱼教程)

    <Win32汇编语言程序设计>(小甲鱼) 1)windows特权保护机制 1)80386的中断和异常 2)80386的保护机制 3)Windows的保护机制 2)80x86处理器的工作模式 ...

  5. Win32汇编学习(10):对话框(1)

    现在我们开始学习一些有关GUI编程的有趣的部分:以对话框为主要界面的应用程序. 理论: 如果您仔细关注过前一个程序就会发现:您无法按TAB键从一个子窗口控件跳到另一个子窗口控件,要想转移的话只有 用鼠 ...

  6. Win32汇编学习笔记(罗云彬)(二)

    1.代码段的属性是由PE头部中的属性位决定的,通过编辑exe文件,把代码段的属性位改为可写,程序就允许修改自己的代码段.典型的应用如:这对可执行文件的压缩软件和加壳软件. 2.堆栈段的内存属性是可读可 ...

  7. Win32汇编获取窗体的mousehover消息

    默认情况下Windows窗体是不会响应WM_MOUSELEAVE和WM_MOUSEHOVER消息的,通过使用_TrackMouseEvent这个函数可以激活这两个消息.在调用这个函数后,当鼠标在指定窗 ...

  8. Win32汇编学习[7]: 定义符号常量(=、EQU、TEXTEQU)

    关于符号常量 =的例子 .386 .model flat,stdcall include   windows.inc include   kernel32.inc include   masm32.i ...

  9. Win32汇编学习笔记(罗云彬)(一)

    1.80x86处理器的3种工作模式:实模式.保护模式和虚86模式 ;>>>>>>>>>>>>>>>>&g ...

最新文章

  1. 16 大常考算法知识点,你掌握了吗?
  2. Notepad++ 6.0 发布,优化了大文件加载性能
  3. 男人“杀”死女人的30句话
  4. 机器学习专题(一):绪论
  5. 金额大小写转换(2)
  6. MSDN2008中文版下载地址
  7. 如何写项目文档?项目文档有哪些?
  8. Python数据分析与展示-图像的手绘效果
  9. 浏览器访问IPv6地址
  10. 初学者如何快速搭建一个属于自己的网站
  11. Foxmail是什么邮箱?
  12. 《汇编语言程序设计》(双语)上机指导
  13. MySQL - 索引的数据结构
  14. 定时器alarm函数
  15. 笔记本电脑右下角网络图标显示红叉
  16. openlayers地图实现地点标注
  17. python----常用模块(常用方法)
  18. 微信群管理机器人开发sdk
  19. 降雨量(附我的SB调题过程)
  20. 将大程序缩减为小程序,数据决定程序结构

热门文章

  1. 谈谈JavaScript中function多重理解
  2. easyUI根据参数动态的生成列数
  3. 理解 Memory barrier(内存屏障)【转】
  4. 2012总结--目录
  5. ThinkPHP3.2开启静态缓存
  6. fedora下java环境配置
  7. 护士如何预防职业病:下肢静脉曲张-健康小常识
  8. 希尔排序 最坏时间_算法篇----希尔排序
  9. mysql管理数据 并上传至云端_西部数码网站管理助手创建、导入恢复、导出备份mysql数据库...
  10. 1039. 到底买不买(20)-PAT乙级真题