From f3c5923e1a6f66b2e5fb8852b0e288f073a6b83e Mon Sep 17 00:00:00 2001 From: dasimx Date: Sun, 31 Mar 2019 13:18:41 +0200 Subject: [PATCH] Fix refreshing display information in wxMSW in some special cases Passing screen HDC to EnumDisplayMonitors() doesn't work if we do it while a UAC prompt is shown or during log-off process, so change the code enumerating the displays to use monitor-appropriate HDC instead. This fixes the problem with losing display information entirely if WM_SETTINGSCHANGE was generated when showing UAC prompt, as it happens when "automatic background color" option is set under Windows 10. --- src/msw/display.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/msw/display.cpp b/src/msw/display.cpp index 7c23d54f15..6c783971be 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -594,10 +594,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")); } @@ -607,13 +607,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;