jpg aus resource?
-
Hi!
Ich versuche, eine jpg-datei in einem fenster anzuzeigen. dabei soll die jpg-datei aus einer resource geholt werden. wieso funktioniert das so nicht?#include <windows.h> #include <olectl.h> LPPICTURE pPicture; long lWidth, lHeight; int iWidth, iHeight; static HINSTANCE g_hInst=NULL; BOOL LoadPicture(LPCTSTR pszResourceID) { HGLOBAL hGlobal = LoadResource (g_hInst, FindResource (g_hInst, "IMAGE", pszResourceID)); // größe der Resource ermitteln DWORD dwFileSize = SizeofResource (g_hInst, FindResource (g_hInst, "IMAGE", pszResourceID)); //IStream* aus dem speicher erzeugen LPSTREAM pstm = NULL; HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm); //IPicture vom bild erzeugen if(pPicture) pPicture->Release(); hr = OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&pPicture); pstm->Release(); //breite u. höhe vom bild holen pPicture->get_Width(&lWidth); pPicture->get_Height(&lHeight); HDC hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL); //in Pixel konvertieren iWidth = (lWidth * GetDeviceCaps(hdc, LOGPIXELSX)) / 2540; iHeight = (lHeight * GetDeviceCaps(hdc, LOGPIXELSY)) / 2540; return TRUE; } BOOL DrawPicture(HWND hwnd, HDC hdc) { if(pPicture) //wenn bild geladen { RECT rc; GetClientRect(hwnd, &rc); //Bild anzeigen mittels Render pPicture->Render(hdc, 0, 0, iWidth, iHeight, 0, lHeight, lWidth, -lHeight, &rc); return TRUE; } return FALSE; } LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); //Deklaration der Windows-Nachrichten-Prozedur int WINAPI WinMain (HINSTANCE hI, HINSTANCE hPrI, PSTR szCmdLine, int iCmdShow) { char szName[] = "Fensterklasse"; WNDCLASS wc; g_hInst=hI; wc.style = CS_HREDRAW | CS_VREDRAW; // CS = "class style" wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hI; wc.hIcon = LoadIcon (NULL, IDI_WINLOGO); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = szName; RegisterClass (&wc); HWND hwnd = CreateWindow (szName, "", WS_SYSMENU | WS_THICKFRAME, 0, 0, 200, 100, NULL, NULL, hI, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); // Nachrichten-Schleife MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } // Windows-Nachrichten-Prozedur LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (message) { case WM_PAINT: hdc = BeginPaint (hwnd, &ps); LoadPicture("ID_TESTBILD"); DrawPicture(hwnd, hdc); EndPaint (hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); }
*.rc-datei:
ID_TESTBILD IMAGE DISCARDABLE "test1.jpg"
Mein Dank an alle hilfsbereiten menschen
-
Es ist immer gut, wenn man angibt, wo der Fehler passiert!
CreateStreamOnHGlobal sollte als 2. Parameter ein FALSE bekommen, da das HGLOBAL der Resource nicht gelöscht werden darf.
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
LoadPicture("ID_TESTBILD");Wie häufig willst Du denn das Bild laden?
-
Also zu 1.: Das Programm lässt sich nicht starten. es spuckt die fehlermeldung aus Access violation at address 004011f3. Read of adress 00000000.
ich nehme mal an, das die LoadResource/FindResource kombination in meinem programm fehlerhaft ist, und anstelle des speicherbereichs der resource bekomme ich nix.
2. Ok, ist vielleicht auch eine mögliche fehlerquelle, aber ich bekomme immer noch den fehler von 1.
3. naja, ich weiss, der aufruf von LoadPicture ist dort ein bischen fehl am platz, aber es hat funktioniert, als ich das jpg-file noch von der platte laden lies. soll ja nur zum testen sein ohne das nochmal wm_paint aufgerufen werden soll. sonst würde ich es natürlich in diesem fall in wm_create laden lassen.
-
Tach,
du hattest mir ja schonmal ein Mail geschickt. Ich hab auch mal ein bischen rumprobiert, aber so auf die schnelle hats nicht geklappt.
Hier hast du einen kleinen Fehler drin:
FindResource(g_hInst, "IMAGE", pszResourceID)
"IMAGE" ist der Typ, also Parameter 3 und pszResourceID ist der Name, also Parameter 2.Allerdings ist das scheinbar nicht der einzige.
TIPP:Prinzipiell solltest du, vor allem wenn etwas nicht funktioniert, die Rückgabewerte der Funktionen auswerten und evtl. mit GetLastError auch den entsprechenden Fehlercode abfragen, dann findest du schnell die Stelle in welcher der Fehler steckt.
Folgenden Code habe ich mal zum anzeigen einea JPG aus einer Resource verwendet (ist allerdings nicht sehr Variabel die Funktion
naja vieliecht hilfts dir ja [irgendwie scheint mir die "spiecherkopiererei" auch zu viel zu sein
weiß nicht mehr warum ich das da rein hab, aber es geht]) :
void ShowJPG(HDC hdc){ LPPICTURE gpPicture=0; HRSRC hResInfo; HGLOBAL hGlobal, hResource; hResInfo=FindResource(GetModuleHandle(0), MAKEINTRESOURCE(IDR_JPG1), "JPG"); _ASSERTE(NULL != hResInfo); hResource=LoadResource(GetModuleHandle(0), hResInfo); _ASSERTE(NULL != hResource); // get ressource size DWORD dwFileSize = SizeofResource(GetModuleHandle(0), hResInfo); LPVOID pvDataFrom = NULL; LPVOID pvDataTo = NULL; // alloc memory based on file size hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); _ASSERTE(NULL != hGlobal); pvDataTo=GlobalLock(hGlobal); _ASSERTE(NULL != pvDataTo); pvDataFrom=LockResource(hResource); memcpy(pvDataTo, pvDataFrom, dwFileSize); GlobalUnlock(hGlobal); LPSTREAM pstm = NULL; // create IStream* from global memory HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm); _ASSERTE(SUCCEEDED(hr) && pstm); // Create IPicture from image file if (gpPicture) gpPicture->Release(); hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture); _ASSERTE(SUCCEEDED(hr) && gpPicture); pstm->Release(); if(gpPicture){ // get width and height of picture long hmWidth; long hmHeight; gpPicture->get_Width(&hmWidth); gpPicture->get_Height(&hmHeight); // convert himetric to pixels int nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), 2540); int nHeight = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), 2540); RECT rc; rc.left=0; rc.right=700; rc.bottom=500; rc.top=0; // display picture using IPicture::Render gpPicture->Render(hdc, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc); gpPicture->Release(); } else TextOut(hdc, 10, 10, "Error", 5); }
-
DANKE, funktioniert!
Allerdings musste ich die _asserte-makros rausnehmen, sonst beschwert sich mein compiler wegen der fehlenden funktion '_asserte'. Gibts was vergleichbares für den c++builder 5 oder hab ich nur vergessen, etwas einzubinden?
Also, der weg, die resource vorher in einen speicherplatz zu verschieben und dann anzuzeigen, funktioniert. bedeutet das mein programm nicht lauffähig gemacht werden kann?
-
Es heißt assert ohne e.
-
-
_ASSERTE ist Microshit-spezifisch, das solltest du dazu sagen. Bello hat einen Borland Compiler, wie du lesen kannst. Deshalb kann er damit recht wenig anfangen.