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.
This commit is contained in:
dasimx
2019-03-31 13:18:41 +02:00
committed by Vadim Zeitlin
parent 8927d7b092
commit f3c5923e1a

View File

@@ -594,10 +594,10 @@ void wxDisplayFactoryMSW::DoRefreshMonitors()
{ {
m_displays.clear(); m_displays.clear();
// We need to pass a valid HDC here in order to get valid hdcMonitor in our // Note that we pass NULL as first parameter here because using screen HDC
// callback. // doesn't work reliably: notably, it doesn't enumerate any displays if
ScreenHDC dc; // this code is executed while a UAC prompt is shown or during log-off.
if ( !::EnumDisplayMonitors(dc, NULL, MultimonEnumProc, (LPARAM)this) ) if ( !::EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) )
{ {
wxLogLastError(wxT("EnumDisplayMonitors")); wxLogLastError(wxT("EnumDisplayMonitors"));
} }
@@ -607,13 +607,24 @@ void wxDisplayFactoryMSW::DoRefreshMonitors()
BOOL CALLBACK BOOL CALLBACK
wxDisplayFactoryMSW::MultimonEnumProc( wxDisplayFactoryMSW::MultimonEnumProc(
HMONITOR hMonitor, // handle to display monitor 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 LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle
LPARAM dwData) // data passed from EnumDisplayMonitors (this) LPARAM dwData) // data passed from EnumDisplayMonitors (this)
{ {
wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData; wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData;
self->m_displays.push_back(wxDisplayInfo(hMonitor, wxGetHDCDepth(hdcMonitor))); WinStruct<MONITORINFOEX> 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 // continue the enumeration
return TRUE; return TRUE;