2016-03-03 102 views
0

我有一个应用程序有几个窗口,我希望它们中的一些(我将调用CMyLockedFrameWndEx,因为它们派生自CFrameWndEx)保持放置在改变系统显示区域后的位置。 我的应用程序的所有窗口的父项都是NULL。锁定窗口位置显示更改

我已经设法已经赶上WM_DISPLAYCHANGE消息时,我把第二台显示器的位置相对第一个;当我连接或断开第二台显示器的HDMI电缆时,我也赶上了WM_DEVICECHANGE。我在CMyLockedFrameWndEx::WindowProc截获了他们。

之后发生自动窗口重新定位。我注意到,因为我已在CMyLockedFrameWndEx::OnWindowPosChangingCMyLockedFrameWndEx::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); 
} 

和传递OnWindowPosChangingOnWindowPosChanged时,流量并非来自由我处理的WindowProc的具体情况。这是一个问题。

我试图按照调用堆栈来查看哪些窗口发送了WM_WINDOWPOSCHANGINGWM_WINDOWPOSCHANGED消息,但我没有成功。我甚至试图使用Spy ++ 64来检测邮件的发件人是谁,但我没有成功。看到谁是发送者的整个想法是:如果它与系统的显示相关联,则更改是事先检测并且弹出自动重新定位甚至发生。

因为我还没有成功,我能做些什么来使窗口免疫系统的显示变化?

谢谢。

+0

请问您能解释一下:当您连接第二个屏幕时,位于第一个屏幕上的窗口发生了什么,例如(100,100)?它移动吗?去哪儿? –

+0

问题不在那里。问题是当我断开第二个屏幕时,我不希望系统自动将窗口放在第一个窗口上。即使断开电缆连接,我也希望窗口继续在第二个屏幕上的位置。当然,这将是** HIDDEN **,但这是我正在寻找的。 – sergiol

回答

0

这个不幸的消息是,我不能这样做对预防方式,因为该系统甚至发送任何有用的消息后,移动窗口到主屏幕。

好消息是,我可以通过添加类的消息映射在

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_Topm_Left变量中的位置。

1

好消息是:很明显,您是在控制自己窗口的位置。

坏消息 - Windows将第一你的窗口移动到新位置,然后发送给您的WM_DISPLAYCHANGEWM_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; 
} 
+0

我还没有接受你的答案,因为我可以设法使用'ON_WM_WINDOWPOSCHANGED()'和它的各自的处理函数'OnWindowPosChanged'来做到这一点 – sergiol

+0

@sergiol - 抱歉,我不明白...你管理或你不? –

+0

我做了,但没有与您的代码。它有点类似,但我设法使用“ON_WM_WINDOWPOSCHANGED()”及其相应的处理函数“OnWindowPosChanged” – sergiol