2016-03-03 4 views
0

У меня есть приложение, которое имеет несколько окон, и я хочу, чтобы некоторые из них (которые я назову CMyLockedFrameWndEx, потому что они происходят от CFrameWndEx) остаются там, где они были после изменения области отображения системы. Родитель всех окон моего приложения NULL.Положение окна замка на дисплее изменяется

Мне удалось поймать сообщение WM_DISPLAYCHANGE, когда я перетаскиваю позицию второго монитора относительно первого; и я также пришел, чтобы поймать WM_DEVICECHANGE, когда я подключаю или отсоединяю кабель HDMI второго монитора. Я перехватил их обоих в CMyLockedFrameWndEx::WindowProc.

После этого происходит автоматическое переключение окна. Я заметил, что bacause я поставил точки останова на 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, чтобы определить, кто был отправителем сообщения, но мне это не удалось. Вся идея увидеть, кто был отправителем, заключалась в том, что если это связано с изменением отображения системы, необходимо заранее обнаружить ее и импичтировать авторепозицию, чтобы даже произойти.

Как я еще не успел, что я могу сделать, чтобы окно не повлияло на изменение отображения системы?

Спасибо.

+0

Не могли бы вы объяснить: что происходит с окном, расположенным на первом экране, например, (100,100) при подключении второго экрана? Это движется? Куда? –

+0

Проблема не там. Проблема в том, что когда я отключу второй экран, я не хочу, чтобы система автоматически помещала окно на 1-ое. Я хочу, чтобы окно продолжало свое положение на втором экране, даже если я отсоединяю кабель. Конечно, это будет ** 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_Left.

1

Хорошая новость: вы, очевидно, контролируете размещение собственного окна.

Плохая новость - Windows будет первый переместить окно в новое положение, затем отправить вам WM_DISPLAYCHANGE и WM_SETTINGCHANGE, как видно в журнале это Spy ++ s:

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

 Смежные вопросы

  • Нет связанных вопросов^_^