Jaberwocky
Jaberwocky

Reputation: 61

WinAPI - Loading Ressources from a DLL

I'm developing an applicaion for Windows 7 with VisualStudio2017. This application wants to have special cursors which are loaded from a DLL. So first I created a DLL and added the following .rc file:

BM_CURSOR_GRAB          CURSOR               "./grab.cur"
BM_CURSOR_GRABBING      CURSOR               "./grabbing.cur"

BM_CURSOR_GRAB and BM_CURSOR_GRABBING are defined in a header file as:

#define BM_CURSOR_GRAB     100
#define BM_CURSOR_GRABBING 101

I compile the DLL - that works and check it with ResourceEditor.exe My resources are included:

Picture from the Resource Editor

Now the "non working" part starts. My application wants to load the cursor, but FindResource doesn't find it. Here is my code:

HMODULE dll    = LoadLibrary("BenjaMiniRessources.dll");
HRSRC   hRes   = FindResource(dll, MAKEINTRESOURCE(100), RT_CURSOR);
DWORD   dwSize = SizeofResource(dll,hRes);
HGLOBAL hMem   = LoadResource(dll, hRes);
LPBYTE  pBytes = (LPBYTE)LockResource(hMem);

Cursor = CreateIconFromResource(pBytes, dwSize, false, 0x00030000);

What am I doing wrong?

Upvotes: 1

Views: 1316

Answers (3)

RbMm
RbMm

Reputation: 33804

when you include BM_CURSOR_GRAB CURSOR "./grab.cur" line to rc file, in generated PE will be (BM_CURSOR_GRAB, RT_GROUP_CURSOR) resource. so type will be RT_GROUP_CURSOR but not RT_CURSOR.

then you need call LookupIconIdFromDirectoryEx function for get name (id) of cursor that best fits the specified size.

after this you need again load resource - already RT_CURSOR with id returned from LookupIconIdFromDirectoryEx.

and finally use it in call CreateIconFromResourceEx.

but however, more simply call LoadImage with IMAGE_CURSOR resource type.

(HCURSOR)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB), IMAGE_CURSOR, 
            0, 0, 0);

for example, for use actual resource size. or is you want use default system cursor size:

(HCURSOR)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB), IMAGE_CURSOR, 
                GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), 0);

or

(HCURSOR)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB), IMAGE_CURSOR, 
                    0, 0, LR_DEFAULTSIZE);

or simply

LoadCursorW(hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB));

last call internal call LoadImageW with LR_DEFAULTSIZE | LR_SHARED flags

however code for direct access resource (LoadImageW do this internal)

ULONG GetResourcePointer(void** ppv, ULONG* pcb, HMODULE hModule, PCWSTR lpName, PCWSTR lpType)
{
    if (HRSRC hResource = FindResource(hModule, lpName, lpType))
    {
        if (HGLOBAL hResData = LoadResource(hModule, hResource))
        {
            if (PVOID pv = LockResource(hResData))
            {
                if (ULONG cb = SizeofResource(hModule, hResource))
                {
                    *ppv = pv, *pcb = cb;

                    return NOERROR;
                }
            }
        }
    }

    return GetLastError();
}

        ULONG err = NOERROR;
        HCURSOR hcur;

        if (HMODULE hmod = (HMODULE)LoadLibraryW(L"*"))
        {
            ULONG cb, err;
            PVOID pv;
            if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB), RT_GROUP_CURSOR)))
            {
                if (int nID = LookupIconIdFromDirectoryEx((PBYTE)pv, FALSE, 0, 0, LR_DEFAULTCOLOR))
                {

                    if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(nID), RT_CURSOR)))
                    {
                        if (!(hcur = (HCURSOR)CreateIconFromResourceEx((PBYTE)pv, cb,
                            FALSE, 0x00030000, 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE)))
                        {
                            err = GetLastError();
                        }
                    }
                }
                else
                {
                    err = GetLastError();
                }
            }
        }

Upvotes: 4

Denys Save
Denys Save

Reputation: 101

Variants of errors:

  1. The system does not find the library with the specified name BenjaMiniRessources.dll, if the return value in LoadLibrary("BenjaMiniRessources.dll") is NULL;
  2. The system does not find a resource of type RT_CURSOR in BenjaMiniRessources.dll, if the return value in FindResource(dll, MAKEINTRESOURCE(100), RT_CURSOR) is NULL. (Maybe type of this resource is RT_GROUP_CURSOR or RT_ANICURSOR);
  3. The error is in string SizeofResource(dll,hRes), if return value is NULL;

  4. The problem is in LoadResource(dll, hRes), if this function returns NULL;

  5. The fault in LockResource(hMem), if this function returns NULL;

  6. The error is in string CreateIconFromResource(pBytes, dwSize, false, 0x00030000).

You can go through the code under the debugger and see which one of the lines of the program first returns an error.

Upvotes: 0

xMRi
xMRi

Reputation: 15375

Use simply LoadCursor with the corresponding hInstance. This works in the MFC and all of my Windows applications.

Upvotes: 5

Related Questions