diff --git a/samples/display/display.cpp b/samples/display/display.cpp index ed5420d147..2d5b264dcb 100644 --- a/samples/display/display.cpp +++ b/samples/display/display.cpp @@ -81,6 +81,9 @@ public: void OnLeftClick(wxMouseEvent& event); private: + // Fill m_book with the information about all the displays. + void PopuplateWithDisplayInfo(); + #if wxUSE_DISPLAY // convert video mode to textual description wxString VideoModeToText(const wxVideoMode& mode); @@ -233,6 +236,11 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, // create child controls m_book = new wxBookCtrl(this, wxID_ANY); + PopuplateWithDisplayInfo(); +} + +void MyFrame::PopuplateWithDisplayInfo() +{ const size_t countDpy = wxDisplay::GetCount(); for ( size_t nDpy = 0; nDpy < countDpy; nDpy++ ) { @@ -426,16 +434,8 @@ void MyFrame::OnLeftClick(wxMouseEvent& event) void MyFrame::OnDisplayChanged(wxDisplayChangedEvent& event) { - // update the current mode text - for ( size_t n = 0; n < m_book->GetPageCount(); n++ ) - { - wxStaticText *label = wxDynamicCast(m_book->GetPage(n)-> - FindWindow(Display_CurrentMode), - wxStaticText); - if ( label ) - label->SetLabel(VideoModeToText(wxDisplay(n).GetCurrentMode())); - } - + m_book->DeleteAllPages(); + PopuplateWithDisplayInfo(); wxLogStatus(this, "Display resolution was changed."); diff --git a/src/msw/display.cpp b/src/msw/display.cpp index 993b3cdaa9..9f1892f07d 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -198,10 +198,6 @@ public: DoRefreshMonitors(); } - // Called when we receive WM_SETTINGCHANGE to refresh the list of monitor - // handles. - static void RefreshMonitors() { ms_factory->InvalidateCache(); } - // Declare the second argument as int to avoid problems with older SDKs not // declaring MONITOR_DPI_TYPE enum. typedef HRESULT (WINAPI *GetDpiForMonitor_t)(HMONITOR, int, UINT*, UINT*); @@ -221,15 +217,9 @@ private: // return wxNOT_FOUND if not found int FindDisplayFromHMONITOR(HMONITOR hmon) const; - // Update m_displays array, used by RefreshMonitors(). + // Update m_displays array, used initially and by InvalidateCache(). void DoRefreshMonitors(); - - // The unique factory being used (as we don't have direct access to the - // global factory pointer in the common code so we just duplicate this - // variable (also making it of correct type for us) here). - static wxDisplayFactoryMSW* ms_factory; - // The pointer to GetDpiForMonitorPtr(), retrieved on demand, and the // related data, including the DLL containing the function that we must // keep loaded. @@ -285,7 +275,6 @@ private: wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMSW); }; -wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL; wxDisplayFactoryMSW::GetDpiForMonitorData wxDisplayFactoryMSW::ms_getDpiForMonitorData; @@ -535,7 +524,8 @@ bool wxDisplayMSW::ChangeMode(const wxVideoMode& mode) LRESULT APIENTRY wxDisplayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if ( msg == WM_SETTINGCHANGE || msg == WM_DISPLAYCHANGE ) + if ( (msg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA) || + msg == WM_DISPLAYCHANGE ) { wxDisplay::InvalidateCache(); @@ -547,12 +537,6 @@ wxDisplayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) wxDisplayFactoryMSW::wxDisplayFactoryMSW() { - // This is not supposed to happen with the current code, the factory is - // implicitly a singleton. - wxASSERT_MSG( !ms_factory, wxS("Using more than one factory?") ); - - ms_factory = this; - m_hiddenHwnd = NULL; m_hiddenClass = NULL; @@ -592,8 +576,6 @@ wxDisplayFactoryMSW::~wxDisplayFactoryMSW() ms_getDpiForMonitorData.UnloadIfNecessary(); ms_getDpiForMonitorData.m_initialized = false; } - - ms_factory = NULL; } /* static */ @@ -613,10 +595,10 @@ void wxDisplayFactoryMSW::DoRefreshMonitors() { m_displays.clear(); - // We need to pass a valid HDC here in order to get valid hdcMonitor in our - // callback. - ScreenHDC dc; - if ( !::EnumDisplayMonitors(dc, NULL, MultimonEnumProc, (LPARAM)this) ) + // Note that we pass NULL as first parameter here because using screen HDC + // doesn't work reliably: notably, it doesn't enumerate any displays if + // this code is executed while a UAC prompt is shown or during log-off. + if ( !::EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) ) { wxLogLastError(wxT("EnumDisplayMonitors")); } @@ -626,13 +608,24 @@ void wxDisplayFactoryMSW::DoRefreshMonitors() BOOL CALLBACK wxDisplayFactoryMSW::MultimonEnumProc( HMONITOR hMonitor, // handle to display monitor - HDC hdcMonitor, // handle to monitor-appropriate device context + HDC /* hdcMonitor */, // handle to monitor-appropriate device context: + // not set due to our use of EnumDisplayMonitors(NULL, ...) LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle LPARAM dwData) // data passed from EnumDisplayMonitors (this) { wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData; - self->m_displays.push_back(wxDisplayInfo(hMonitor, wxGetHDCDepth(hdcMonitor))); + WinStruct monInfo; + if ( !::GetMonitorInfo(hMonitor, &monInfo) ) + { + wxLogLastError(wxT("GetMonitorInfo")); + } + + HDC hdcMonitor = ::CreateDC(NULL, monInfo.szDevice, NULL, NULL); + const int hdcDepth = wxGetHDCDepth(hdcMonitor); + ::DeleteDC(hdcMonitor); + + self->m_displays.push_back(wxDisplayInfo(hMonitor, hdcDepth)); // continue the enumeration return TRUE;