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

理论:

和处理键盘输入一样,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函数来计算的。

Win32汇编学习(7):鼠标输入消息的更多相关文章

  1. 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...

  2. Win32汇编学习(4):绘制文本

    这次,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: "绘制"字符串 Windows 中的文本是一 ...

  3. Win32汇编学习(5):绘制文本2

    这次我们将学习有关文本的诸多属性如字体和颜色等. 理论: Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表蓝色.如果您想指定一种颜色就必须给该颜色赋相关的 RGB ...

  4. Win32汇编学习(1):基本概念

    背景知识 Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而 ...

  5. Win32汇编学习(6):键盘输入消息

    这次,我们将要学习WINDOWS程序是如何处理键盘消息的. 理论: 因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它.WINDOWS 将负责把击键消息送到具有输入焦点的那个应 ...

  6. win32 汇编学习(2):消息框

    这一次,我们将用汇编语言写一个 Windows 程序,程序运行时将弹出一个消息框并显示"你好,我的第一个Win32汇编程序". 理论知识 Windows 为编写应用程序提供了大量的 ...

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

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

  8. Win32汇编学习(3):简单的窗口

    这次我们将写一个 Windows 程序,它会在桌面显示一个标准的窗口,以此根据代码来学习如何创建一个简单的窗口. 理论: Windows 程序中,在写图形用户界面时需要调用大量的标准 Windows ...

  9. Win32汇编学习(11):对话框(2)

    我们将进一步学习对话框,探讨如何把对话框当成输入设备.如果您看了前一篇文章,那就会发现这次的例子只有少量的改动,就是把我们的对话框窗口附属到主窗口上.另外,我们还要学习通用对话框的用法. 理论: 把对 ...

随机推荐

  1. ConfuserEx壳

    前言: 这几天用Rolan的时候出现了点问题,然后发现了这个非常好用的工具居然只有几百k,打算逆向一下,然后发现了ConfuserEx壳 探索: Rolan是用C#写的,刚开始用EXEinfoPE打开 ...

  2. vector排序

    // VectorSort.cpp : Defines the entry point for the console application. // #include "stdafx.h& ...

  3. Linux在终端命令行模式下智能补全功能以及组合键

    linux命令行下也有很多热键(快捷键).先来看看tab键 1.如果想看看linux下以c开头的命令可直接在命令行下敲入c然后连续敲两次tab,再选择y,会显示所有以c开头的命令. 2.涉及到文件时, ...

  4. python的基础1

    1.换行需要多个引号,'''''' """"""Eg:print('''文能提笔安天下,# 武能上马定乾坤.# 心存谋略和人生,# 古今银熊 ...

  5. python re(正则表达式模块)学习

    一.简介 正则表达式本身是一种小型的.高度专业化的编程语言,而在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎 ...

  6. Java如何获取图片验证码保存

    举例网站:https://my.1hai.cn/Login/?url=http://www.1hai.cn/ 一.场景:出于安全性考虑,越来越多的Web平台登录都会增加图形验证码(图片),或者短信验证 ...

  7. 集合 & 深浅copy

    集合: 特点:集合是可变的数据类型,但他里面的元素必须是不可变的数据类型,无序,不可重复. 创建: set1 = set({1,2,3}) 或者直接创建set2 = {1,2,3} 集合的增删查: 增 ...

  8. Python静态方法(staticmethod)和类方法(classmthod)

    Python静态方法(staticmethod)和类方法(classmthod)翻了翻之前的笔记,也刚好看到一篇不错的blog,关于静态方法和类方法的,方便以后查阅,就写在这里了,废话不多说,直接上代 ...

  9. java框架之Struts2(1)-简介及入门

    简介 Struts2 是一个基于 MVC 设计模式的 Web 应用框架,它本质上相当于一个 servlet,在 MVC 设计模式中,Struts2 作为控制器 (Controller) 来建立模型与视 ...

  10. 8 . IO类-标准IO、文件IO、stringIO

    8.1 IO类 #include <iostream> //标准IO头文件  8.2 文件输入输出流 #include <fstream> //读写文件头文件 std::fst ...