鼠标
见钱眼开 于 2005-5-3
当用户移动鼠标时,Windows在屏幕上显示一个“鼠标光标”的小位图。每一个光标都有一个指向屏幕精确位置的单象素的“热点”。一般提到鼠标光标在屏幕上的位置时,指的就是热点的位置。例如,箭头光标的热点在顶端,十字光标的热点在交叉点处等等。
定义窗口类时可以指定该类窗口的缺省光标,例如:
Wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //为该类窗口指定一个箭头光标
也可以在窗口过程处理WM_MOUSEMOVE消息期间通过SetCursor函数指定光标形状。
Windows只把键盘消息发送给拥有输入焦点的窗口。鼠标消息不同,只要鼠标跨越窗口或在某窗口中按下鼠标键,那么窗口过程就可以接收到鼠标消息,不管该窗口是否活动或拥有输入焦点。
Windows共定义了21种鼠标消息,其中11种与客户区无关。鼠标移动经过窗口客户区时,窗口过程收到WM_MOUSEMOVE消息;鼠标在窗口客户区按下或释放键时,窗口过程收到如下表所示的消息。
键 | 按下 | 释放 | 双击键 |
左 | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK |
中 | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK |
右 | WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK |
对于这些消息,lParam参数包含客户区内的鼠标位置,低16位为x坐标,高16位为y坐标;wParam参数代表鼠标键及Shift、Ctrl键的状态。只有包含CS_DBCLICKS风格的窗口类创建的窗口才能接收鼠标双击消息。
当鼠标移动经过窗口客户区时,Windows并不为鼠标的每个象素位置产生一个WM_MOUSEMOVE消息。应用程序接收到WM_MOUSEMOVE消息的次数依赖于鼠标硬件和其窗口过程处理鼠标移动消息的速度。
可能会出现这样一种情况:一个窗口的窗口过程只接收到WM_LBUTTONDOWN消息
,而没有接收到WM_LBUTTONUP消息。原因是鼠标在一个窗口按下,然后移动到另一个窗口释放。避免这种情况出现的办法是调用SetCapture函数,该函数可以使窗口捕获鼠标,并且连续不断的接收鼠标消息。有一个例外是,在显示模态(Modal)窗口时,其他窗口将不可能接收到鼠标消息。
双击鼠标键是在短时间内单击两次。如果该窗口可以接收鼠标双击消息,那么双击鼠标左键后接收的一系列鼠标消息将是:WM_LBUTTONDOWN、WM_LBUTTONUP、WM_LBUTTONDBLCLK、WM_LBUTTONUP。
如果鼠标动作在窗口的非客户区内,那么窗口过程将接收到一个“非客户区”鼠标消息。消息中含有字母“NC”的表示非客户区消息,一般由Windows负责处理,见下表。
键 | 按下 | 释放 | 双击 |
左 | WM_NCLBUTTONDOWN | WM_NCLBUTTONUP | WM_NCLBUTTONDBLCLK |
中 | WM_NCMBUTTONDOWN | WM_NCMBUTTONUP | WM_NCMBUTTONDBLCLK |
右 | WM_NCRBUTTONDOWN | WM_NCRBUTTONUP | WM_NCRBUTTONDBLCLK |
非客户区鼠标消息中的wParam参数代表移动或单击鼠标键所在的非客户区位置;lParam参数代表屏幕内的,而非客户区的鼠标位置,低16位为x坐标,高16位为y坐标;可以通过ScreenToClient(hwnd,&pt)和ClientToScreen(hwnd,&pt)函数转换客户区和屏幕坐标。
最后一个鼠标消息是客户区非命中测试消息WM_NCHITTEST。该消息在其他所有客户区和非客户区鼠标消息之前触发。lParam参数表示鼠标的屏幕位置,wParam参数未使用。WM_NCHITTEST消息通常由DefWindowProc函数处理并返回一个值,指明鼠标所在的窗口区域。如果位于非客户区,返回值将成为非客户区鼠标消息wParam参数的值;如果位于客户区,不处理返回值,只是把屏幕坐标转换为客户区坐标并产生客户区鼠标消息。
因此,Windows是用WM_NCHITTEST消息产生所有其他鼠标消息。
即使没有安装鼠标,Windows依然可以显示一个光标。Windows为光标设置了一个“显示技术”。安装鼠标后显示计数初始化为0;否则为-1。显示计数只有为正时才显示光标。因此在没有安装光标的情况下要显示光标,可以调用ShowCursor(TRUE)函数;隐藏光标则调用ShowCursor(FALSE)函数。
GetCursorPos和SetCursorPos函数分别用于返回和设置屏幕鼠标位置。
如果鼠标被捕获,而鼠标键当前未按下,且鼠标光标移到了另一个窗口上,那么将不是由捕获鼠标的窗口而是光标下面的窗口来接收窗口消息。这是为了防止程序捕获鼠标后未释放造成系统的混乱。因此,只有鼠标在客户区按下时才会捕获鼠标;当键释放时,才释放鼠标捕获。
转动鼠标滚轮导致Windows在有输入焦点的窗口(不是鼠标光标下的窗口)产生WM_MOUSEWHEEL消息。lParam参数代表相对于屏幕的鼠标位置,wParam参数低16位用于标识鼠标键和Shift与Ctrl键的状态;高16位用于表示一个delta值,该值缺省是120或-120。值120或-120表明文档分别向上或向下滚动三行。如果delta值为40或-40,表示文档分别向上或向下滚动一行。