【发布时间】:2012-10-02 19:07:46
【问题描述】:
我正在使用 wxWidges (native C++) 重写应用程序。我确实有几个通过 Visual Studio 资源编辑器创建的用户定义的鼠标光标。资源编辑器为每个文件创建 MYCURSOR.CUR 之类的文件,其中包含位图和其他信息,并将一个条目添加到 app.rc 文件中,例如:
IDC_MYCURSOR CURSOR "MYCURSOR.CUR"
...并在生成的resource.h 中添加一行:
#define IDC_MYCURSOR 103
编译应用程序时,已编译资源采用二进制形式,成为app.exe 的组成部分。不使用wxWidgets框架时,可以调用:
HCURSOR hCur = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYCURSOR));
其中hInstance 是具有带有光标资源的可执行文件的应用程序的句柄(以编译的二进制形式,在app.exe 内)。
使用 wxWidgets,我可以创建 wxCursor 类的实例,并将带有光标的文件名传递给它——比如 wxCursor cursor(wxT("MYCURSOR.CUR"));——它可以工作。但是,必须找到MYCURSOR.CUR 文件(比如与app.exe 放在同一目录中)。换句话说,它忽略了附加到app.exe 的已编译资源。如果找不到该名称的文件,则不加载光标形状。
有没有什么方法——在 Windows 中——可以让我根据资源编号从资源中加载光标?
我知道,代码应该以可移植的方式编写,例如基于 Unix 的操作系统。是否有任何推荐的方法可以将 Windows 资源或MYCURSOR.CUR 文件转换为编译到或附加到生成的可执行文件的形式?
更新
我在 wxWidget 论坛上发现了 upCASE(2005 年 4 月)在 wxCursor from .rc [Win] 中的提示:
wxCursor( "#1", wxBITMAP_TYPE_CUR_RESOURCE );
我尝试将它与我的号码一起使用,它似乎可以工作,但我不知道为什么。然后我像这样改进它:
#define STR(value) #value
#define RES(value) wxT("#") wxT(STR(value))
...
wxCursor cur(RES(IDC_MYCURSOR), wxBITMAP_TYPE_CUR_RESOURCE);
我认为这很丑陋,而且可能不是正确的方法。无论如何,你能解释一下吗?
另外,查看c:\wxWidgets-2.9.4\src\msw\cursor.cpp 内部,我发现接受字符串参数的构造函数将其解释为文件名(至少参数名为filename)。代码...
switch ( kind )
{
case wxBITMAP_TYPE_CUR_RESOURCE:
hcursor = ::LoadCursor(wxGetInstance(), filename.t_str());
break;
...
建议LoadCursor() 以不用于堆栈 Windows 游标的方式使用(否则第一个参数应为 NULL)。 ::LoadCursor 将参数命名为 LPCTSTR lpCursorName 和 the doc says
要加载的游标资源的名称。或者,该参数可以由低位字中的资源标识符和高位字中的零组成。 MAKEINTRESOURCE 宏也可用于创建此值。
我也试过了
wxCursor cur(MAKEINTRESOURCE(IDC_MYCURSOR), wxBITMAP_TYPE_CUR_RESOURCE);
但它失败了,因为wxCursor 构造函数应用了字符串转换——参见上面的filename.t_str()。你能对此发表评论吗?
已解决(加上一些解释我遇到了什么......)
之前,我只通过 IDE 使用 Windows 应用程序资源,或者我只通过 app.rc 文件直接做一些小事情。在VZ's answer 和ravenspoint answer 的帮助下深入挖掘时,我可能会更好地理解它们最初的含义以及微软过去和后来所做的事情,以及我困惑的根源是什么。
首先,当您通过 Visual Studio IDE 创建一些资源(比如鼠标光标)时,它会自动获得一个数字标识(比如103)。该数字在resource.h 中自动捕获为#define IDC_MYCURSOR 103 - 即还给出了宏标识符。将光标的相关信息插入app.rc 时使用宏标识符,如下所示:
IDC_MYCURSOR CURSOR "MYCURSOR.CUR"
由于resource.h 包含在app.rc 中,它可能大致相当于
103 CURSOR "MYCURSOR.CUR"
并且资源编译器可能会将103 数字转换为#103 字符串或类似的东西。可能正因为如此,wxCursor("#103", wxBITMAP_TYPE_CUR_RESOURCE); 才有效。 103 通过resource.h 的间接性是我在试图理解 ravenpoint 的观点时感到困惑的根源:)
然而,使用app.rc 而不使用resource.h 和资源的字符串标识符可能是设计者的初衷。因此,写作
mycursor CURSOR "MYCURSOR.CUR"
意味着资源脚本文件编译器创建了可以直接在LoadCursor()函数或wxCursor("mycursor", ...);内部使用的"mycursor"字符串标识符。这是 VZ 推荐的方式,在指出的 wx 示例中可以找到。
我创建了自己的cursor.rc2,其中包含鼠标光标资源信息。然后将.rc2 包含到app.rc 文件中,以与其他资源信息相结合......并且它可以工作! :) 总结是:不要使用数字来标识资源。使用字符串。
再次感谢您的时间和经验, 彼得
【问题讨论】:
标签: windows visual-c++ wxwidgets