WM_LBUTTONDOWN消息
关于WM ERASEBKGND和WM AINT的深刻理解

一直以来,对于WM_PAINT和WM_ERASEBKGND消息不是很清楚,从书上和网上找了很多资料,大体上有以下几点说法:1>WM_PAINT先产生,WM_ERASEBKGND后产生2.WM_PAINT产生后,在调用BeginPaint时hdc = BeginPaint(hWnd, &ps);如果ps.fErase为true,则BeginPaint会产生WM_ERASEBKGND消息3.BeginPaint函数用来擦除窗口背景4.WM_ERASEBKGND用来绘制背景经过调试、分析,发现上面的说法并不正确。
以下是一些测试代码,代码后面附上一些分析。
最后总结出几点,可以解释程序中出现的所有关于窗口重绘的问题。
如有不正确的地方,大家可以指正。
为了说明问题,在此不说WM_NCPAINT消息(非客户区消息),只说WM_ERASEBKGND消息和客户区的WM_PAINT消息//此段代码摘自vc6应用程序向导自动生成的代码,并添加了一些测试代码LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;TCHAR szHello[MAX_LOADSTRING];LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);switch (message){case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);// Parse the menu selections:switch (wmId){case IDM_ABOUT:DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_ERASEBKGND: //如果处理了这个消息,则默认消息处理函数不会调用,背景就不会绘制{static int iCount=0;char ch[MAX_PATH];sprintf(ch,"%d ---------WM_ERASEBKGND\n",iCount);//这个函数需要包含#include<stdio.h>OutputDebugString(ch); //调试时便于观察iCount ;break;}case WM_PAINT:{OutputDebugString(" -------------WM_PAINT\n");hdc = BeginPaint(hWnd, &ps); //使无效区域变得有效,并填充ps结构// TODO: Add any drawing code here...//绘制一个蓝色椭圆,ps.rcPaint保存了客户区矩形HBRUSH hbrush=::CreateSolidBrush(RGB(0,0,255));::SelectObject(hdc,hbrush);::Ellipse(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.r cPaint.bottom);::DeleteObject(hbrush);EndPaint(hWnd, &ps);break;}case WM_LBUTTONDOWN: //调用DefWindowProc擦除客户区背景{HDC hdc;hdc=::GetDC(hWnd);WPARAM w=(WPARAM)hdc;LPARAM l=0;DefWindowProc(hWnd, WM_ERASEBKGND, w, l);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}先说一下程序运行时发现的一些现象:1.上面的代码:如果添加了WM_ERASEBKGND消息,里面什么也不做,如下case WM_ERASEBKGND:break;则当程序运行时,如果收到WM_ERASEBKGND消息,则这个switch-case结构中就不会执行默认消息处理函数DefWindowProc,运行时发现,窗口的背景就没有了,即背景为空。
Win32教程7-处理鼠标输入消息

| 首页 >> 编程详解 >> Iczelion的Win32汇编教程 | Win32ASM 论坛 | 联系站长 |
Win32教程7-处理鼠标输入消息
作者:Lxx翻译·发布日期:2000-7-1·阅读次数:2988
【在这里下载本文的源代码】
本课中我们将学习如何在我们的窗口过程函数中处理鼠标按键消息。示例程序演示了如何等待左键按下消息,我们将在按下的位置显示一个字符串。
.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
【关闭本窗口】
Copyright? 1998-2008 by 罗云彬,All Rights Reserved,所有文章版权各属于其作者,如转载请务必注明作者!
由于lParam是一个32位长的数,其中高、底16位分别包括了x、y坐标所以我们做一些小处理,以便保存它们。
shr eax,16
mov hitpoint.y,eax
保存完坐标后我们设标志MouseClick为TRUE,这是在处理WM_PAINT时用来判断是否有鼠标左键按下消息。然后我们调用InvalidateRect()函数迫使WINDOWS重新绘制客户区。
关于MFC的有些知识

关于MFC的有些知识实验⼀1、在VC++中,⼯程与各种源⽂件之间是什么关系?解答:⼯程的实质是⼀些相互关联的源⽂件的集合,可以把项⽬理解成⼀个⼯作任务, 开发环境中,⼯程包含在⼯作区间中,⼀个⼯作区可以管理多个⼯程2、⼀个VC++⼯程下会有3个⽂件夹,这3个⽂件夹分别是什么?以.cpp为后缀的⽂件会添加到哪个⽂件夹中?以.h为后缀⽂件会添加到哪个⽂件夹中?解答:分别是head Files ,Sourse Files, Resourse Files ,.cpp放在Sourse ⽂件⾥⾯,.h放在Head Files⽂件⾥3,以win32 console application⼯程为例,简述⼯程的建⽴,⽂件的添加,⼯程的编译和链接及⼯程的执⾏过程。
解答:这个就是win32 console application⼯程的实例验证过程。
实验⼆1.简述Windows应⽤程序的特点。
解答:⼀.事件驱动的程序设计它是⼀种“被动”式程序设计⽅法,程序开始运⾏时,处于等待⽤户输⼊事件状态,然后取得事件并作出相应反应,处理完毕⼜返回并处于等待事件状态。
⼆. 消息循环与输⼊消息是⼀种报告有关事件发⽣的通知。
· 事件驱动是靠消息循环机制来实现的。
· Windows应⽤程序的消息来源有以下四种:(1)输⼊消息(2)控制消息(3)系统消息(4)⽤户消息三. 图形输出Windows程序的所有输出都是图形,字符也被作为图形来处理。
· GDI提供两种基本服务:创建图形输出和存储图象。
· 绘图函数分为三类:⼀是⽂字输出;⼆是⽮量图形函数,⽤于画线、圆等⼏何图形;三是光栅(位图)图形函数,⽤于绘制位图。
四. ⽤户界⾯对象⽤户界⾯对象:窗⼝边框系统菜单框标题栏菜单栏⼯具条客户区垂直滚动条和⽔平滚动条状态栏图标光标插⼊符对话框控件消息框五.资源共享· 常见的资源包括:设备上下⽂,画刷,画笔,字体,对话框控制,对话框,图标,定时器,插⼊符号,通信端⼝,电话线等。
无标题栏窗口移动方法种种

无标题栏窗口移动方法种种首先,看看在正常情况下系统是怎样来移动程序窗口的。
当使用者在程序窗口标题栏区域(非工作区)内,按下鼠标左键时将会发生下列事情:◆系统向该窗口过程函数发送WM_NCLBUTTONDOWN消息。
◆WM_NCLBUTTONDOWN消息最终将传送到窗口过程函数中的DefWindowProc()函数中去。
◆DefWindowProc()函数将根据鼠标左键按下并移动,以及HTCAPTION标识所表示鼠标按下时的位置诸多信息,来执行该消息的缺省动作即窗口随同鼠标光标一起移动的操作。
下面作为练习来测试一下,首先在窗口回调函数(即窗口过程函数)中设置下列语句:case WM_NCLBUTTONDOWNreturn 0;然后,同样是在窗口标题栏内按住鼠标左键并移动鼠标,但此时窗口却并不随同鼠标一起移动了,这是怎么回事?这是因为上述语句中设有“return 0”语句的缘故。
该语句使得WM_NCLBUTTONDOWN消息未能传递到DefWindowProc()函数,就在窗口过程函数中提前返回了,当然移动窗口的操作就无从进行了。
这也从反面印证了一个事实,那就是,最后完成移动窗口的操作将是由DefWindowProc()函数来完成的。
通过上面的分析可以勾划出这样一个操作过程:即用户在窗口标题栏内按下鼠标左键→系统发送WM_NCLBUTTONDOWN消息→DefWindowProc()函数接收消息→用户移动鼠标→DefWindowProc()函数执行窗口随同鼠标一起移动的操作。
由此得出一个结论,那就是要想实现移动窗口的操作,必须具备两个条件:一是要按下鼠标左键并移动(DefWindowProc()函数将检测这个条件);二是在按下鼠标左键时能发送WM_NCLBUTTONDOWN消息并返回HTCAPTION标识。
下面就根据以上的分析,在没有窗口标题栏的情况下,采取骗取DefWindowProc()函数的方式,来实现对无标题栏窗口实体的移动操作。
WM_LBUTTONDOWN消息

WM_LBUTTONDOWN消息问:一个SDI程序中在视里,消息WM_LBUTTONDOWN将视中的内容作一下翻转,但问题是当我快速按鼠标时总是不能得到正确的WM_LBUTTONDOWN消息.(从spy 中看到)我认为问题可能出在重画代码太慢,但我放入了一个空状态,依然没有解决。
难道说为一个标准输入设备,我必须实时检测鼠标?答:1)你能保证那些快速击打没有解释成双击?2)当你快速单击鼠标时,你会得到如下消息WM_LBUTTONDOWN,WM_LBUTTONUP, WM_LBUTTONDBLCLICK, WM_LBUTTONDOWN, WM_LBUTTONUP,WM_LBUTTONDBLCLICK. (这是4次单击的结果).要么你进入控制面板将鼠标的双击调至最快,要么你就不要击打的这么快.保存工具条菜单有bug吗?使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR);你的工具条需要包括id,而不是象默认的工具条那样.编译错误问:我编译程序时遇上下面这个错误:cannot convert from void(unsigned long) to void(_cdecl*)(unsigned long) 答:在你的函数声明改成如下形式:extern 'C'{....}编译消息问:我在编译时遇上这种提示消息:error C2258: illegal pure syntax, must be '= 0'error C2252: 'THIS_FILE' : pure specifier can only be specified for functions错误周围的代码是这样的:#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif到底怎么回事?答:遇到这种情形通常是在包含文件中有一个语法错误,象语句后面少了一个;号.只是猜测一下,察看一下#include的文件,可能里面的括号或其他并不搭配.所以可能将 "static char THIS_FILE[]=__FILE__;"之类的语句理解为类中的成员函数声明我不能确定下面会解决这个问题,但换了我是你,我会检查在include文件中是否有")","}"搭配不正确或缺少了";".这个代码块是否是全局的.重定义__FILE__是否会产生错误?。
MFC的消息处理模式

第七章MFC的消息处理模式一消息与输入焦点Windows编程与其它类型编程的最大不同之处在于使用消息机制,所有的Windows 应用程序都是消息驱动的,消息机制是Windows应用程序的核心。
在Windows中发生的一切都可以用消息来表示,消息用于告诉操作系统发生了什么。
在Windows中,所有的消息都有一个特定的名字,实质上是用不同的整数来标记。
Windows系统预定义了许多消息,每个消息都拥有一个宏定义,即用形象的字符串来标识消息,一系列#define 语句将消息与特定数值联系起来,可以在头文件WinUser.h中找到这些宏定义,例如#define WM_PAINT 120可以在程序中通过消息名“WM_PAINT”来访问它。
其他消息如:#define WM_MOUSEMOVE 0x0200#define WM_LBUTTONDOWN 0x0201#define WM_LBUTTONUP 0x0202#define WM_LBUTTONDBLCLK 0x0203#define WM_RBUTTONDOWN 0x0204#define WM_RBUTTONUP 0x0205#define WM_RBUTTONDBLCLK 0x0206#define WM_MBUTTONDOWN 0x0207#define WM_MBUTTONUP 0x0208#define WM_MBUTTONDBLCLK 0x0209消息是由消息的名称(UINT)和两个参数(WPARAM, LPARAM)组成。
消息的参数中包含有重要的信息。
例如对鼠标消息而言,LPARAM中一般包含鼠标的位置信息,而WPARAM参数中包含了发生该消息时,SHIFT、CTRL等键的状态信息,对于不同的消息类型来说,两个参数也都相应地具有明确意义。
Windows是一个以消息为导向的系统,应用程序只能被动地等待消息的发生,每当键盘上有个键被按下,系统就会发出一个按键消息给窗口,告诉它某个键被按下去了,只要鼠标移动一下,系统也会发出相应的消息,并把鼠标的坐标信息传给窗口。
05鼠标消息测试

鼠标消息测试当鼠标在窗口的客户区发生落下、弹起、双击、移动等操作时,窗口会收到对应的客户区鼠标消息,按照用户操作的鼠标键:左键(Left)、中键(Middle)、右键(Right)与鼠标动作:落下这些消息的参数都是相同的:wParam:表示当产生鼠标消息时对应的鼠标键与键盘的Ctrl、Alt、Shift键的状态,可以通过与下表中的系统预定义宏做按位与运算测试键的状态;Value of wParam. Indicates whether various virtual keys are down.This parameter can be any combination of the following values: 值English DescriptionMK_CONTROL Set if the ctrl key is down.MK_LBUTTON Set if the left mouse button is down.MK_MBUTTON Set if the middle mouse button is down.MK_RBUTTON Set if the right mouse button is down.MK_SHIFT Set if the shift key is down.lParam:存储产生鼠标时,以窗口客户区坐标表示鼠标的位置信息,可以通过以下带参的宏等到。
xPos = LOWORD(lParam); // 水平坐标yPos = HIWORD(lParam); // 垂直坐标实验内容1使用鼠标的左键在窗口的客户绘制线段分析:以鼠标落下时的位置为起点(用POINT类型的结构体变量ptStart存储),弹起的位置为终点(用POINT类型的结构体变量ptEnd存储)绘制线段,由于这是两个消息,如果用局部自动变量存储,则在鼠标弹起变量ptStart已经被重新初始化了,因此采用局部自动变量存储;1、新建项目MouseTest;2、在窗口过程的变量定义部分添加以下代码:static POINT ptStart,ptEnd;3、在窗口函数的消息处理部分增加以下代码以处理鼠标左键落下与弹起消息:case WM_LBUTTONDOWN://使用ptStart记录鼠标落下的位置ptStart.x=LOWORD(lParam);ptStart.y=HIWORD(lParam);break;case WM_LBUTTONUP: //使用ptEnd记录鼠标弹起的位置hdc=GetDC(hWnd);ptEnd.x=LOWORD(lParam);ptEnd.y=HIWORD(lParam);MoveToEx(hdc,ptStart.x,ptStart.y,NULL);LineTo(hdc,ptEnd.x,ptEnd.y);ReleaseDC(hWnd,hdc);break;4、编译运行程序;5、实验结果分析:程序运行后当压下鼠标落下并移动一段距离后松开,确实绘制出一条从起点到终点的线段,但程序有以下缺点:在鼠标压下到松开的过程中看不到线段,直到松开鼠标才绘制出线段,最好是当鼠标移动时能够看到一个线段随着鼠标指针的移动同时移动;6、我们考虑在鼠标移动时从起点到鼠标指针的当前点绘制一条线段,因此增加以下代码case WM_MOUSEMOVE:hdc=GetDC(hWnd);ptEnd.x=LOWORD(lParam);ptEnd.y=HIWORD(lParam);MoveToEx(hdc,ptStart.x,ptStart.y,NULL);LineTo(hdc,ptEnd.x,ptEnd.y);ReleaseDC(hWnd,hdc);Break;7、编译运行,发现随着鼠标指针的移动,从窗口的左上角到鼠标的当前位置绘制了很多线段;通过分析发现当鼠标左键没有压下时是不用绘制线段的,因此在窗口函数的变量声明部分增加一个静态变量bMouseDown来记录鼠标当前状态,代码如下:BOOL bMouseDown=FALSE8、在WM_LBUTTONDOWN中增加以下代码:bMouseDown=TRUE;9、在WM_LBUTTONUP中增加以下代码:bMouseDown=FALSE;10、将WM_MOUSEMOVE处理程序放到一个条件语句中,修改后的代码如下:case WM_MOUSEMOVE:if(bMouseDown) {hdc=GetDC(hWnd);ptEnd.x=LOWORD(lParam);ptEnd.y=HIWORD(lParam);MoveToEx(hdc,ptStart.x,ptStart.y,NULL);LineTo(hdc,ptEnd.x,ptEnd.y);ReleaseDC(hWnd,hdc);}Break;11、编译运行,发现当鼠标左键压下后,随着鼠标指针的移动,从鼠标落下的位置到鼠标的当前位置绘制了很多线段;通过分析可知移动的过程中每次从起点到终点绘制线段前没有擦除上一次绘制的线段;12、Windows绘图模式介绍及图形动画效果的实现当使用画笔在窗口绘图时,实际上是在将画笔的像素颜色和目标显示表面的像素颜色按位进行布尔运算;常见的操作有模式描述R2_BLACK 点总是绘出黑色.R2_COPYPEN 点是画笔的颜色R2_NOT 点是原来的颜色按位取反R2_WHITE 点总是绘出白色.R2_XORPEN 点的颜色是画笔颜色与原来颜色的异或操作结果由于一个变量做两次非运算还是原来的值,因此常用R2_NOT模式进行图形的绘值与擦除以实现动画效果。
WM_LBUTTONDOWN,WM_LBUTTONUP

WM_LBUTTONDOWN,WM_LBUTTONUPWM_LBUTTONDOWN //⿏标左键按下消息WM_LBUTTONUP //⿏标左键弹起消息参数和按下⼀样当⽤户在窗⼝的客户区域中按住⿏标左键时,会发布WM_LBUTTONDOWN消息。
如果未捕获⿏标,则该消息会发布到光标下⽅的窗⼝中。
否则,消息将发布到已捕获⿏标的窗⼝。
WM_LBUTTONDOWNfwKeys = wParam; //键标志xPos = LOWORD(lParam); //光标的⽔平位置yPos = HIWORD(lParam); //光标的垂直位置参数【fwKeys】在【wParam中】标识按下的键值。
此参数可以是以下值的任意组合:值描述MK_CONTROL 标识CTRL键按下。
MK_LBUTTON 标识左键按下.MK_MBUTTON 标识中键按下。
MK_RBUTTON 标识右键按下。
MK_SHIFT 标识SHIFT键按下.【XPOS】【lParam的】的低位字节的值。
指定光标的x坐标。
坐标相对于客户区域的左上⾓。
【yPos】【lParam的】的⾼字节的值。
指定光标的y坐标。
坐标相对于客户区域的左上⾓。
返回值如果应⽤程序处理此消息,则应返回零。
备注应⽤程序可以使⽤MAKEPOINTS宏将【lParam的】参数转换为POINTS结构。
实例:case WM_LBUTTONDOWN:return OnLButtonDown(hWnd,(UINT)wParam, POINT{ LOWORD(lParam),HIWORD(lParam) });LRESULT OnLButtonDown(HWND hWnd,UINT nFlags, POINT pos){if (pos.x >= m_splitterPos - 10 && pos.x <= m_splitterPos + 10){m_IsSplit = TRUE; //标识可以拖拽/*SetCursor(m_hCursor);SetCapture(hWnd);*/}return0;}LRESULT OnLButtonUp(HWND hWnd, UINT nFlags, POINT pos){if (m_IsSplit){m_IsSplit = FALSE; //标识不可拖拽ReleaseCapture();}return0;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WM_LBUTTONDOWN消息
问:一个SDI程序中在视里,消息WM_LBUTTONDOWN将视中的内容作一下翻转,但问题是当我快速按鼠标时总是不能得到正确的WM_LBUTTONDOWN消息.(从spy 中看到)
我认为问题可能出在重画代码太慢,但我放入了一个空状态,依然没有解决。
难道说为一个标准输入设备,我必须实时检测鼠标?
答:1)你能保证那些快速击打没有解释成双击?
2)当你快速单击鼠标时,你会得到如下消息WM_LBUTTONDOWN,
WM_LBUTTONUP, WM_LBUTTONDBLCLICK, WM_LBUTTONDOWN, WM_LBUTTONUP,
WM_LBUTTONDBLCLICK. (这是4次单击的结果).要么你进入控制面板将鼠标的
双击调至最快,要么你就不要击打的这么快.
保存工具条菜单有bug吗?
使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,
重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会
出现在该位置,这是什么原因?
你试试这个
PToolBar->Create(this,...,ID_MYTOOLBAR);
你的工具条需要包括id,而不是象默认的工具条那样.
编译错误
问:我编译程序时遇上下面这个错误:
cannot convert from void(unsigned long) to void(_cdecl*)(unsigned long) 答:在你的函数声明改成如下形式:
extern 'C'
{
....
}
编译消息
问:我在编译时遇上这种提示消息:
error C2258: illegal pure syntax, must be '= 0'
error C2252: 'THIS_FILE' : pure specifier can only be specified for functions
错误周围的代码是这样的:
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
到底怎么回事?
答:
遇到这种情形通常是在包含文件中有一个语法错误,象语句后面少了一个;号.
只是猜测一下,察看一下#include的文件,可能里面的括号或其他并不搭配.所以可能将 "static char THIS_FILE[]=__FILE__;"之类的语句理解为类中的成员函数声明
我不能确定下面会解决这个问题,但换了我是你,我会
检查在include文件中是否有")","}"搭配不正确或缺少了";".
这个代码块是否是全局的.
重定义__FILE__是否会产生错误?。