Seltsames bitmap problem
-
also ich poste erstmal den code:
// bildverarbeitung2.cpp : Definiert den Einsprungpunkt für die Anwendung. // #include "stdafx.h" #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); HBITMAP hBitmap; BITMAP bitmap; HDC hdc, hdcMem ; HINSTANCE hInstance ; PAINTSTRUCT ps ; HBITMAP loadImg(char* path) { if(HBITMAP ret = (HBITMAP)LoadImage(0,path,IMAGE_BITMAP,0,0,LR_LOADFROMFILE)) return ret; else return NULL; } HDC getScreenShot() { return GetDC(0); } HBITMAP getBitmapScreenShot() { HDC screen = getScreenShot(); HDC hdcCompatible = CreateCompatibleDC(screen); HBITMAP screenBitmap = CreateCompatibleBitmap(screen, GetDeviceCaps(screen, HORZRES), GetDeviceCaps(screen, VERTRES)); SelectObject(hdcCompatible, screenBitmap); BitBlt(hdcCompatible,0,0, GetDeviceCaps(screen, HORZRES), GetDeviceCaps(screen, VERTRES), screen, 0,0,SRCCOPY) ; return screenBitmap; } HDC getBitmapHDC(HBITMAP img) { HDC hdcImage = CreateCompatibleDC(GetDC(0)); SelectObject(hdcImage,img); return hdcImage; } SIZE getBitmapSize(HBITMAP img) { BITMAP imgInfo; GetObject(img, sizeof(BITMAP), (LPSTR)&imgInfo); SIZE ret; ret.cx = imgInfo.bmWidth; ret.cy = imgInfo.bmHeight; return ret; } HBITMAP getHDCScaled(float xscale, float yscale, HDC source) { HDC hdcScaled = getScreenShot(); HBITMAP hbmScaled = CreateCompatibleBitmap(source, GetDeviceCaps(source, HORZRES) * xscale, GetDeviceCaps(source, VERTRES) * yscale); SelectObject(hdcScaled, hbmScaled); StretchBlt(hdcScaled, 0, 0, GetDeviceCaps(source, HORZRES) * xscale, GetDeviceCaps(source, VERTRES) * yscale, source, 0, 0, GetDeviceCaps(source, HORZRES), GetDeviceCaps(source, VERTRES), SRCCOPY); return hbmScaled; } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static char szAppName[] = "Name" ; HWND hwnd ; MSG msg ; WNDCLASSEX wndclass ; wndclass.cbSize = sizeof (wndclass) ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ; RegisterClassEx (&wndclass) ; hwnd = CreateWindow (szAppName, "Fenstername", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE : { hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; HDC scrShot = getScreenShot(); hBitmap = getHDCScaled(0.4, 0.4, scrShot); GetObject (hBitmap, sizeof (BITMAP), &bitmap) ; } return 0 ; case WM_PAINT : { hdc = BeginPaint (hwnd, &ps) ; hdcMem = CreateCompatibleDC (hdc) ; SelectObject (hdcMem, hBitmap) ; BitBlt (hdc, 100, 100, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY) ; EndPaint (hwnd, &ps) ; return 0 ; } case WM_DESTROY : DeleteDC (hdcMem) ; DeleteObject (hBitmap) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }nunja, wenn ich das aufrufe wird in der oberen linken bildschirmecke tatsächlich ein screenshot mit der größe 0.4 gezeichnet. dieser befindet sich aber nicht im fenster und wird auch nur 1 mal gezeichnet...nähmlich ganz am anfang oO
-
- Du released die hBitmap nie aus hdcMem (mittels zweitem SelectObject()!)
- Du erzeugst bei jedem WM_PAINT ein neues hdcMem
- Generell bist du recht wenig am saubermachen

(Unter Win95 hättest du nach nen paar WM_PAINT-Aufrufen sofort merkwürdige Grafikfehler, fehlende Symbole oder dir würde sogar das ganze Windows wegschmieren ;D)
-
geeky schrieb:
- Du released die hBitmap nie aus hdcMem (mittels zweitem SelectObject()!)
hö ? wie jetzt? versteh ich ned
-
z.B. mag DeleteObject() das nicht so gerne:
Do not delete a drawing object (pen or brush) while it is still selected into a DC.
Nehmen wir mal die WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ; hdcMem = CreateCompatibleDC (hdc) ; SelectObject (hdcMem, hBitmap) ; BitBlt (hdc, 100, 100, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY) ; EndPaint (hwnd, &ps) ;Du erzeugst hier ein hdcMem-Handle bei jedem WM_PAINT-Aufruf löscht aber bei WM_DESTROY nur jeweils das letzte hdcMem, weil du alle vorigen ja hier in WM_PAINT überschreibst. Gut, Windows räumt bei Programmende eh selber auf, aber wenn deine Anwendung lange läuft steigt die Anzahl der GDI-Handles an und es gibt da von Windows ein Limit!
Dann selektierst du hier hBitmap in das hdcMem, selektierst es aber nirgendswo mehr raus. Einige GDI-Funktionen wie DeleteObject() mögen in-ein-DC-selektierte GDI-Objekte nicht mehr

Abgeändert:
hdc = BeginPaint (hwnd, &ps) ; hdcMem = CreateCompatibleDC (hdc) ; HGDIOBJ prevObj=SelectObject (hdcMem, hBitmap) ; BitBlt (hdc, 100, 100, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY) ; SelectObject(hdcMem,prevObj); DeleteDC(hdcMem); EndPaint (hwnd, &ps) ;