Képmegjelenítési probléma C++-ban

Címkék
Képmegjelenítési probléma C++-ban
2020-05-27T15:42:24+02:00
2020-05-29T15:24:36+02:00
2022-08-11T20:20:40+02:00
Tomi_T2
Sziasztok!

Képeket szeretnék megjeleníteni Code::Block-s alatt C++-ban, de valamiért a kódom nem akar egyet sem kirajzolni.
Erről a kóddarabról van szó. Kihagytam belőle valamit, vagy rosszul csináltam? Megjegyzésekben bele is írtam, hogy - szerintem - mi mit csinál.

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC grafikakezelo; PAINTSTRUCT ps; static HBITMAP kep; BITMAP bitmapkep; HDC grafikakezelo2; switch (message) /* handle the messages */ { case WM_CREATE: //A kép betöltése: kep = (HBITMAP) LoadImageW(NULL, L"kek_labda.bmp", IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT); break; case WM_PAINT: grafikakezelo = BeginPaint(hwnd, &ps); //Készítek egy másik grafikakezelőt az első alapján: grafikakezelo2 = CreateCompatibleDC(grafikakezelo); //A kep-et betöltöm ebbe az új grafikakezelőbe: SelectObject(grafikakezelo2, kep); //Kiolvasom a kep méretét: GetObject(kep, sizeof(bitmapkep), &bitmapkep); //Végül a kép kirajzolása az 50-50 képernyőkoordinátára: BitBlt(grafikakezelo, 50, 50, bitmapkep.bmWidth, bitmapkep.bmHeight, grafikakezelo2, 0, 0, SRCCOPY);
Mutasd a teljes hozzászólást!
Olvasd is el, amit linkelek, ne csak copy-paste-lj..

Ezt pl miből gondoltad, hogy működni fog?

LoadBitmap(GetModuleHandle(NULL), "kek_labda.bmp");
Mert a dokumentáció (MSDN) és az általam linkelt oldal alapján is egyértelműnek kéne lennie, hogy ez így nem fog menni, a LoadBitmap 'resource'-okkal működik.

Módosítások, hogy működjön a programod:

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HBITMAP g_hbmBall = NULL; *** g_hbmBall = static_cast<HBITMAP>( LoadImage(NULL, "kek_labda.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)); *** A másk helyen is cast-olj, ahol kéri a fordító!

Függvény lokális változó nem tartja meg az értékét a hívások között. A 'g_hbmBall' változód folyton 'NULL' volt, hiszen arra inicializáltad a függvény elején. Vagy tegyed static-á, vagy old meg másképp, hogy szépen elérhető legyen a WindowProcedure-ból.
Mutasd a teljes hozzászólást!

  • Ez egy nagyon jó oldal (biztosan nagyon régi, még anno használtam :)

    Bitmaps, Device Contexts and BitBlt

    Nézd meg a függvényeid visszatérési értékét és akkor látni fogod, hogy melyik hívás hasal el és miért..

    Az is sokat segítene, ha minimális fordítható kódot tudnál bemásolni, amely reprodukálja a nem működést / problémádat..
    Mutasd a teljes hozzászólást!
  • Szia!

    Kezd az elején..

    // From File:
    hBitmap = (HBITMAP)LoadImage(hInstance, "myimage.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

    A fenti minta alapján keresd meg mi a baj a tiéddel.

    kep = (HBITMAP) LoadImageW(NULL, L"kek_labda.bmp", IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);

    Az L prefix szerintem felesleges ebben az esetben.
    LR_LOADFROMFILE Enélkül viszont nem fog file-ból betölteni semmit szerintem.
    Nem hinném hogy elhagyható opció file betöltése esetén.

    Lásd:
    win32/api/winuser/nf-winuser-loadimagew
    Mutasd a teljes hozzászólást!
  • "Az is sokat segítene, ha minimális fordítható kódot tudnál bemásolni, amely reprodukálja a nem működést / problémádat.."

    Tulajdonképpen az lenne az egész, illetve az egész lényege a kódomnak, amit be is illesztettem: beolvasni a képet a WM_CREATE-ben és kirajzolni a WM_PAINT-ben. De semmit nem mutat, csak az üres képernyőt.
    Az oldal, amit ajánlottál, tényleg jónak tűnik; éppen most böngészgetem és próbálom átültetni belőle a dolgokat, de egyelőre nem igazán akar működni...
    Mutasd a teljes hozzászólást!
  • Kíváncsiságból kimásoltam a képkirajzolási kódot a hivatkozott oldalról, és átraktam egy üres Win32GUI projektbe, de ezt a hibát írja ki a Code::Blocks erre
    HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall);
    a sorra:
    F:\progsetup\codeblocks-17.12mingw-nosetup\sajatok\ablakosrajz\Egy_rajz\main.cpp|100|error: invalid conversion from 'HGDIOBJ {aka void*}' to 'HBITMAP {aka HBITMAP__*}' [-fpermissive]|

    És a teljes kód így néz ki:

    #if defined(UNICODE) && !defined(_UNICODE) #define _UNICODE #elif defined(_UNICODE) && !defined(UNICODE) #define UNICODE #endif #include <tchar.h> #include <windows.h> /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); /* Make the class name into a global variable */ TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp"); int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ /* Use Windows's default colour as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ _T("Code::Blocks Template Windows App"), /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ ShowWindow (hwnd, nCmdShow); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HBITMAP g_hbmBall = NULL; switch (message) /* handle the messages */ { case WM_CREATE: g_hbmBall = LoadBitmap(GetModuleHandle(NULL), "kek_labda.bmp"); if(g_hbmBall == NULL) MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION); break; case WM_PAINT: { BITMAP bm; PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall); GetObject(g_hbmBall, sizeof(bm), &bm); BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); EndPaint(hwnd, &ps); } break; case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }
    Mutasd a teljes hozzászólást!
  • Olvasd is el, amit linkelek, ne csak copy-paste-lj..

    Ezt pl miből gondoltad, hogy működni fog?

    LoadBitmap(GetModuleHandle(NULL), "kek_labda.bmp");
    Mert a dokumentáció (MSDN) és az általam linkelt oldal alapján is egyértelműnek kéne lennie, hogy ez így nem fog menni, a LoadBitmap 'resource'-okkal működik.

    Módosítások, hogy működjön a programod:

    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HBITMAP g_hbmBall = NULL; *** g_hbmBall = static_cast<HBITMAP>( LoadImage(NULL, "kek_labda.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)); *** A másk helyen is cast-olj, ahol kéri a fordító!

    Függvény lokális változó nem tartja meg az értékét a hívások között. A 'g_hbmBall' változód folyton 'NULL' volt, hiszen arra inicializáltad a függvény elején. Vagy tegyed static-á, vagy old meg másképp, hogy szépen elérhető legyen a WindowProcedure-ból.
    Mutasd a teljes hozzászólást!
  • Szia!

    Használd az MSDN-t és olvasd el alaposan egy használni kívánt függvényt leírását és paraméterezését.

    Leírtam és utánam is leírták még egyszer hogy nem jól paraméterezed a függvényhívást.
    Olvasd el ujra amit írtunk és használd is.

    win32/api/winuser/nf-winuser-loadimagew

    Ez pl 6 paraméteres függvény,

    Olvasd el mit ír az egyik részben:

    name
    Type: LPCTSTR
    The image to be loaded. If the hinst parameter is non-NULL and the fuLoad parameter omits LR_LOADFROMFILElpszName specifies the image resource in the hinst module
    ....
    If the hinst parameter is NULL and the fuLoad parameter omits the LR_LOADFROMFILE value, the lpszName specifies the OEM image to load. The OEM image identifiers are defined in Winuser.h and have the following prefixes.

    Különösen a második részt...
    Te nem OEM image-et akarsz betölteni, nemdebár?
    Akkor?
    Miért nem használod az LR_LOADFROMFILE opciót?
    Nem dísz, nem hagyható el , mert ha elhagyod, nem azt fogja tenni a függvény amit te szeretnél... hanem amit kell tennie ezen opció hiányában.
    Mutasd a teljes hozzászólást!
  • Beleírtam az LR_LOADFROMFILE utasítást a megfelelő paraméterhelyre, de így sem rajzol ki semmit.
    Az OEM kép az az, ami be van dolgozva az .exe állományba? Nekem nem olyan kell, hanem ami csak mellé van téve, önállóan.
    Az MSDN-t persze olvasom, azzal is kezdtem eleve, de csak nem akar még összejönni a dolog...
    Egyébként a visszaadott kép nem NULL paraméterű (kiírattam egy IF-ELSE-vel), így feltételezem, hogy nem a kép beolvasással lesz a gond, hanem valahol másütt.
    Mutasd a teljes hozzászólást!
  • Leírtam a konkrét 2 sor módosítást, ami után megjelenítődik a kép.
    Azt hittem azon már túl vagy
    Mutasd a teljes hozzászólást!
  • Csak most tudtam a tanácsod alapján módosítani a programomat, és valóban kirajzolja már a kék labdát! Nagyon köszönöm a megoldásodat (de persze köszönet Kövics Istvánnak is a segítségért!)!
    Úgy örülök!
    Viszont halvány lila gőzöm sincs arról, hogy mit jelent egy függvény statikus mivolta, meg ez a kóddarab a fájlbeolvasás elé: static_cast<HBITMAP>
    Ha nem adom a NULL kezdőértéket a labdaképet tároló változónak, akkor az nem lesz statikus és a kóddarab sem kell elé, vagy hogy van ez?
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
Címkék
abcd