【问题标题】:wxWidgets on Windows: How to create wxCursor from the application resource number?Windows 上的 wxWidgets:如何从应用程序资源编号创建 wxCursor?
【发布时间】: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 lpCursorNamethe doc says

要加载的游标资源的名称。或者,该参数可以由低位字中的资源标识符和高位字中的零组成。 MAKEINTRESOURCE 宏也可用于创建此值。

我也试过了

wxCursor cur(MAKEINTRESOURCE(IDC_MYCURSOR), wxBITMAP_TYPE_CUR_RESOURCE);

但它失败了,因为wxCursor 构造函数应用了字符串转换——参见上面的filename.t_str()。你能对此发表评论吗?

已解决(加上一些解释我遇到了什么......)

之前,我只通过 IDE 使用 Windows 应用程序资源,或者我只通过 app.rc 文件直接做一些小事情。在VZ's answerravenspoint 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


    【解决方案1】:

    对于数字 ID,您需要使用不太明显的 wxCursor("103")。这就是为什么使用 wxWidgets 你通常会使用字符串名称(如上面答案中的my_cursor)。

    当然,你也可以这样做

    #include <wx/cpp.h>
    
    wxCursor cursor(wxSTRINGIZE(IDC_CURSOR));
    

    【讨论】:

    • 谢谢,瓦迪姆! (刚刚发布了与类似的盲目移动的更新。)所以,额外的 # 是不必要的。我正处于应用程序重写过程的最开始,我想从一开始就很好地重写它。那么……有没有类似“使用已经存在的resource.h重写时该怎么做”的文章?我应该按照您显示的方式使用wxSTRINGIZE,还是应该手动对resource.h 进行字符串化以避免使用wxSTRINGIZE?如果my_cursor CURSOR "mycursor.cur" 中的my_cursor 是字符串,资源编译器会高兴吗?
    • 刚试过,但是#必须在字符串化的数字前面使用(如wxCursor cur("#" wxSTRINGIZE(IDC_CURSOR));。否则不起作用。
    • 哎呀,对不起,你是对的,整数资源的字符串形式确实是“#103”,抱歉忘记了这个“#”。如果您这样做,您可能应该定义自己的宏#define MAKE_IDC(name) "#" wxSTRINGIZE(IDC_ ## name)(我已经将“IDC_”前缀移出以避免重复)。否则,您确实可以像在 .rc 文件中一样使用“my_cursor”,然后简单地将其用作 wxCursor ctor 中的字符串。除非您有很多光标(和/或位图、图标等)要更改,否则我会这样做。
    • 非常感谢,祝您有美好的一天。
    • 我不知道如何解释这个 MSDN 页面,但您绝对可以使用字符串作为资源标识符。在资源编辑器中打开任何 wxWidgets 示例,您将看到游标在“已编译”资源文件中被称为“WXCURSOR_BLANK”等等。另外,请查看 MSDN 中的LoadCursor() 文档,它的第二个参数是字符串,而不是数字,并且实际上只能使用可怕的 MAKEINTRESOURCE() hack 将数字传入其中。
    【解决方案2】:

    这不行吗?

    在资源文件中

    my_cursor CURSOR "mycursor.cur"
    

    在代码中

    wxCursor(my_cursor)
    

    【讨论】:

    • 我明天试试,但我怀疑。原因是my_cursor 是整数值的宏名称。没有任何东西可以将"my_cursor" 字符串转换为my_cursor 整数(在问题中称为IDC_MYCURSOR)。
    • 它也不起作用。原因是它导致void wxCursor::InitFromStock(wxStockCursor idCursor) 并且它只接受股票游标wxCURSOR_HAND 等。 InitFromStock 在静态结构 StdCursor 内部定义标准游标的初始化数组。该数字用作数组的索引。超出范围时,将报告 invalid cursor id in wxCursor() ctor
    • 再次感谢。我终于对资源进行了足够深入的挖掘。我将更新问题以总结我的经验。
    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    相关资源
    最近更新 更多