锁定窗口位置显示更改
我有一个应用程序有几个窗口,我希望它们中的一些(我将调用CMyLockedFrameWndEx
,因为它们派生自CFrameWndEx
)保持放置在改变系统显示区域后的位置。 我的应用程序的所有窗口的父项都是NULL。锁定窗口位置显示更改
我已经设法已经赶上WM_DISPLAYCHANGE
消息时,我把第二台显示器的位置相对第一个;当我连接或断开第二台显示器的HDMI电缆时,我也赶上了WM_DEVICECHANGE
。我在CMyLockedFrameWndEx::WindowProc
截获了他们。
之后发生自动窗口重新定位。我注意到,因为我已在CMyLockedFrameWndEx::OnWindowPosChanging
和CMyLockedFrameWndEx::OnWindowPosChanged
上放置了断点,并且在我遇到WindowProc
的事件之后它们停止。这个工作流程似乎是无关我描述成我WindowProc
方法事件的捕捉是:
LRESULT CMyLockedFrameWndEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_DISPLAYCHANGE)
{
TRACE(_T("DISPLAY CHANGE"));
return 0L;
}
if (message == WM_SYSCOMMAND)
{
TRACE(_T("SYSCOMMAND"));
if (wParam == SC_MOVE)
{
return 0L;
}
}
if (message == WM_WININICHANGE)
{
TRACE(_T("WININICHANGE"));
if (wParam == SPI_SETWORKAREA)
{
return 0L;
}
}
return __super::WindowProc(message, wParam, lParam);
}
和传递OnWindowPosChanging
或OnWindowPosChanged
时,流量并非来*我处理的WindowProc
的具体情况。这是一个问题。
我试图按照调用堆栈来查看哪些窗口发送了WM_WINDOWPOSCHANGING
或WM_WINDOWPOSCHANGED
消息,但我没有成功。我甚至试图使用Spy ++ 64来检测邮件的发件人是谁,但我没有成功。看到谁是发送者的整个想法是:如果它与系统的显示相关联,则更改是事先检测并且弹出自动重新定位甚至发生。
因为我还没有成功,我能做些什么来使窗口免疫系统的显示变化?
谢谢。
这个不幸的消息是,我不能这样做对预防方式,因为该系统甚至发送任何有用的消息后,移动窗口到主屏幕。
好消息是,我可以通过添加类的消息映射在
ON_WM_WINDOWPOSCHANGED()
线的移动反应并与其各自的处理函数里面提供:
CMyLockedFrameWndEx::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
__super::OnWindowPosChanged(lpwndpos);
CFrameWndEx* pFrame=(CFrameWndEx*)::AfxGetMainWnd();
VALIDATE_FPTR(pFrame);
CMyDoc* pDoc=(CMyDoc*)pFrame->GetActiveDocument();
VALIDATE_FPTR(pDoc);
POSITION p= pDoc->GetFirstViewPosition();
while(p)
{
CMyLockedView* pLockedView= dynamic_cast<CLockedView*>(pDoc->GetNextView(p));
if(!pLockedView)
continue;
if(pLockedView->GetParentFrame() == this)
{
this->SetWindowPos(NULL, m_Top, m_Left, 0, 0, SWP_NOSIZE);
break;
}
}
}´
注,它可以帮助我保持窗口在m_Top
和m_Left
变量中的位置。
好消息是:很明显,您是在控制自己窗口的位置。
坏消息 - Windows将第一你的窗口移动到新位置,然后发送给您的WM_DISPLAYCHANGE
和WM_SETTINGCHANGE
,如在此间谍++的日志:
S WM_WINDOWPOSCHANGING lpwp:003CF9AC
S WM_GETMINMAXINFO lpmmi:003CF624
R WM_GETMINMAXINFO lpmmi:003CF624
R WM_WINDOWPOSCHANGING
S WM_WINDOWPOSCHANGED lpwp:003CF9AC
S WM_MOVE xPos:278 yPos:450
R WM_MOVE
R WM_WINDOWPOSCHANGED
S WM_SETTINGCHANGE wFlag:SPI_ICONVERTICALSPACING pszMetrics:0026E018
R WM_SETTINGCHANGE
S WM_DISPLAYCHANGE cBitsPerPixel:32 cxScreen:2560 cyScreen:1440
R WM_DISPLAYCHANGE
S WM_SETTINGCHANGE wFlag:SPI_SETWORKAREA pszMetrics:0026E018
R WM_SETTINGCHANGE
所以 - 你将有自己测试改变到另一个屏幕的位置。如在此简单的例子,其中2560
是我的屏幕宽度:
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS* pWP = (WINDOWPOS*)lParam;
if ((pWP->flags & SWP_NOMOVE) == 0) // it's a move
{
if (pWP->x < 2560)
pWP->flags |= SWP_NOMOVE;
}
return 0;
}
请问您能解释一下:当您连接第二个屏幕时,位于第一个屏幕上的窗口发生了什么,例如(100,100)?它移动吗?去哪儿? –
问题不在那里。问题是当我断开第二个屏幕时,我不希望系统自动将窗口放在第一个窗口上。即使断开电缆连接,我也希望窗口继续在第二个屏幕上的位置。当然,这将是** HIDDEN **,但这是我正在寻找的。 – sergiol