前言
最近学习了Windows下的屏幕截图,延伸到窗口截图,其中也遇到了不少的坑,好在最后还是实现了我的目标。顺便封装了一下Win32的api,方便后续使用。
屏幕和窗口截图
首先是先找了MS官方的屏幕截图示例,不过并没有很符合我的要求,不过也受到启发,使用窗口DC获取窗口图像。
枚举屏幕和窗口
为了将屏幕和窗口进行统一,我们定义一个结构体
//1. 屏幕的hwnd为NULL,这时截图的区域由rect指定
//2. 窗口的hwnd不为空,这时可以根据API获取窗口的大小
// 为了将屏幕和窗口进行统一,因此使用了结构体
struct WindowInfo
{
HWND hwnd; /* 为空表示屏幕截图 */
std::string desc; // 窗口标题
RECT rect{
0,0,0,0 }; /* hwnd不为空时,此参数无效 */
};
- 如果电脑上有多个显示器,并且我们想截取指定的屏幕怎么办呢?这时就需要枚举显示器的API
- 要截图指定的窗口,那我们要先知道窗口的句柄,如何获取呢?这时也需要枚举窗口的API或者获取当前鼠标指向的窗口
// 判断当前鼠标指向哪个窗口 HWND GetCurPointedWindow() { POINT point; BOOL ret = GetCursorPos(&point); if (ret) { HWND hwnd = WindowFromPoint(point); if (hwnd != nullptr && hwnd != INVALID_HANDLE_VALUE) { return hwnd; } } return nullptr; }
封装好的枚举类,使用示例在后面:
class Enumerator
{
public:
using EnumCallback = std::function<void(const WindowInfo &)>;
static bool EnumMonitor(EnumCallback callback)
{
// 调用Win32Api进行显示器遍历
return ::EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&callback);
}
static bool EnumWindow(EnumCallback callback)
{
// 调用Win32Api进行窗口遍历
return ::EnumWindows(EnumWindowsProc, (LPARAM)&callback);
}
private:
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
//::GetParent获取的有可能是所有者窗口,因此使用GetAncestor获取父窗口句柄
HWND parent