2015-02-01 2 views
5

여러 디스플레이 장치가있는 화면 캡처 작업을하고 있습니다. GetDesktopWindow()는 기본 모니터에 대한 핸들 만 가져 오므로 EnumDisplayMonitors()를 사용하여 작업을 시도했습니다.MSDN 라이브러리로 여러 화면 캡쳐

은 MSDN 웹 사이트를 읽은 후, 나는) (주에서이 쓴 :

HDC hdc = GetDC(NULL); 
EnumDisplayMonitors(hdc, NULL, MyCapScreenEnumProc, 0); 
ReleaseDC(NULL, hdc); 

그리고 "BOOL CALLBACK MyCapScreenEnumProc (HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)"콜백

기능, 나는 MSDN:Capturing an Image에서 샘플 기능 " INT CaptureAnImage (HWND HWND)"를 복사 한 다음 수정했다 :

  1. 를 대신 읽기 HWND 파라미터, I는 함수를 선언
  2. 는 RECT
  3. 대한 파라미터 lprcMonitor 사용 디바이스 컨텍스트로 파라미터 hdcMonitor 사용 디바이스 컨텍스트를 연신 코드를 제거 GetDesktopWindow()으로 초기화

    BOOL CALLBACK MyCapScreenEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) 
    { 
        HWND hWnd = GetDesktopWindow(); 
        HDC hdcMemDC = NULL; 
        HBITMAP hbmScreen = NULL; 
        BITMAP bmpScreen; 
    
        //generate a unique file name for the bitmaps 
        static int file_number = 1; 
        stringstream ss; 
        ss << "all_capture_" << file_number++ << ".bmp"; 
        string filename = ss.str(); 
        wstring widestr = wstring(filename.begin(), filename.end()); 
    
        // Create a compatible DC which is used in a BitBlt from the window DC 
        hdcMemDC = CreateCompatibleDC(hdcMonitor); 
    
        if (!hdcMemDC) 
        { 
         MessageBox(hWnd, L"CreateCompatibleDC has failed", L"Failed", MB_OK); 
         goto done; 
        } 
    
        // Get the client area for size calculation 
        RECT rcClient = *lprcMonitor; 
    
        // Create a compatible bitmap from the Window DC 
        hbmScreen = CreateCompatibleBitmap(hdcMonitor, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); 
    
        if (!hbmScreen) 
        { 
         MessageBox(hWnd, L"CreateCompatibleBitmap Failed", L"Failed", MB_OK); 
         goto done; 
        } 
    
        // Select the compatible bitmap into the compatible memory DC. 
        SelectObject(hdcMemDC, hbmScreen); 
    
        // Bit block transfer into our compatible memory DC. 
        if (!BitBlt(hdcMemDC, 
           0, 0, 
           rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, 
           hdcMonitor, 
           0, 0, 
           SRCCOPY)) 
        { 
         MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK); 
         goto done; 
        } 
    
        // Get the BITMAP from the HBITMAP 
        GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen); 
    
        BITMAPFILEHEADER bmfHeader; 
        BITMAPINFOHEADER bi; 
    
        bi.biSize = sizeof(BITMAPINFOHEADER); 
        bi.biWidth = bmpScreen.bmWidth; 
        bi.biHeight = bmpScreen.bmHeight; 
        bi.biPlanes = 1; 
        bi.biBitCount = 32; 
        bi.biCompression = BI_RGB; 
        bi.biSizeImage = 0; 
        bi.biXPelsPerMeter = 0; 
        bi.biYPelsPerMeter = 0; 
        bi.biClrUsed = 0; 
        bi.biClrImportant = 0; 
    
        DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31)/32) * 4 * bmpScreen.bmHeight; 
    
        // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
        // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
        // have greater overhead than HeapAlloc. 
        HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize); 
        char *lpbitmap = (char *)GlobalLock(hDIB); 
    
        // Gets the "bits" from the bitmap and copies them into a buffer 
        // which is pointed to by lpbitmap. 
        GetDIBits(hdcMonitor, hbmScreen, 0, 
           (UINT)bmpScreen.bmHeight, 
           lpbitmap, 
           (BITMAPINFO *)&bi, DIB_RGB_COLORS); 
    
    
    
    
        // A file is created, this is where we will save the screen capture. 
        HANDLE hFile = CreateFile(widestr.c_str(), 
               GENERIC_WRITE, 
               0, 
               NULL, 
               CREATE_ALWAYS, 
               FILE_ATTRIBUTE_NORMAL, NULL); 
    
        // Add the size of the headers to the size of the bitmap to get the total file size 
        DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
    
        //Offset to where the actual bitmap bits start. 
        bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 
    
        //Size of the file 
        bmfHeader.bfSize = dwSizeofDIB; 
    
        //bfType must always be BM for Bitmaps 
        bmfHeader.bfType = 0x4D42; //BM 
    
        DWORD dwBytesWritten = 0; 
        WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 
        WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 
        WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL); 
    
        //Unlock and Free the DIB from the heap 
        GlobalUnlock(hDIB); 
        GlobalFree(hDIB); 
    
        //Close the handle for the file that was created 
        CloseHandle(hFile); 
    
        //Clean up 
        done: 
        DeleteObject(hbmScreen); 
        DeleteObject(hdcMemDC); 
        return TRUE; 
    } 
    
    ,691,363 :
  4. 는 고유 한 파일 이름
  5. 여기

전체 코드를 생성하는 코드를 추가210

그러나 기본 화면을 두 번 캡처하는 것으로 나타났습니다. 두 번째 캡처의 화면 크기가 두 번째 모니터의 화면 크기와 동일합니다. 나는 그 코드에 무엇이 잘못된 것인지 모른다. 누구든지 그것을 지적하거나 작업을 수행하는 더 좋은 방법을 제안 할 수 있습니까? 감사합니다. 당신은 모니터에서 BitBlt 필요

답변

4

하지 영점에서 lprcMonitor에 귀하에게 제공 좌표 :

// Bit block transfer into our compatible memory DC. 
if (!BitBlt(hdcMemDC, 
      0, 0, 
      rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, 
      hdcMonitor, 
      lprcMonitor->left, lprcMonitor->top, // <<--- !!! 
      SRCCOPY)) 
+0

감사합니다! 이것은 문제를 해결했습니다! – Samuel