#include "wx/frame.h"
#endif
-#include "wx/dynload.h"
+#include "wx/dynlib.h"
#include "wx/sysopt.h"
#include "wx/display_impl.h"
#include "wx/msw/wrapwin.h"
#include "wx/msw/missing.h"
#include "wx/msw/private.h"
+#include "wx/msw/private/hiddenwin.h"
#ifndef __WXWINCE__
// Older versions of windef.h don't define HMONITOR. Unfortunately, we
// m_displays array if they're available
wxDisplayFactoryMSW();
+ // Dtor destroys the hidden window we use for getting WM_SETTINGCHANGE.
+ virtual ~wxDisplayFactoryMSW();
+
bool IsOk() const { return !m_displays.empty(); }
virtual wxDisplayImpl *CreateDisplay(unsigned n);
virtual int GetFromPoint(const wxPoint& pt);
virtual int GetFromWindow(const wxWindow *window);
+ // Called when we receive WM_SETTINGCHANGE to refresh the list of monitor
+ // handles.
+ static void RefreshMonitors() { ms_factory->DoRefreshMonitors(); }
+
+
private:
// EnumDisplayMonitors() callback
static BOOL CALLBACK MultimonEnumProc(HMONITOR hMonitor,
// return wxNOT_FOUND if not found
int FindDisplayFromHMONITOR(HMONITOR hmon) const;
+ // Update m_displays array, used by RefreshMonitors().
+ 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 array containing information about all available displays, filled by
// MultimonEnumProc()
wxMonitorHandleArray m_displays;
+ // The hidden window we use for receiving WM_SETTINGCHANGE and its class
+ // name.
+ HWND m_hiddenHwnd;
+ const wxChar* m_hiddenClass;
+
wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMSW);
};
+wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL;
// ----------------------------------------------------------------------------
// wxDisplay implementation
// do change the mode
switch ( pfnChangeDisplaySettingsEx
(
- GetName().wx_str(), // display name
+ GetName().t_str(), // display name
pDevMode, // dev mode or NULL to reset
NULL, // reserved
flags,
// wxDisplayFactoryMSW implementation
// ----------------------------------------------------------------------------
+LRESULT APIENTRY
+wxDisplayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if ( msg == WM_SETTINGCHANGE )
+ {
+ wxDisplayFactoryMSW::RefreshMonitors();
+
+ return 0;
+ }
+
+ return ::DefWindowProc(hwnd, msg, wParam, 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;
+
if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL
|| gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
{
|| gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
return;
- // enumerate all displays
+ DoRefreshMonitors();
+
+ // Also create a hidden window to listen for WM_SETTINGCHANGE that we
+ // receive when a monitor is added to or removed from the system as we must
+ // refresh our monitor handles information then.
+ m_hiddenHwnd = wxCreateHiddenWindow
+ (
+ &m_hiddenClass,
+ wxT("wxDisplayHiddenWindow"),
+ wxDisplayWndProc
+ );
+}
+
+wxDisplayFactoryMSW::~wxDisplayFactoryMSW()
+{
+ if ( m_hiddenHwnd )
+ {
+ if ( !::DestroyWindow(m_hiddenHwnd) )
+ {
+ wxLogLastError(wxT("DestroyWindow(wxDisplayHiddenWindow)"));
+ }
+
+ if ( m_hiddenClass )
+ {
+ if ( !::UnregisterClass(m_hiddenClass, wxGetInstance()) )
+ {
+ wxLogLastError(wxT("UnregisterClass(wxDisplayHiddenWindow)"));
+ }
+ }
+ }
+
+ ms_factory = NULL;
+}
+
+void wxDisplayFactoryMSW::DoRefreshMonitors()
+{
+ m_displays.Clear();
+
if ( !gs_EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) )
{
wxLogLastError(wxT("EnumDisplayMonitors"));
int wxDisplayFactoryMSW::GetFromWindow(const wxWindow *window)
{
+#ifdef __WXMSW__
return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window),
MONITOR_DEFAULTTONULL));
+#else
+ const wxSize halfsize = window->GetSize() / 2;
+ wxPoint pt = window->GetScreenPosition();
+ pt.x += halfsize.x;
+ pt.y += halfsize.y;
+ return GetFromPoint(pt);
+#endif
}
#endif // wxUSE_DISPLAY
+
+void wxClientDisplayRect(int *x, int *y, int *width, int *height)
+{
+#if defined(__WXMICROWIN__)
+ *x = 0; *y = 0;
+ wxDisplaySize(width, height);
+#else
+ // Determine the desktop dimensions minus the taskbar and any other
+ // special decorations...
+ RECT r;
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ if (x) *x = r.left;
+ if (y) *y = r.top;
+ if (width) *width = r.right - r.left;
+ if (height) *height = r.bottom - r.top;
+#endif
+}