繁体   English   中英

WinAPI-从DLL加载资源

[英]WinAPI - Loading Ressources from a DLL

我正在使用VisualStudio2017开发适用于Windows 7的应用程序。 该应用程序希望具有从DLL加载的特殊游标。 所以首先我创建了一个DLL并添加了以下.rc文件:

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

BM_CURSOR_GRAB和BM_CURSOR_GRABBING在头文件中定义为:

#define BM_CURSOR_GRAB     100
#define BM_CURSOR_GRABBING 101

我编译DLL-可以正常工作并使用ResourceEditor.exe对其进行检查。我的资源包括在内:

资源编辑器中的图片

现在,“不工作”部分开始。 我的应用程序想要加载游标,但是FindResource找不到它。 这是我的代码:

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);

我究竟做错了什么?

只需将LoadCursor与相应的hInstance一起使用。 这适用于MFC和我的所有Windows应用程序。

当您将BM_CURSOR_GRAB CURSOR "./grab.cur"行包含到rc文件中时,在生成的PE中将是(BM_CURSOR_GRAB, RT_GROUP_CURSOR)资源。 所以类型将是RT_GROUP_CURSOR而不是RT_CURSOR

那么您需要调用LookupIconIdFromDirectoryEx函数以获取最适合指定大小的游标的名称(id)。

在此之后,你需要重新加载资源-已经RT_CURSOR与返回ID LookupIconIdFromDirectoryEx

最后在调用CreateIconFromResourceEx使用它。

但是,更简单的LoadImage使用IMAGE_CURSOR资源类型调用LoadImage

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

例如,用于使用实际资源大小。 还是要使用默认的系统光标大小:

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

要么

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

或简单地

LoadCursorW(hmod, MAKEINTRESOURCE(BM_CURSOR_GRAB));

最后一次调用内部调用LoadImageW带有LR_DEFAULTSIZE | LR_SHARED LR_DEFAULTSIZE | LR_SHARED标志

但是直接访问资源的代码( LoadImageW在内部执行此操作)

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();
                }
            }
        }

错误的变种:

  1. 如果LoadLibrary("BenjaMiniRessources.dll")的返回值为NULL,则系统找不到具有指定名称BenjaMiniRessources.dll的库。
  2. 如果在FindResource(dll, MAKEINTRESOURCE(100), RT_CURSOR)的返回值为NULL,则系统不会在BenjaMiniRessources.dll中找到类型为RT_CURSOR的资源。 (此资源的类型可能是RT_GROUP_CURSOR或RT_ANICURSOR);
  3. 如果返回值为NULL SizeofResource(dll,hRes),则错误在字符串SizeofResource(dll,hRes),

  4. 如果此函数返回NULL,则问题出在LoadResource(dll, hRes)

  5. 如果此函数返回NULL,则为LockResource(hMem)的错误; LockResource(hMem)

  6. 错误在字符串CreateIconFromResource(pBytes, dwSize, false, 0x00030000)

您可以遍历调试器下的代码,查看程序的哪一行首先返回错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM