Rya*_*yan 3 c++ windows winapi screenshot
我正在编写一些代码,它将截取另一个应用程序,给出它的'窗口句柄,用C++编写.我正在使用的方法是使用BitBlt.我的应用程序成功截取屏幕截图,我有一个功能,将该图像数据保存到bmp文件.
截图包含窗口的chrome.也就是边框和标题栏.根据我的理解,GetClientRect应该排除窗口的边框和标题栏.据我所知,GetWindowRect返回用户桌面内的坐标,并GetClientRect返回相对于应用程序本身的坐标.
我在屏幕截图中注意到标题栏和左边框是可见的,但应用程序的右边框和底部被切断了.所以,我在想,如果我要排除的标题和边框,然后我需要做某种组合的GetWindowRect和GetClientRect,并使用有关窗口本身的信息,以抵消GetClientRect尺寸以任何窗口的标题栏的高度, 例如.
这听起来是否准确,或者我的代码是否在做错了?
#include <Windows.h>
#include "ScreenshotManager.h"
namespace Managers {
    ScreenshotManager::ScreenshotManager(HWND gameHandle) {
        // get a device context for the window
        m_gameContext = GetWindowDC(gameHandle);
        // create a compatible device context for bitblt
        m_bitmapContext = CreateCompatibleDC(m_gameContext);
        // get window client area dimensions
        GetClientRect(gameHandle, &m_gameClientArea);
    }
    bool ScreenshotManager::TakeScreenshot() {
        // create a compatible bitmap for the game screenshots
        m_bitmap = CreateCompatibleBitmap(m_gameContext, m_gameClientArea.right, m_gameClientArea.bottom);
        // select the bitmap into the compatible device context
        SelectObject(m_bitmapContext, m_bitmap);
        // perform bit block transfer
        if (BitBlt(m_bitmapContext, 0, 0, m_gameClientArea.right, m_gameClientArea.bottom, m_gameContext, 0, 0, SRCCOPY) == false)
            return false;
        // get information about the taken screenshot
        GetObject(m_bitmap, sizeof(BITMAP), &m_bitmapInformation);
        return true;
    }
    void ScreenshotManager::SaveScreenshot(LPCWSTR outputPath) {
        BITMAPFILEHEADER   bmfHeader;    
        BITMAPINFOHEADER   bi;
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = m_bitmapInformation.bmWidth;
        bi.biHeight = m_bitmapInformation.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 = ((m_bitmapInformation.bmWidth * bi.biBitCount + 31) / 32) * 4 * m_bitmapInformation.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(m_gameContext, m_bitmap, 0, (UINT)m_bitmapInformation.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
        // A file is created, this is where we will save the screen capture.
        HANDLE hFile = CreateFile(outputPath, 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);
    }
}
GetClientRect()不包括边框和标题栏.它只是告诉你客户区的尺寸.
BitBlt()从一个设备上下文复制矩形像素区域到另一个设备上下文.在此示例中,源DC是窗口 DC,因此原点坐标是相对于该窗口的.
你的代码正在做的是从窗口的原点复制一个客户端大小的矩形.(这就是为什么右边和底边都会丢失的原因.)
您可能有兴趣AdjustWindowRectEx()帮助确定要复制的区域的坐标.