【音视频】Windows下获取App窗口缩略图优化(6-1)

前一篇文章《【音视频】获取桌面程序窗口列表以及桌面、窗口的缩略图(4-4)》获取App窗口缩略图有一点瑕疵,经过felicityWSH的指点,自己抽空研究了下,终于将其优化了,感谢!

本章采用了DWM(Desktop Window Manage)技术解决采集App缩略图遗留的问题,主要用到DwmRegisterThumbnail、DwmUpdateThumbnailProperties和DwmUnregisterThumbnail。因为主要针对采集缩小化的窗口缩略图采集不到问题,所以思路如下:依然遍历所有App窗口,如果没有最小化那么按照原来思路采集,如果是最小化窗口,则使用DWM将最小化窗口显示在自己创建的Layered窗口X上面,窗口X远离屏幕显示区域显示,接着用原来的采集方法采集X的缩略图即可。

修改App窗口枚举方法:

BOOL CALLBACK VideoDevice::enumWindowProc(HWND hwnd, LPARAM dwData)
{
	std::list<VIDEO_DEVICE>* devices = reinterpret_cast<std::list<VIDEO_DEVICE>*>(dwData);
	/* 省略 */
	VIDEO_DEVICE device = {};
	/* 省略 */
	if (!device.id.empty() && !device.name.empty()) {
		int err;
		if (IsIconic(hwnd)) { // 窗口最小化
			err = registerThumbnailWindow(hwnd, device.thumbnail);
		}
		else {
			err = allocWindowThumbnail(hwnd, device.thumbnail);
		}
		/* 省略 */
		devices->push_back(device);
	}
	return TRUE;
}

实现缩略图窗口注册方法:

int VideoDevice::registerThumbnailWindow(HWND hWnd, VIDEO_THUMBNAIL& thumbnailInfo)
{
	if (m_layeredThumbnailWindow == nullptr) {
		m_layeredThumbnailWindow = createLayeredWindow();
	}
	if (m_layeredThumbnailWindow == nullptr) {
		return ERROR_CODE_NULL_POINTER;
	}

	HTHUMBNAIL thumbnail = NULL;
	HRESULT hr = DwmRegisterThumbnail(m_layeredThumbnailWindow, hWnd, &thumbnail);
	if (FAILED(hr)) {
		return ERROR_CODE_DEVICE_REGISTER_THUMBNAIL_FAILED;
	}

	RECT dest;
	GetClientRect(m_layeredThumbnailWindow, &dest);

	DWM_THUMBNAIL_PROPERTIES dskThumbProps;
	dskThumbProps.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_VISIBLE | DWM_TNP_SOURCECLIENTAREAONLY | DWM_TNP_OPACITY;
	dskThumbProps.fSourceClientAreaOnly = FALSE;
	dskThumbProps.fVisible = TRUE;
	dskThumbProps.rcDestination = dest;
	dskThumbProps.opacity = 255;

	hr = DwmUpdateThumbnailProperties(thumbnail, &dskThumbProps);
	if (FAILED(hr)) {
		DwmUnregisterThumbnail(thumbnail);
		return ERROR_CODE_DEVICE_UPDATE_THUMBNAIL_PROPERTY_FAILED;
	}

	// 使用原来方法采集缩略图
	allocWindowThumbnail(m_layeredThumbnailWindow, thumbnailInfo);
	DwmUnregisterThumbnail(thumbnail);
	return ERROR_CODE_OK;
}

创建Layered窗口用来显示最小化的App:

HWND VideoDevice::createLayeredWindow()
{
	WNDCLASS wndCls;
	wndCls.cbClsExtra = 0;
	wndCls.cbWndExtra = 0;
	wndCls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndCls.hCursor = nullptr;
	wndCls.hInstance = nullptr;
	wndCls.hIcon = nullptr;
	wndCls.lpfnWndProc = layeredWindowProc;
	wndCls.lpszClassName = L"Capture Minimize Window Class";
	wndCls.lpszMenuName = nullptr;
	wndCls.style = CS_NOCLOSE;
	// 注册自己的窗口类
	RegisterClass(&wndCls);

	HWND hWnd = CreateWindow(wndCls.lpszClassName, L"Capture Minimize Window", WS_POPUPWINDOW, -32000, -32000, 640, 360, nullptr, nullptr, nullptr, nullptr);
	if (hWnd == nullptr) {
		return nullptr;
	}
	ShowWindow(hWnd, SW_SHOWNORMAL);

	// 去除任务栏缩略图显示
	SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);

	UpdateWindow(hWnd);
	return hWnd;
}

窗口类方法使用默认调用方式即可:

LRESULT CALLBACK VideoDevice::layeredWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

删除allocWindowThumbnail方法中原来处理最小化App窗口的片段:
在这里插入图片描述
在这里插入图片描述
至此,获取App窗口缩略图优化完成,完美收尾!只要不断努力钻研,有朝一日定有收获。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值