CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Dec 2009
    Posts
    0

    Vista/Win7 Ingame-Screens are black :( GETDC Problem?

    Hey we are coding a tool which takes screens automatically ingame. The Problem is that on Viste/Win7 Systems the Screens are only black...I found some inof about getdc and bitblt...The problem seem to related to them. The Coder is very busy with his job atm and I try to get some help during the time. And not very known with C++...but our Coder gave me the code for the Screenshot part...Maybe someone can help.

    Maybe this is a reason too...?

    Desktop Window Manager

    The desktop composition feature, introduced in Windows Vista, fundamentally changes the way applications display pixels on the screen. When desktop composition is enabled, individual windows no longer draw directly to the screen or primary display device as they did in previous versions of Microsoft Windows. Instead, their drawing is redirected to off-screen surfaces in video memory, which are then rendered into a desktop image and presented on the display.


    Code:
        QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
        {
            RECT r;
            GetClientRect(winId, &r);
    
            if (w < 0) w = r.right - r.left;
            if (h < 0) h = r.bottom - r.top;
    
        #ifdef Q_OS_WINCE_WM
            if (qt_wince_is_pocket_pc()) {
                QWidget *widget = QWidget::find(winId);
                if (qobject_cast<QDesktopWidget *>(widget)) {
                    RECT rect = {0,0,0,0};
                    AdjustWindowRectEx(&rect, WS_BORDER | WS_CAPTION, FALSE, 0);
                    int magicNumber = qt_wince_is_high_dpi() ? 4 : 2;
                    y += rect.top - magicNumber;
                }
            }
        #endif
    
            // Create and setup bitmap
            HDC display_dc = GetDC ;
            HDC bitmap_dc = CreateCompatibleDC(display_dc);
            HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h);
            HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);
    
            // copy data
            HDC window_dc = GetDC(winId);
            BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
        #ifndef Q_OS_WINCE
                                            | CAPTUREBLT
        #endif
                    );
    
            // clean up all but bitmap
            ReleaseDC(winId, window_dc);
            SelectObject(bitmap_dc, null_bitmap);
            DeleteDC(bitmap_dc);
    
            QPixmap

    I found the following code but haven't tried it yet. Could this do the trick?

    Code:
       1.
          #include<iostream>
       2.
          #include<windows.h>
       3.
          using namespace std;
       4.
           
       5.
          inline int GetFilePointer(HANDLE FileHandle){
       6.
          return SetFilePointer(FileHandle, 0, 0, FILE_CURRENT);
       7.
          }
       8.
           
       9.
          bool SaveBMPFile(char *filename, HBITMAP bitmap, HDC bitmapDC, int width, int height){
      10.
          bool Success=0;
      11.
          HDC SurfDC=NULL;
      12.
          HBITMAP OffscrBmp=NULL;
      13.
          HDC OffscrDC=NULL;
      14.
          LPBITMAPINFO lpbi=NULL;
      15.
          LPVOID lpvBits=NULL;
      16.
          HANDLE BmpFile=INVALID_HANDLE_VALUE;
      17.
          BITMAPFILEHEADER bmfh;
      18.
          if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, width, height)) == NULL)
      19.
          return 0;
      20.
          if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL)
      21.
          return 0;
      22.
          HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
      23.
          BitBlt(OffscrDC, 0, 0, width, height, bitmapDC, 0, 0, SRCCOPY);
      24.
          if ((lpbi = (LPBITMAPINFO)(new char[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)])) == NULL)
      25.
          return 0;
      26.
          ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
      27.
          lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
      28.
          SelectObject(OffscrDC, OldBmp);
      29.
          if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, NULL, lpbi, DIB_RGB_COLORS))
      30.
          return 0;
      31.
          if ((lpvBits = new char[lpbi->bmiHeader.biSizeImage]) == NULL)
      32.
          return 0;
      33.
          if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, lpvBits, lpbi, DIB_RGB_COLORS))
      34.
          return 0;
      35.
          if ((BmpFile = CreateFile(filename,
      36.
          GENERIC_WRITE,
      37.
          0, NULL,
      38.
          CREATE_ALWAYS,
      39.
          FILE_ATTRIBUTE_NORMAL,
      40.
          NULL)) == INVALID_HANDLE_VALUE)
      41.
          return 0;
      42.
          DWORD Written;
      43.
          bmfh.bfType = 19778;
      44.
          bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
      45.
          if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
      46.
          return 0;
      47.
          if (Written < sizeof(bmfh))
      48.
          return 0;
      49.
          if (!WriteFile(BmpFile, &lpbi->bmiHeader, sizeof(BITMAPINFOHEADER), &Written, NULL))
      50.
          return 0;
      51.
          if (Written < sizeof(BITMAPINFOHEADER))
      52.
          return 0;
      53.
          int PalEntries;
      54.
          if (lpbi->bmiHeader.biCompression == BI_BITFIELDS)
      55.
          PalEntries = 3;
      56.
          else PalEntries = (lpbi->bmiHeader.biBitCount <= 8) ?
      57.
          (int)(1 << lpbi->bmiHeader.biBitCount) : 0;
      58.
          if(lpbi->bmiHeader.biClrUsed)
      59.
          PalEntries = lpbi->bmiHeader.biClrUsed;
      60.
          if(PalEntries){
      61.
          if (!WriteFile(BmpFile, &lpbi->bmiColors, PalEntries * sizeof(RGBQUAD), &Written, NULL))
      62.
          return 0;
      63.
          if (Written < PalEntries * sizeof(RGBQUAD))
      64.
          return 0;
      65.
          }
      66.
          bmfh.bfOffBits = GetFilePointer(BmpFile);
      67.
          if (!WriteFile(BmpFile, lpvBits, lpbi->bmiHeader.biSizeImage, &Written, NULL))
      68.
          return 0;
      69.
          if (Written < lpbi->bmiHeader.biSizeImage)
      70.
          return 0;
      71.
          bmfh.bfSize = GetFilePointer(BmpFile);
      72.
          SetFilePointer(BmpFile, 0, 0, FILE_BEGIN);
      73.
          if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
      74.
          return 0;
      75.
          if (Written < sizeof(bmfh))
      76.
          return 0;
      77.
          return 1;
      78.
          }
      79.
          bool ScreenCapture(int x, int y, int width, int height, char *filename){
      80.
          HDC hDc = CreateCompatibleDC(0);
      81.
          HBITMAP hBmp = CreateCompatibleBitmap(GetDC(0), width, height);
      82.
          SelectObject(hDc, hBmp);
      83.
          BitBlt(hDc, 0, 0, width, height, GetDC(0), x, y, SRCCOPY);
      84.
          bool ret = SaveBMPFile(filename, hBmp, hDc, width, height);
      85.
          DeleteObject(hBmp);
      86.
          return ret;
      87.
          }
      88.
           
      89.
          int main() {
      90.
          int x1 = 0;
      91.
          int y1 = 0;
      92.
          int x2 = GetSystemMetrics(SM_CXSCREEN);
      93.
          int y2 = GetSystemMetrics(SM_CYSCREEN);
      94.
          ScreenCapture(x1, y1, x2 - x1, y2 - y1, "rename_me_before_upload.bmp");
      95.
          cin.ignore();
      96.
          return 0;
      97.
          }

  2. #2
    Join Date
    Apr 2009
    Posts
    598

    Re: Vista/Win7 Ingame-Screens are black :( GETDC Problem?

    I think the problem comes from the lack of reservation of space for the bytes of the header of the bitmap and the bitmap itself.

    In the example, you have these allocations at lines 24 and 31. They are missing in your code.

  3. #3
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Vista/Win7 Ingame-Screens are black :( GETDC Problem?

    The code is fragmented and so it is hard to follow. It looks like you are getting a windowID for some window and trying to capture from its DC directly. I don't know about desktop composition, but that may be the problem. In some of the capture utilities I've seen, they capture individual windows in the same way they do an entire screen capture; however, they just limit the bitblt to the rectangle of the window being captured. This might work in your case.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured