Windows下ppt放映获取不到窗口的问题

一、问题

在屏幕分享或者投屏,选择单个应用窗口进行分享或者投屏时,当我们选择了PPT的窗口,如果在分享的中途,点击了放映PPT,此时会新创建一个窗口,句柄HWND也会不一样,但是此时远端看到的还是我们最开始那个PPT窗口

二、要求

1、PPT放映后可以自动切换到PPT幻灯片放映窗口,并且结束放映后可以自动切换到原来的窗口

2、使用 Alt + Tab 键可以自动切换PPT放映窗口和原窗口

三、实现步骤(假设我们这里已经拿到了最开始的那个可以编辑的PPT窗口句柄hwnd)

1、先来看一下使用office和wps时PPT窗口的一些不同属性 

 officewps
 PPT编辑窗口PPT放映窗口PPT编辑窗口PPT放映窗口
exe名称

win10:POWERPNT.EXE

win7  :POWERPNT.exe

win10:POWERPNT.EXE

win7  :POWERPNT.exe

wps.exe

wpp.exe
窗口句柄不同不同不同不同
进程pid相同相同不同不同
大小可变化全屏可变化全屏

 

 

 

 

 

 

 

2、根据以上属性找到PPT放映窗口

1、将最开始的窗口句柄保存两份

2、如果当前捕获的创建exe名称为POWERPNT.EXE或者是wps.exe

3、获取当前置顶的窗口exe名称(这一步也可以轮询所有的exe,然后找到exe名字为POWERPNT.EXE或者是wpp.exe的窗口,并且判断是否最大化)

4、判断当前置顶窗口exe名称是不是POWERPNT.EXE、wps.exe、wpp.exe其中的一个

5、如果是再判断当前窗口句柄和上一次捕获的窗口句柄是否相同,如果相同那么则不做处理。

如果不同:

(1)  判断当前置顶的窗口是不是全屏的,如果是全屏并且当前窗口不是全屏的,那么则切换窗口句柄为置顶窗口的句柄

(2)  如果不是全屏并且上一次捕获窗口是全屏的,而且当前置顶窗口和我们最开始捕获的窗口一致,那么也切换窗口句柄为当前置顶的窗口句柄

四、具体代码

static std::vector<string> SpecialProcNameList{ "powerpnt.exe", "wps.exe" };
static std::vector<string> originProcNameList{ "wps.exe" };
static std::vector<string> changeProcNameList{ "wpp.exe" };
// 大写转换成小写
void UpperToLower(std::string& upper)
{
	std::string lower;
	for (int i = 0; i < upper.length(); ++i)
	{
		if ('A' <= upper[i] && 'Z' >= upper[i])
		{
			upper[i] = upper[i] + 32;
		}
	}
}
// 枚举显示器的大小
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
	std::vector<RECT> * pRect = (std::vector<RECT>*)dwData;
	MONITORINFO monitorinfo;
	monitorinfo.cbSize = sizeof(MONITORINFO);
	GetMonitorInfo(hMonitor, &monitorinfo);
	pRect->push_back(monitorinfo.rcMonitor);
	return true;
}
// 判断是不是全屏的
bool CheckFullscreen(HWND hwnd)
{
	std::vector<RECT> monitorRect;
	EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitorRect);
	RECT rect;
	GetWindowRect(hwnd, &rect);
	for (int i = 0; i < monitorRect.size(); ++i) {
		if (rect.left <= monitorRect[i].left &&
			rect.top <= monitorRect[i].top &&
			rect.right >= monitorRect[i].right &&
			rect.bottom >= monitorRect[i].bottom)
		{
			return true;
		}
	}
	return false;
}
// 获取当前置顶窗口
HWND GetCurrentTopWindow()
{
	return ::GetForegroundWindow();
}
// 获取进程id
DWORD GetProcessId(HWND hwnd)
{
	DWORD dwProcId;
	::GetWindowThreadProcessId(hwnd, &dwProcId);
	return dwProcId;
}
// 获取进程名称,比如wps.exe
std::string GetProcessName(DWORD procId)
{
	HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, procId);
	char wndName[MAX_PATH] = "";
	GetProcessImageFileNameA(hProc, wndName, MAX_PATH);
	CloseHandle(hProc);
 
	std::string name = wndName;
	auto pos = name.rfind("/");
	if (pos == std::string::npos) {
		pos = name.rfind("\\");
	}
	if (pos == std::string::npos) {
		return "";
	}
	return name.substr(pos + 1, name.length() - pos);
}
// 判断exe name是不是我们想要的
bool IsSameWindow(HWND topWnd, HWND shareWnd) {
	std::string topWndName = GetProcessName(GetProcessId(topWnd));
	std::string shareWndName = GetProcessName(GetProcessId(shareWnd));
	if (topWndName == shareWndName)
	{
		return true;
	}
	if (originProcNameList.size() != changeProcNameList.size()) {
		return false;
	}
	UpperToLower(topWndName);
	UpperToLower(shareWndName);
	for (int i = 0; i < originProcNameList.size(); ++i) {
		if (topWndName == originProcNameList[i] && shareWndName == changeProcNameList[i] || topWndName == changeProcNameList[i] && shareWndName == originProcNameList[i])
		{
			return true;
		}
	}
	return false;
}
 
// orignWnd和targetWnd是最开始存下来的两个句柄
// targetWnd:表示要捕获的窗口句柄
// orignWnd:表示最开始选择的那个窗口句柄
void Capture()
{
    std::vector<std::string>::iterator iter = std::find(SpecialProcNameList.begin(), SpecialProcNameList.end(), m_procName);
	if (iter != SpecialProcNameList.end())
	{
		if (!IsWindow(targetWnd) && IsWindow(orignWnd))
		{
			targetWnd = orignWnd;
		}
		else if (IsWindow(targetWnd)) {
			HWND hwnd = GetCurrentTopWindow();
			if ((targetWnd== orignWnd&& CheckFullscreen(hwnd) ||
				hwnd == orignWnd&& hwnd != targetWnd) &&
				IsSameWindow(hwnd, targetWnd))
			{
				m_hTARGETWND = hwnd;
			}
		}
	}
    ......
 
}

五、遗留问题

1、放映多个PPT时会导致画面错乱

2、外接显示器的情况下,放映PPT,除了轮询暂时没有想到更好的办法找到全屏的窗口

关于上面两个问题,如果有更好的想法,请多多指教

四、参考文章

1、多显示器下判断ppt是否播放

3、MFC实时监测ppt是否在播放

4、Windows检测PPT,WPS幻灯片播放并获取窗口句柄

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值