Search code examples
windowsvisual-c++wxwidgets

wxWidgets on Windows: How to create wxCursor from the application resource number?


I am rewriting the application using wxWidges (native C++). I do have several user-defined mouse cursors created via the Visual Studio resource editor. The resource editor creates for each one the file like MYCURSOR.CUR with the bitmap and the other info, adds one entry to the app.rc file like:

IDC_MYCURSOR      CURSOR     "MYCURSOR.CUR"

... and adds one line to the generated resource.h like:

#define  IDC_MYCURSOR 103

When the application is compiled, the compiled resources take the binary form that becomes integral part of the app.exe. When the wxWidgets framework is not used, one can call:

HCURSOR hCur = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYCURSOR));

where hInstance is the handle to the application that has the executable with the cursor resource (in compiled binary form, here inside the app.exe).

With wxWidgets, I can create the instance of the wxCursor class, and pass it the name of the file with the cursor -- like wxCursor cursor(wxT("MYCURSOR.CUR")); -- and it works. However, the MYCURSOR.CUR file must be found (say placed in the same directory as the app.exe). In other words, it ignores the compiled resource attached to the app.exe. If the file of the name is not found, the cursor shape is not loaded.

Is there any way that--in Windows--would allow me to load the cursor from the resource, based on the resource number?

I understand, that the code should be written the way that is portable say to a Unix-based OS. Is there any recommended way to transform the Windows resource or the MYCURSOR.CUR file to the form that is compiled to or attached to the produced executable?

UPDATE

I have found at wxWidget discussion forum the hint in wxCursor from .rc [Win] by upCASE (April 2005):

wxCursor( "#1", wxBITMAP_TYPE_CUR_RESOURCE );

I tried to use it with my number and it seems to work, but I do not know why. Then I improved it like this:

#define STR(value) #value
#define RES(value) wxT("#") wxT(STR(value))
...
wxCursor cur(RES(IDC_MYCURSOR), wxBITMAP_TYPE_CUR_RESOURCE);

I consider that uggly and likely not to be the right way. Anyway, can you explain that?

Also, looking inside the c:\wxWidgets-2.9.4\src\msw\cursor.cpp, I have found that the constructor that takes the string argument interprets it as a filename (at least the argument is named filename). The code...

switch ( kind )
{
    case wxBITMAP_TYPE_CUR_RESOURCE:
        hcursor = ::LoadCursor(wxGetInstance(), filename.t_str());
        break;
...

suggests that the LoadCursor() is used the way that is not used for the stack Windows cursor (otherwise the first argument should be NULL). The ::LoadCursor names the argument as LPCTSTR lpCursorName, and the doc says that

The name of the cursor resource to be loaded. Alternatively, this parameter can consist of the resource identifier in the low-order word and zero in the high-order word. The MAKEINTRESOURCE macro can also be used to create this value.

I tried also the

wxCursor cur(MAKEINTRESOURCE(IDC_MYCURSOR), wxBITMAP_TYPE_CUR_RESOURCE);

but it fails because the wxCursor constructor applies the string conversion -- see the above filename.t_str(). Can you comment on this?

SOLVED (plus some explanation what I was confronted with...)

Earlier, I have worked with Windows application resources only via IDE, or I did only small things directly via an app.rc file. When digging deeper with the help of the VZ's answer and the ravenspoint answer, I may understand better what they initially meant and what Microsoft did in the past and later, and what was the source of my confusion.

Firstly, when you create some resource (say mouse cursor) via Visual Studio IDE, it is automatically given a numeric identification (say 103). The number is automatically captured in resource.h as #define IDC_MYCURSOR 103 -- i.e. given also the macro identifier. The macro identifier is used when the information about the cursor is inserted to the app.rc, like this:

IDC_MYCURSOR      CURSOR     "MYCURSOR.CUR"

As the resource.h is included into the app.rc, it is probably roughly equivalent to

103               CURSOR     "MYCURSOR.CUR"

and the resource compiler probably converts the 103 number to #103 string or something like that. Probably because of that, the wxCursor("#103", wxBITMAP_TYPE_CUR_RESOURCE); works. The indirection of the 103 via the resource.h was the source of my confusion when trying to understand ravenspoint's point :)

However, the usage of an app.rc without the resource.h and the string identifier of the resource was probably the initial intention of the designers. Thus, writing

mycursor          CURSOR     "MYCURSOR.CUR"

means that the resource-script-file compiler creates the "mycursor" string identifier that can be used directly inside the LoadCursor() function or the wxCursor("mycursor", ...);. This is the way recommended by VZ and found in the pointed out wx samples.

I have created my own cursor.rc2 that contains mouse-cursor resource information. The .rc2 is then included into the app.rc file to be combined with the other resource information... and it works! :) The summary is: Do not use numbers for identification of the resources. Use strings.

Thanks again for your time and experience, Petr


Solution

  • With a numeric ID you need to use a not really obvious wxCursor("103"). This is why with wxWidgets you'd typically use string names (like my_cursor in the answer above).

    Of course, you can also do

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