// handle WM_SETCURSOR in button class BOOL CMyButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg) { ::SetCursor(m_hMyCursor); return TRUE; }
当用户将鼠标指针移到按钮上时,鼠标不被捕获,Windows发送一个WM_SETCURSOR消息到按钮。从上面OnSetCursor的代码中可以看到,它传递一个参数是窗口句柄(pWnd)- 即鼠标指针所指的窗口,这里指的是按钮本身;OnSetCursor传递的第二个参数是nHitTest,这是一个鼠标点击测试代码(Mouse Hit-Test Codes),它以HTXXX开头,用于WM_NCHITTEST消息;OnSetCursor传递的第三个参数是触发事件的鼠标消息的消息ID-例如,WM_MOUSEMOVE。WM_SETCURSOR是专门用来设置鼠标指针的消息,当设置了鼠标指针以后,应该让它返回TRUE以防止Windows再作缺省处理。 WM_SETCURSOR的处理机制是这样的,如果有父窗口的话,缺省的窗口过程首先发送WM_SETCURSOR消息到父窗口,如果父窗口处理WM_SETCURSOR消息(即返回TRUE),则Windows不再作任何多余的事情,处理完消息便结束。如果父窗口不处理WM_SETCURSOR消息(即返回FALSE),Windows让子窗口来处理WM_SETCURSOR,如果子窗口也不做任何处理(返回FALSE),Windows使用全程光标指针,如果没有全程光标指针,则使用箭头指针。
如果你在程序中要是使用动态光标指针,你必须决定是在子窗口处理WM_SETCURSOR消息还是在父窗口中处理WM_SETCURSOR消息。两种方法各有利弊,根据具体情况而定。一般总是让对象决定它们自己的行为属性-也就是说最好在子窗口中做处理。本文中的子窗口即按钮。这就要派生一个新的按钮类,新的按钮类有自己的消息映射及其消息处理过程。可以使用类向导来产生新的按钮类,但那样要做的事情太多。如果你已经有自己的按钮类,那当然是在自己的按钮类中处理WM_SETCURSOR消息。如果没有自己的按钮类而又想偷懒的话,那就在对话框中处理WM_SETCURSOR消息得啦,只是不要向面向对象专家说是我告诉你这么做的。 本文附带一个简单的基于对话框的程序,MyCursor,这个例子程序示范了两种方法来改变光标指针。如果将鼠标移到按钮上(“OK”键和“Cancel”键),光标指针变为蓝色手指,它是通过在对话框中处理OnSetCursor实现的(参见代码),另外,如果将鼠标指针移到带下划线的超链接上,光标指针又变为另外一个Windows中常常使用的手指。它是通过在窗口子类(CStaticLink)中实现的。CStaticLink是一个通用的可重用类,在VC知识库的范例程序中经常用到,其中CStaticLink::OnSetCursor的大多数代码处理是从win32hlp.exe可执行程序中吸取手型指针,它们与本文有关光标设置的内容关系不大,我没有全部列出来,如果你对细节感兴趣,可以从本文的开始处下载范例程序......
最后祝大家编程愉快!