WEB开发网
开发学院软件开发VC 改变窗口中的光标形状 阅读

改变窗口中的光标形状

 2010-07-11 20:44:46 来源:WEB开发网   
核心提示:不管什么时候,当用户将鼠标移动到按钮上并且鼠标没有被捕获时,改变窗口中的光标形状(2),Windows 会发送一条WM_SETCURSOR消息给按钮,它传递一个窗口句柄——即鼠标指针指向的窗口,在发生冲突时程序员能够改变这个基本值,可以在一个特殊的头文件中规定这个值, 此时就是按钮本身;击中测试

不管什么时候,当用户将鼠标移动到按钮上并且鼠标没有被捕获时,Windows 会发送一条WM_SETCURSOR消息给按钮。它传递一个窗口句柄——即鼠标指针指向的窗口, 此时就是按钮本身;击中测试码——即在WM_NCHITTEST消息中使用的HTXXX码(见 Figure 1);和一个触发事件的消息ID,比如说它触发了WM_MOUSEMOVE事件。设置鼠标 光标的最佳机会就是在处理WM_SETCURSOR消息的时候。如果要这么做,你必须返回TRUE以阻止窗口默认的处理过程。

此时处理会如何进行呢?首先窗口默认的处理过程向父窗口(如果有的话)发送WM_SETCURSOR消息到父窗口。如果父窗口处理了WM_SETCURSOR消息(就是说它返回了TURE),Windows就不做什么了, 该消息就算处理完了。如果父窗口没有处理WM_SETCURSOR消息(返回FALSE),Windows就给子窗口一个处理这条消息的机会。假如子窗口也没有处理该消息(返回FALSE),Windows就使用全局光标,要是连全局光标也没有,则使用箭头光标。

这些意味着什么?这意味着在需要动态设置光标时,你要决定是在子窗口还是在父窗口处理WM_SETCURSOR消息。两个选择都可行,这取决于实际情况。一般来说,最好让对象决定自己的属性,这就是说最好在子窗口处理消息。本例中子窗口是指按钮。但这需要从CButton类继承一个新的按钮类,让它有自己的消息映射和其 它一些必要的属性,如果你是乐于使用 Class Wizard 的人(有没有人用它啊?),这意味着需要多敲几下键盘或多点几次鼠标。如果你已经具备了自己的按钮类,那我明确的告诉你在这个子类中处理WM_SETCURSOR消息。要是你没有自己的按钮类而且你 又是个懒人,那就在对话框里处理WM_SETCURSOR消息也行。不过千万不要告诉别的面向对象专家,是我要你这么干的!

Figure 2 按钮上设置的光标

我写了一个简单的基于对话框的应用程序,NoCursor,来举例说明这两种方法。如果你把鼠标移动到一个按钮上(OK或Cancel),光标变成蓝色的指示手指(见 Figure 2);该功能通过处理对话框类的OnSetCursor函数实现(见 Figure 3)。另外,当你把鼠标移动到带下划线的超级链接上时,光标变成另一种不同的指示手指。该功能是在子类CStaticLink里实现的(见 Figure 4)。CStaticLink是在我的专栏里经常出现的一个多用途超链接类(见 Figure 5)。CStaticLink::OnSetCursor函数中的大部分代码是处理如何从winhlp32.exe获得适合的手形光标资源,就光标设置而言这些代码无关 紧要,故省略。如果你对这些细节很感兴趣,可以象往常一样从本文顶部的链接下载全部代码。

Figure 4 超级链接上设置的光标

我获得一个含有对话框的库(当然也就包括一些资源ID)。当我在主程序中使用这个库时,库中的资源ID和主程序的资源ID发生了冲突。结果是,要显示库中的对话框时却弹出了主程序中的对话框。要怎样做才能避免冲突?难道要手工对库中的资源ID进行设置吗?

Hans Zwahlen

唉,这个问题没有特别令人满意的答案,只有一些曲线救国的办法。该问题的实质在于Windows中的每个资源必须从属于某个模块(EXE或DLL),而在每一个模块中,特定资源不能有相同的名称或ID。就DLL(动态链接库)而言不存在这样的问题,因为DLL本身就有和主程序不同的HINSTANCE句柄。但对静态链接库来说,所有资源在同一个EXE文件内共存,就像一个大家庭的成员共同生活在一起一样。当然,像家庭成员可能发生冲突一样,资源 也存在发生冲突的可能性。

MFC是如何解决这个问题的呢?它采用800磅重的大猩猩的方法,“我是800磅重的大猩猩,身强体壮,你们打不赢我,最好乖乖听我的。”据我所知MFC没有任何内置的对话框,但有一些通用的菜单项ID,像ID_FILE_OPEN。这些ID也被用作菜单项提示字符串的资源ID。所有MFC的ID值都比0xE000大。最好不要使用大于该值的ID,否则产生冲突就是你的问题。

这种方法对编写操作系统的人来说可能是适合的,但如果你只是一个努力赚钱养家糊口的人,当顾客抱怨你的ID和他的程序有冲突的时候,最好不要“嘴硬”, 你必须要想方设法解决这个问题,要不然怎么办?

我曾经用过的一个办法是:把库中所有资源ID规定为一个已初始化基本值的偏移量,在发生冲突时程序员能够改变这个基本值。可以在一个特殊的头文件中规定这个值,然后程序员必须同时在主程序文件和资源文件中包含它。

// 在主应用程序rc文件
#include "libres.h" // ID 标识符
#include "libres.rc" // 资源

Tags:改变 窗口 光标

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接