2016-03-03 164 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