gpt4 book ai didi

c++ - 为什么 GetClientRect 包括窗口边框和标题栏?

转载 作者:太空狗 更新时间:2023-10-29 19:59:47 31 4
gpt4 key购买 nike

我正在编写一些代码,在给定窗口句柄的情况下,使用 C++ 截取另一个应用程序的屏幕截图。我使用的方法是使用BitBlt。我的应用程序成功截取了屏幕截图,并且我有一个函数可以将该图像数据保存到 bmp 文件中。

虽然屏幕截图包含窗口的镶边。即边框和标题栏。根据我的理解,GetClientRect 应该排除窗口的边框和标题栏。我知道 GetWindowRect 返回用户桌面内的坐标,而 GetClientRect 返回相对于应用程序本身的坐标。

我注意到在我的屏幕截图中,标题栏和左边框是可见的,但应用程序的右边框和底部被截断了。所以,我在想,如果我想排除标题和边框,那么我需要对 GetWindowRectGetClientRect 进行某种组合,并使用有关例如,无论窗口标题栏的高度是多少,窗口本身都会偏移 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() 感兴趣以帮助识别您要复制的区域的坐标。

关于c++ - 为什么 GetClientRect 包括窗口边框和标题栏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11066923/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com