2 Stimmen

Schwarzes Bild bei der Erstellung eines Bitmaps aus einer Auswahl des Bildschirms in C++

Ich versuche, eine Bildschirmaufnahme von einem ausgewählten Bereich des Desktops zu erstellen.

Das Problem, das ich habe, ist, dass die Ausgabe (.bmp-Datei) nur schwarz ist.

Ich habe CreateBitmapInfoStruct(); und CreateBMPFile(); aus MSDN . Der Rest sind Schnipsel aus dem Internet, die von mir zusammengeschnitten wurden.

So sieht mein Code derzeit aus:

#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{ 
    BITMAP bmp; 
    PBITMAPINFO pbmi; 
    WORD    cClrBits; 

    // Retrieve the bitmap color format, width, and height.  
    if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
        cout << "ERROR:1";

    // Convert the color format to a count of bits.  
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if (cClrBits == 1) 
        cClrBits = 1; 
    else if (cClrBits <= 4) 
        cClrBits = 4; 
    else if (cClrBits <= 8) 
        cClrBits = 8; 
    else if (cClrBits <= 16) 
        cClrBits = 16; 
    else if (cClrBits <= 24) 
        cClrBits = 24; 
    else cClrBits = 32; 

    // Allocate memory for the BITMAPINFO structure. (This structure  
    // contains a BITMAPINFOHEADER structure and an array of RGBQUAD  
    // data structures.)  

     if (cClrBits < 24) 
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER) + 
                    sizeof(RGBQUAD) * (1<< cClrBits)); 

     // There is no RGBQUAD array for these formats: 24-bit-per-pixel or 32-bit-per-pixel 

     else 
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER)); 

    // Initialize the fields in the BITMAPINFO structure.  

    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    pbmi->bmiHeader.biWidth = bmp.bmWidth; 
    pbmi->bmiHeader.biHeight = bmp.bmHeight; 
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
    if (cClrBits < 24) 
        pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 

    // If the bitmap is not compressed, set the BI_RGB flag.  
    pbmi->bmiHeader.biCompression = BI_RGB; 

    // Compute the number of bytes in the array of color  
    // indices and store the result in biSizeImage.  
    // The width must be DWORD aligned unless the bitmap is RLE 
    // compressed. 
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbmi->bmiHeader.biHeight; 
    // Set biClrImportant to 0, indicating that all of the  
    // device colors are important.  
     pbmi->bmiHeader.biClrImportant = 0; 
     return pbmi; 
 } 

void CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, 
                  HBITMAP hBMP, HDC hDC) 
 { 
     HANDLE hf;                 // file handle  
    BITMAPFILEHEADER hdr;       // bitmap file-header  
    PBITMAPINFOHEADER pbih;     // bitmap info-header  
    LPBYTE lpBits;              // memory pointer  
    DWORD dwTotal;              // total count of bytes  
    DWORD cb;                   // incremental count of bytes  
    BYTE *hp;                   // byte pointer  
    DWORD dwTmp; 

    pbih = (PBITMAPINFOHEADER) pbi; 
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    if (!lpBits) 
         cout << "ERROR:2"; 

    // Retrieve the color table (RGBQUAD array) and the bits  
    // (array of palette indices) from the DIB.  
    GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
        DIB_RGB_COLORS);

    // Create the .BMP file.  
    hf = CreateFile(pszFile, 
                   GENERIC_READ | GENERIC_WRITE, 
                   (DWORD) 0, 
                    NULL, 
                   CREATE_ALWAYS, 
                   FILE_ATTRIBUTE_NORMAL, 
                   (HANDLE) NULL); 
    if (hf == INVALID_HANDLE_VALUE) 
        cout << "ERROR:4"; 
    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
    // Compute the size of the entire file.  
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pbih->biSize + pbih->biClrUsed 
                 * sizeof(RGBQUAD) + pbih->biSizeImage); 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 

    // Compute the offset to the array of color indices.  
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pbih->biSize + pbih->biClrUsed 
                    * sizeof (RGBQUAD); 

    // Copy the BITMAPFILEHEADER into the .BMP file.  
    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
        (LPDWORD) &dwTmp,  NULL)) 
    {
       cout << "ERROR:5";
    }

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
    if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                  + pbih->biClrUsed * sizeof (RGBQUAD), 
                  (LPDWORD) &dwTmp, ( NULL)))
        cout << "ERROR:6";

    // Copy the array of color indices into the .BMP file.  
    dwTotal = cb = pbih->biSizeImage; 
    hp = lpBits; 
    if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
           cout << "ERROR:7";

    // Close the .BMP file.  
     if (!CloseHandle(hf)) 
           cout << "ERROR:8"; 

    // Free memory.  
    GlobalFree((HGLOBAL)lpBits);
}

void getBit(string name) {
    int nX = 300;
    int nX2 = 600;
    int nY = 300;
    int nY2 = 700;
     HDC hScrDC  =  GetDC(NULL); 
     HDC hMemDC  =  CreateCompatibleDC(hScrDC);
     int nWidth  =  nX2  -  nX; 
     int nHeight  =  nY2  -  nY; 
     HBITMAP hBitmap  =  CreateCompatibleBitmap(hScrDC,  nWidth,  nHeight); 
     HBITMAP hOldBitmap  =  (HBITMAP)SelectObject(hMemDC,  hBitmap); 

     BitBlt(hMemDC,  0,  0,  nWidth,  nHeight, 
     hScrDC,  nX,  nY,  SRCCOPY); 
     hBitmap  =  (HBITMAP)SelectObject(hMemDC,  hOldBitmap); 
     DeleteDC(hScrDC); 
     DeleteDC(hMemDC); 
    // now your image is held in hBitmap. You can save it or do whatever with it
    PBITMAPINFO pbi = CreateBitmapInfoStruct(hBitmap);
    //File name
    LPTSTR path = L"test.bmp";
    CreateBMPFile(path,pbi,hBitmap,hMemDC);
}

void main(void) {
    getBit("SAVE");
    cout << "Done";
    int wait;
    cin >> wait;
}

2voto

Adrian McCarthy Punkte 42872

Das größte Problem ist, dass GetDIBits schlägt fehl, weil Sie ein Handle zu einem gelöschten Speicherkontext anstelle eines Handles zu einem gültigen Gerätekontext übergeben. Wenn Sie das beheben, funktioniert es.

Bei der Fehlersuche ist es immer eine gute Idee, alle Rückgabewerte zu überprüfen.

Andere Dinge, die mir aufgefallen sind:

  1. Sie sollten hSrcDC nicht löschen, da Sie es nicht erstellt haben. Verwenden Sie ReleaseDC , die das Pendant zu GetDC .
  2. Erwägen Sie die Verwendung von CAPTUREBLT in Ihrem BitBlt anrufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X