Win32汇编学习(7):鼠标输入消息
这次我们将学习如何在我们的窗口过程函数中处理鼠标按键消息。例子演示了如何等待鼠标左键按下消息,我们将在按下的位置显示一个字符串。
理论:
和处理键盘输入一样,WINDOWS将捕捉鼠标动作并把它们发送到相关窗口。这些活动包括左、右键按下、移动、双击、滚轮消息WM_WHEEL
等。WINDOWS并不像处理键盘输入那样把所有的鼠标消息都导向有输入焦点的窗口,任何鼠标经过的窗口都将接收到鼠标消息,无论有否输入焦点。另外,窗口还会接收到鼠标在非客户区移动的消息(WM_NCMOVE
),但大多数的情况下我们都会将其忽略掉。当鼠标在某窗口客户区移动时,该窗口将接收到WM_MOUSEMOVE
消息。一个窗口若想处理WM_LBUTTONDBCLK
或 WM_RBUTTONDBCLK
,那么它的窗口类必须有CS_DBLCLKS
风格,否则它就会接受到一堆的按键起落(WM_XBUTTONDOWN
或WM_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
保存完坐标后我们设标志MouseClick
为TRUE
,这是在处理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
函数来计算的。
Win32汇编学习(7):鼠标输入消息的更多相关文章
- 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
- Win32汇编学习(4):绘制文本
这次,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: "绘制"字符串 Windows 中的文本是一 ...
- Win32汇编学习(5):绘制文本2
这次我们将学习有关文本的诸多属性如字体和颜色等. 理论: Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表蓝色.如果您想指定一种颜色就必须给该颜色赋相关的 RGB ...
- Win32汇编学习(1):基本概念
背景知识 Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而 ...
- Win32汇编学习(6):键盘输入消息
这次,我们将要学习WINDOWS程序是如何处理键盘消息的. 理论: 因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它.WINDOWS 将负责把击键消息送到具有输入焦点的那个应 ...
- win32 汇编学习(2):消息框
这一次,我们将用汇编语言写一个 Windows 程序,程序运行时将弹出一个消息框并显示"你好,我的第一个Win32汇编程序". 理论知识 Windows 为编写应用程序提供了大量的 ...
- Win32汇编学习(10):对话框(1)
现在我们开始学习一些有关GUI编程的有趣的部分:以对话框为主要界面的应用程序. 理论: 如果您仔细关注过前一个程序就会发现:您无法按TAB键从一个子窗口控件跳到另一个子窗口控件,要想转移的话只有 用鼠 ...
- Win32汇编学习(3):简单的窗口
这次我们将写一个 Windows 程序,它会在桌面显示一个标准的窗口,以此根据代码来学习如何创建一个简单的窗口. 理论: Windows 程序中,在写图形用户界面时需要调用大量的标准 Windows ...
- Win32汇编学习(11):对话框(2)
我们将进一步学习对话框,探讨如何把对话框当成输入设备.如果您看了前一篇文章,那就会发现这次的例子只有少量的改动,就是把我们的对话框窗口附属到主窗口上.另外,我们还要学习通用对话框的用法. 理论: 把对 ...
随机推荐
- cf 893 E
有 次询问,第 次询问包含两个数 . 求满足下面两个要求的 数组的方案数. 1. 数组由 个整数构成 2. A与B不同当且仅当至少存在一个数 满足 .答案对 取模 数据范围: 显 ...
- Number()、parseInt()和parseFloat()的区别
JS中Number().parseInt()和parseFloat()的区别 三者的作用: Number(): 可以用于任何数据类型转换成数值: parseInt(): 函数可解析一个字符串,并返回一 ...
- PHP(javascript基础)
js浏览器的脚本语言js的基础语法和 . js Dom操作写法分类1.行内(内联)写在标签里面,以属性的形式表现,属性名是“事件属性名” 例如:<button onClick="js代 ...
- hadoop-1.0.1根目录下的jar包
- bug修复记录
telnet 网址 ping netaddr traceroute netaddr ,这是一个linux下的命令可以通过Vmmap观察程序运行时所需要的依赖库协议里面涉及到数组的, 一定要判断最大值 ...
- Fiddler (进阶)内置命令与断点
Fiddler 内置命令与断点 命令 对应请求项 介绍 示例 ? All 问号后边跟一个字符串,可以匹配出包含这个字符串的请求 ?google > Body 大于号后面跟一个数字,可以匹配出请求 ...
- Linux之cat的使用
基本介绍 工作原理 从标准输入读入要 cat 的文件列表,然后逐个打开,读入文件内容,再将内容输出到标准输出上. 使用场景 一次显示整个文件 从键盘创建一个文件 将几个文件合并为一个文件 将一个或多个 ...
- 012-docker-安装-fabric:1.4
一.准备工作 linux 版本.docker.docker-compose go安装且版本较新 uname -a docker --version docker-compose --version g ...
- python之wtforms组件
作用 生成 HTML 表单. form 表单验证. 基本使用 安装 pip3 install wtforms 示例 登录 from flask import Flask, render_templat ...
- oracle 新建用户后赋予的权限语句
grant create session,resource to itsys; grant create table to itsys;grant resource to itsys;grant cr ...