《Windows程序设计》(第五版)(美Charles Petzold著)
- 当Windows用户移动鼠标时,Windows系统会在显示设备上移动一个位图格式的小图标,称为“鼠标指针”,鼠标指针具有一个单像素精度的“热点”,热点在显示设备上指示了一个精确的位置。
- wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //默认的鼠标指针是斜向箭头,箭头的顶点即为热点。IDC_CROSS:指针 IDC_WAIT:沙漏
- 当鼠标经过窗口,或在窗口内被单击,即使该窗口是非活动窗口或不带输入焦点,窗口过程还是会收到鼠标消息
- 当鼠标经过窗口客户区时,窗口过程接收WM_MOUSEMOVE消息
- 当鼠标在窗口客户区内被按下或释放时,窗口过程接收如下消息:
- WM_LBUTTONDOWN(按下)、WM_LBUTTONUP(释放)、WM_LBUTTONDBLCLK(第二次按下按钮) //左键
- WM_MBUTTONDOWN(按下)、WM_MBUTTONUP(释放)、WM_MBUTTONDBLCLK(第二次按下按钮) //中键
- WM_RBUTTONDOWN(按下)、WM_RBUTTONUP(释放)、WM_RBUTTONDBLCLK(第二次按下按钮) //右键
- 参数lParam包含了鼠标的位置信息,低位字表示x坐标,高位字表示y坐标,它们都是相对于窗口客户区左上角的相对坐标。鼠标移经窗口的客户区时,Windows系统不会为鼠标经过的每个像素位置都产生WM_MOUSEMOVE消息。程序收到的WM_MOUSEMOVE消息个数取决于鼠标硬件和窗口过程处理鼠标移动消息的速度。如果消息队列中还有未经处理的WM_MOUSEMOVE消息,Windows就不会重复向消息队列中添加该消息。
- x = LOWORD(lParam)
- y = HIWORD(lParam)
- WM_LBUTTONDOWN和WM_LBUTTONUP可以不在一个窗口,如在一个窗口按下左键,然后移动到另一个窗口释放
- 即使鼠标位于窗口的客户区之外,窗口过程也有办法继续“捕获鼠标”,并继续接收鼠标消息
- 若正在显示一个系统模式消息框或系统模式对话框,则其它任何程序都不能接收鼠标消息
- if(wParam & MK_SHIFT) { if(wParam & MK_CONTROL{...} ...} 按下Shift+Ctrl组合键
- GetKeyState函数也能够返回鼠标按钮或Shift等键的状态,状态信息与正被处理的消息是完全同步的,在没有按下鼠标时,不能用GetKeyState函数。while(GetKeyState(VK_LBUTTON) >= 0);是错误的代码
- 如果想让窗口过程接收鼠标双击消息,那么在调用RegisterClass初始化窗口类结构时,必须在窗口风格字段中包含标识符CS_DBLCLKS: wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
- 如果窗口类型没有包含CS_DBLCLKS,那么当用户连续两次快速单击左键时,窗口过程接收的消息顺序为:WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDOWN WM_LBUTTONUP,如果包含,则接收消息为 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK WM_LBUTTONUP
- 窗口的非客户区包括标题栏、菜单和窗口滚动条。系统一般不需要用户处理非客户区鼠标消息,只需将这些消息发送给DefWindowProc,从而使Windows执行系统函数
- 非客户区的鼠标消息的标识符包含了字母"NC",表示“非客户”,如WM_NCMOUSEMOVE
- 非客户区鼠标消息的参数wParam表示非客户区鼠标移动或单击的位置,它的值被设定为一个以HT为首的标识符,其中HT表示“击中测试”。
- lParam包含的坐标都是屏幕坐标,此时显示区域左上角的x和y都是0
- 利用下面两个Windows函数,可以将屏幕坐标与客户区坐标相互转换:"非客户区击中测试"WM_NCHITTEST优先级高于其它所有客户区和非客户区鼠标消息。参数lParam包含鼠标位置的屏幕坐标x和y。参数wParam没有用到。Windows应用程序通常会把这个消息发送给DefWindowProc,然后Windows会利用WM_NCHITTEST消息来产生所有其它和鼠标位置相关的鼠标消息。对非客户区消息来说,DefWindowProc处理WM_NCHITTEST消息后返回一个可用于鼠标消息的wParam参数的值。如果返回了HITLIENT,则Windows会将屏幕坐标转换成客户区坐标,并产出一个客户区鼠标消息。
- ScreenToClient(hwnd,&pt)
- ClientToScreen(hwnd,&pt)
- 如果窗口过程包括下面几行语句:
1 case WM_NCHITTEST: 2 return (LRESULT) HTNOWHERE;
那么程序就能够阻止系统向窗口发送所有客户区和非客户区鼠标消息
- 若安装了鼠标,则显示计数初始值为0,否则为-1.只有显示计数为非负时,系统才显示鼠标指针。ShowCursor(TRUE):增加显示计数,ShowCursor(FALSE):减少显示计数
- GetCursorPos(&pt):获取指针位置 SetCursorPos(x,y)设置指针位置。 这里x,y都是屏幕坐标
- GetCursorPos返回的坐标值是鼠标当前的位置,参数lParam包含的是指产生消息的那一刻的鼠标位置
- SetCapture(hwnd);捕获鼠标 ReleaseCapture();释放鼠标
- WM_MOUSEWHEEL滚动的滚轮 lParam包含的坐标信息是相对于屏幕左上角的,wParam的低位字包含一些了标志。