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



    1. Du released die hBitmap nie aus hdcMem (mittels zweitem SelectObject()!)
    2. Du erzeugst bei jedem WM_PAINT ein neues hdcMem
    3. 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:

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

Anmelden zum Antworten