在Win10系统中,把C++程序“消失的”窗口“拽”出来显示
Posted dvlinker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Win10系统中,把C++程序“消失的”窗口“拽”出来显示相关的知识,希望对你有一定的参考价值。
程序启动时会创建主窗口,初始不显示主窗口或者将主窗口掩藏起来,待底层模块初始化完成后,再将主窗口显示出来。结果在两个同事的win10系统上都频繁出现启动程序后窗口不显示的问题。
我们在显示主窗口时,先是调用ShowWindow将窗口显示出来,然后调用SetForegroundWindow将窗口拉到前端显示,但窗口还是显示不出来。正常情况下,我们调用ShowWindow和SetForegroundWindow之后就能将掩藏的窗口显示出来的。
难道程序启动时UI线程有堵塞或者卡死?难道UI线程有死循环发生,或者调用底层的接口没有返回(底层的函数发生了堵塞)?首先查看Windows任务管理器中我们程序进程的CPU占用情况,结果都正常,应该不是死循环问题触发的。然后将windbg附加到程序进程上,使用~0s切换到UI线程中,多次go多次打印出UI线程的函数调用堆栈,确定UI线程并没有发生堵塞或卡死问题。
难道是窗口的位置坐标有问题?窗口跑到桌面区域之外去了?于是添加打印,将窗口的位置坐标打印出来,窗口坐标是正常的,是在桌面区域之内的。后来又对该窗口调用IsWindowVisible API函数,将该函数的返回值打印出来,看看窗口是否处于显示状态,结果发现IsWindowVisible返回的是TRUE,即窗口已经处于显示状态了。
然后又在SPY++中以窗口类名搜索到该窗口,查看窗口风格,已经具有WS_VISIBLE标识,也表明窗口已经处于显示状态。种种排查手段都表明窗口已经处于显示状态了,但实际上还是看不到这个窗口,这也太诡异了!更诡异的是,在一个同事的机器上,点击任务栏中其他程序的窗口,会将我们的程序的窗口带出来。
既然找不出问题的原因,只能采取规避的办法将问题规避掉。后来尝试了几种规避的方法,都可以将窗口调出来,下面将两种方法分享出来。
1、将窗口向旁边移动几个像素,然后再将窗口移动到原来的位置,代码如下:
// 获取窗口原来的位置
RECT rcDlg;
::GetWindowRect( m_pMainDlg->GetHWND(), &rcDlg);
// 将窗口向左上角移动两个像素
int nXPos = rcDlg.left - 2;
int nYPos = rcDlg.top - 2;
int nWidth = rcDlg.right - rcDlg.left;
int nHeight = rcDlg.bottom - rcDlg.top;
::MoveWindow(m_pMainDlg->GetHWND(), nXPos, nYPos, nWidth, nHeight, TRUE);
// 将窗口移动到原来的位置
nXPos = rcLoginDlg.left + 2;
nYPos = rcLoginDlg.top + 2;
::MoveWindow(m_pMainDlg->GetHWND(), nXPos, nYPos, nWidth, nHeight, TRUE);
这种方法有点小问题,因为来回移动窗口,虽然只移动了几个像素,可能会有窗口闪动的问题。所以我们采用了第二种方法。
2、先将窗口置顶,然后再将窗口取消置顶,代码如下:
::SetWindowPos(m_pMainDlg->GetHWND(), HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOSIZE | SWP_NOMOVE);
::SetWindowPos(m_pMainDlg->GetHWND(), HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOSIZE | SWP_NOMOVE);
以上是关于在Win10系统中,把C++程序“消失的”窗口“拽”出来显示的主要内容,如果未能解决你的问题,请参考以下文章