WinAPI - Încărcarea resurselor dintr-un DLL

Sunt în curs de dezvoltare o aplicație pentru Windows 7 cu VisualStudio2017. Această aplicație dorește să aibă cursoare speciale care sunt încărcate de pe un DLL. Deci, mai intai am creat un DLL si am adaugat urmatorul fisier .rc:

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

BM_CURSOR_GRAB și BM_CURSOR_GRABBING sunt definite într-un fișier antet ca:

#define BM_CURSOR_GRAB     100
#define BM_CURSOR_GRABBING 101

Am compila DLL - care functioneaza si verifica-l cu ResourceEditor.exe Resursele mele sunt incluse:

Picture from the Resource Editor

Acum începe partea "non working". Aplicația mea dorește să încarce cursorul, dar FindResource nu o găsește. Aici este codul meu:

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

ce fac greșit?

0
"Ce fac greșit?" - nu verificarea eșecului, fără a apela GetLastError() .
adăugat autor Jonathan Potter, sursa
Ați încercat enumerarea resurselor. Resursele RT_CURSOR nu sunt incluse incluse direct în secțiunea resursă, ele sunt mai mult, de obicei, incluse ca sub resurse într-un RT_GROUP_CURSOR.
adăugat autor Chris Becke, sursa

3 răspunsuri

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

0
adăugat
O.K! Asta funcționează ... Dar cum ar trebui să știm că aș putea folosi un modul ca instanță ?! Argh ... WinAPI ... Mulțumesc!
adăugat autor DragonEgg, sursa
@ DragonEgg în documentația Win32 Data Types : " HMODULE și HINSTANCE sunt aceleași în versiunile curente ale Windows, dar au reprezentat lucruri diferite în Windows pe 16 biți. "De asemenea, vedeți Care este diferența dintre HINSTANCE și HMODULE? în blogul lui Raymond Chen.
adăugat autor Remy Lebeau, sursa

când includeți BM_CURSsau_GRAB CURSsau "./grab.cur" la fisierul rc, in PE generat va fi resursa (BM_CURSsau_GRAB, RT_GROUP_CURSsau) . astfel încât tipul va fi RT_GROUP_CURSsau dar nu RT_CURSsau .

atunci trebuie să sunați LookupIconIdFromDirectsauyEx pentru a obține numele (id) al curssauului care se potrivește cel mai bine dimensiunii specificate.

după aceasta, trebuie să încărcați din nou resursa - deja RT_CURSsau cu id-ul returnat de la LookupIconIdFromDirectsauyEx .

și în cele din urmă să-l utilizați la apel < code> CreateIconFromResourceEx .

dar cu toate acestea, mai simplu, sunați < code> LoadImage cu tipul de resursă IMAGE_CURSsau .

(HCURSsau)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSsau_GRAB), IMAGE_CURSsau, 
            0, 0, 0);

de exemplu, pentru utilizarea dimensiunii reale a resurselsau. sau dsauiți să utilizați dimensiunea implicită a curssauului sistemului:

(HCURSsau)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSsau_GRAB), IMAGE_CURSsau, 
                GetSystemMetrics(SM_CXCURSsau), GetSystemMetrics(SM_CYCURSsau), 0);

sau

(HCURSsau)LoadImageW(hmod, MAKEINTRESOURCE(BM_CURSsau_GRAB), IMAGE_CURSsau, 
                    0, 0, LR_DEFAULTSIZE);

sau simply

LoadCurssauW(hmod, MAKEINTRESOURCE(BM_CURSsau_GRAB));

ultimul apel intern apel LoadImageW cu LR_DEFAULTSIZE | LR_SHARED

however code fsau 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 NOERRsau;
                }
            }
        }
    }

    return GetLastErrsau();
}

        ULONG err = NOERRsau;
        HCURSsau hcur;

        if (HMODULE hmod = (HMODULE)LoadLibraryW(L"*"))
        {
            ULONG cb, err;
            PVOID pv;
            if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(BM_CURSsau_GRAB), RT_GROUP_CURSsau)))
            {
                if (int nID = LookupIconIdFromDirectsauyEx((PBYTE)pv, FALSE, 0, 0, LR_DEFAULTCOLsau))
                {

                    if (!(err = GetResourcePointer(&pv, &cb, hmod, MAKEINTRESOURCE(nID), RT_CURSsau)))
                    {
                        if (!(hcur = (HCURSsau)CreateIconFromResourceEx((PBYTE)pv, cb,
                            FALSE, 0x00030000, 0, 0, LR_DEFAULTCOLsau|LR_DEFAULTSIZE)))
                        {
                            err = GetLastErrsau();
                        }
                    }
                }
                else
                {
                    err = GetLastErrsau();
                }
            }
        }
0
adăugat
Acest lucru funcționează de asemenea ... Dar este destul de ... complex D: Și ​​... Nu am nici o idee cum să-mi dau seama ... Răspunsul tău este mult mai aproape de problema mea decât primul - dar eu sunt primul una ca rezolvată deoarece este mai ușor de folosit.
adăugat autor DragonEgg, sursa
@DragonEgg - dar la început spun că LoadImageW este cea mai bună soluție pentru tine. LoadCursorW este un caz particular al LoadImageW dacă sunteți de acord să utilizați dimensiunea implicită pentru cursor. codul pe care îl furnizez - doar pentru demo
adăugat autor RbMm, sursa

Variante de erori:

  1. Sistemul nu găsește biblioteca cu numele specificat BenjaMiniRessources.dll, dacă valoarea returnată în LoadLibrary ("BenjaMiniRessources.dll") este NULL;
  2. Sistemul nu găsește o resursă de tip RT_CURSOR în BenjaMiniRessources.dll, dacă valoarea returnată în FindResource (dll, MAKEINTRESOURCE (100), RT_CURSOR) este NULL. (Poate că tipul acestei resurse este RT_GROUP_CURSOR sau RT_ANICURSOR);
  3. Eroarea este in sirul SizeofResource (dll, hRes), daca valoarea returnata este NULL; </

  4. Problema este LoadResource (dll, hRes) , dacă această funcție returnează NULL;

  5. Vina în LockResource (hMem) , dacă această funcție returnează NULL;

  6. Eroarea este în șirul CreateIconFromResource (pBytes, dwSize, false, 0x00030000) .

Puteți trece prin codul de sub debugger și să vedeți care dintre liniile programului întoarce mai întâi o eroare.

0
adăugat
dacă valoarea returnată în LoadLibrary este mai mică de 32; - arătați că confundați LoadLibrary și ShellExecute . codul LoadLibrary pe returnarea defecțiunilor este exact 0, iar valoarea returnată trebuie comparată numai cu 0 (nu cu 32). și nu poate fi această resursă este RT_GROUP_CURSOR , dar exact
adăugat autor RbMm, sursa
Îmi pare rău, am confundat LoadLibrary() și LoadModule ().
adăugat autor Denys Save, sursa