WinAPI - تحميل Ressources من DLL

أنا بصدد تطوير تطبيق لويندوز 7 مع VisualStudio2017. يريد هذا التطبيق أن يكون لديك مؤشرات خاصة التي يتم تحميلها من 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 يتم تضمين موارد بلدي:

Picture from the Resource Editor

الآن يبدأ الجزء "غير عامل". يريد طلبي تحميل المؤشر ، ولكن 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);

ما الخطأ الذي افعله؟

0
"ما الخطأ الذي افعله؟" - عدم التحقق من الفشل ، وعدم الاتصال GetLastError() .
وأضاف المؤلف Jonathan Potter, مصدر
هل جربت تعداد الموارد. لا يتم استخدام موارد RT_CURSOR ، iirc ، المضمنة في قسم الموارد مباشرةً ، وهي أكثر ، عادةً ما يتم تضمينها كموارد فرعية في RT_GROUP_CURSOR.
وأضاف المؤلف Chris Becke, مصدر

3 إجابة

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

0
وأضاف
حسنا! هذا يعمل ... ولكن كيف ينبغي للمرء أن يعرف أنني أستطيع استخدام وحدة نمطية كمثال ؟! ارغ ... وينابى ... شكرا!
وأضاف المؤلف DragonEgg, مصدر
DragonEgg حسب وثائق أنواع بيانات Win32 : " HMODULE و HINSTANCE هي نفسها في الإصدارات الحالية من Windows ، ولكنها تمثل أشياء مختلفة في Windows 16 بت. "انظر أيضًا ما الفرق بين HINSTANCE و HMODULE؟ في مدونة Raymond Chen.
وأضاف المؤلف Remy Lebeau, مصدر

عندما تدرج BM_CURSأو_GRAB CURSأو "./grab.cur" سطر لملف rc ، في PE الناتج سيكون (BM_CURSأو_GRAB ، RT_GROUP_CURSأو) مورد. لذلك سيكون النوع RT_GROUP_CURSأو ولكن لا RT_CURSأو .

ثم تحتاج إلى استدعاء LookupIconIdFromDirectأوyEx </القانون> وظيفة لاسم الحصول على (ID) المؤشر الذي يناسب حجم معين.

بعد ذلك تحتاج مرة أخرى تحميل الموارد - بالفعل RT_CURSأو مع معرف عائد من LookupIconIdFromDirectأوyEx .

وأخيرًا استخدمه في الاتصال < كود> CreateIconFromResourceEx </القانون> .

ولكن مع ذلك ، يمكنك ببساطة استدعاء < code> LoadImage مع نوع مورد IMAGE_CURSأو .

(HCURSأو)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSأو_GRAB), IMAGE_CURSأو, 
            0, 0, 0);

على سبيل المثال ، لاستخدام حجم المورد الفعلي. أو هل تريد استخدام حجم مؤشر النظام الافتراضي:

(HCURSأو)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSأو_GRAB), IMAGE_CURSأو, 
                GetSystemMetrics(SM_CXCURSأو), GetSystemMetrics(SM_CYCURSأو), 0);

أو

(HCURSأو)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSأو_GRAB), IMAGE_CURSأو, 
                    0, 0, LR_DEFAULTSIZE);

أو simply

LoadCursأوW(hmod, MAKEINTRESOURCE(BM_CURSأو_GRAB));

آخر مكالمة داخلية مكالمة LoadImageW مع LR_DEFAULTSIZE | LR_SHARED العلامات

however code fأو 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 NOERRأو;
                }
            }
        }
    }

    return GetLastErrأو();
}

        ULONG err = NOERRأو;
        HCURSأو hcur;

        if (HMODULE hmod = (HMODULE)LoadLibraryW(L"*"))
        {
            ULONG cb, err;
            PVOID pv;
            if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(BM_CURSأو_GRAB), RT_GROUP_CURSأو)))
            {
                if (int nID = LookupIconIdFromDirectأوyEx((PBYTE)pv, FALSE, 0, 0, LR_DEFAULTCOLأو))
                {

                    if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(nID), RT_CURSأو)))
                    {
                        if (!(hcur = (HCURSأو)CreateIconFromResourceEx((PBYTE)pv, cb,
                            FALSE, 0x00030000, 0, 0, LR_DEFAULTCOLأو|LR_DEFAULTSIZE)))
                        {
                            err = GetLastErrأو();
                        }
                    }
                }
                else
                {
                    err = GetLastErrأو();
                }
            }
        }
0
وأضاف
هذا يعمل كذلك ... لكنه تماما ... معقدة D: و ... ليس لدي أي فكرة عن كيفية معرفة ذلك ... إجابتك أقرب بكثير لمشكلتي ثم أول واحد - ولكن أنا علامة على أول واحد كما حل لأنه أسهل في الاستخدام.
وأضاف المؤلف DragonEgg, مصدر
DragonEgg - ولكن أنا في البداية أقول أن LoadImageW هو الحل الأمثل بالنسبة لك. تعد LoadCursorW حالة خاصة LoadImageW إذا كنت توافق على استخدام الحجم الافتراضي للمؤشر. الشفرة ، التي أقدمها - فقط للعرض التجريبي
وأضاف المؤلف RbMm, مصدر

المتغيرات من الأخطاء:

  1. لا يعثر النظام على المكتبة بالاسم المحدد BenjaMiniRessources.dll ، إذا كانت قيمة الإرجاع في LoadLibrary ("BenjaMiniRessources.dll") هي NULL ؛
  2. لا يعثر النظام على مورد من نوع RT_CURSOR في BenjaMiniRessources.dll ، إذا كانت قيمة الإرجاع في FindResource (dll ، و MAKEINTRESOURCE (100) ، و RT_CURSOR) هي NULL. (ربما يكون نوع هذا المورد هو RT_GROUP_CURSOR أو RT_ANICURSOR) ؛
  3. الخطأ موجود في السلسلة SizeofResource (dll، hRes)، إذا كانت قيمة الإرجاع هي NULL ؛

  4. المشكلة في LoadResource (dll، hRes) ، إذا أرجعت هذه الدالة NULL ؛

  5. الخطأ في LockResource (hMem) ، إذا أرجعت هذه الدالة NULL ؛

  6. الخطأ موجود في السلسلة CreateIconFromResource (pBBB ، dwSize ، false ، 0x00030000) .

يمكنك الذهاب من خلال رمز تحت المصحح ونرى أي واحد من أسطر البرنامج لأول مرة إرجاع خطأ.

0
وأضاف
إذا كانت قيمة الإرجاع في LoadLibrary أقل من 32 ؛ - يبدو أنك تخلط بين LoadLibrary و ShellExecute . فشل LoadLibrary عند الفشل بالضبط 0 ويجب مقارنة قيمة الإرجاع بـ 0 فقط (وليس 32). ولا يمكن أن يكون هذا المورد هو RT_GROUP_CURSOR ولكن بالضبط
وأضاف المؤلف RbMm, مصدر
أنا آسف ، أنا الخلط بين LoadLibrary() و LoadModule ().
وأضاف المؤلف Denys Save, مصدر