]> git.saurik.com Git - wxWidgets.git/blame - src/msw/display.cpp
simplify code so it always returns the same object
[wxWidgets.git] / src / msw / display.cpp
CommitLineData
a536e411 1/////////////////////////////////////////////////////////////////////////////
2ad495fb 2// Name: src/msw/display.cpp
a536e411 3// Purpose: MSW Implementation of wxDisplay class
fd921f35
VZ
4// Author: Royce Mitchell III, Vadim Zeitlin
5// Modified by: Ryan Norton (IsPrimary override)
a536e411
JS
6// Created: 06/21/02
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
fd921f35 9// Copyright: (c) 2002-2006 wxWidgets team
65571936 10// Licence: wxWindows licence
a536e411
JS
11/////////////////////////////////////////////////////////////////////////////
12
13// ===========================================================================
14// declarations
15// ===========================================================================
16
17// ---------------------------------------------------------------------------
18// headers
19// ---------------------------------------------------------------------------
20
a536e411
JS
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25 #pragma hdrstop
26#endif
27
28#if wxUSE_DISPLAY
29
7212d155
PC
30#include "wx/display.h"
31
a536e411 32#ifndef WX_PRECOMP
ad9835c9
WS
33 #include "wx/dynarray.h"
34 #include "wx/app.h"
35 #include "wx/frame.h"
a536e411
JS
36#endif
37
2d748a33 38#include "wx/dynlib.h"
ef1717a9 39#include "wx/sysopt.h"
8585e2b5 40
ef1717a9 41#include "wx/display_impl.h"
52778e00 42#include "wx/msw/wrapwin.h"
7212d155 43#include "wx/msw/missing.h"
142ae7b3 44#include "wx/msw/private.h"
ad6f09f5 45#include "wx/msw/private/hiddenwin.h"
a536e411 46
2ad495fb 47#ifndef __WXWINCE__
01c54165 48 // Older versions of windef.h don't define HMONITOR. Unfortunately, we
bcc1153a
VZ
49 // can't directly test whether HMONITOR is defined or not in windef.h as
50 // it's not a macro but a typedef, so we test for an unrelated symbol which
51 // is only defined in winuser.h if WINVER >= 0x0500
52 #if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK)
53 DECLARE_HANDLE(HMONITOR);
e5570318
JS
54 typedef BOOL(CALLBACK * MONITORENUMPROC )(HMONITOR, HDC, LPRECT, LPARAM);
55 typedef struct tagMONITORINFO
56 {
57 DWORD cbSize;
58 RECT rcMonitor;
59 RECT rcWork;
60 DWORD dwFlags;
61 } MONITORINFO, *LPMONITORINFO;
62 typedef struct tagMONITORINFOEX : public tagMONITORINFO
63 {
64 TCHAR szDevice[CCHDEVICENAME];
65 } MONITORINFOEX, *LPMONITORINFOEX;
66 #define MONITOR_DEFAULTTONULL 0x00000000
67 #define MONITOR_DEFAULTTOPRIMARY 0x00000001
68 #define MONITOR_DEFAULTTONEAREST 0x00000002
ad9835c9 69 #define MONITORINFOF_PRIMARY 0x00000001
bcc1153a
VZ
70 #define HMONITOR_DECLARED
71 #endif
2ad495fb 72#endif // !__WXWINCE__
a536e411 73
d238d403
VZ
74// display functions are found in different DLLs under WinCE and normal Win32
75#ifdef __WXWINCE__
9a83f860 76static const wxChar displayDllName[] = wxT("coredll.dll");
d238d403 77#else
9a83f860 78static const wxChar displayDllName[] = wxT("user32.dll");
d238d403
VZ
79#endif
80
a536e411 81// ----------------------------------------------------------------------------
06efac1f 82// typedefs for dynamically loaded Windows functions
a536e411
JS
83// ----------------------------------------------------------------------------
84
8585e2b5
VZ
85typedef LONG (WINAPI *ChangeDisplaySettingsEx_t)(LPCTSTR lpszDeviceName,
86 LPDEVMODE lpDevMode,
87 HWND hwnd,
88 DWORD dwFlags,
89 LPVOID lParam);
a536e411 90
01c54165
VZ
91typedef BOOL (WINAPI *EnumDisplayMonitors_t)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
92typedef HMONITOR (WINAPI *MonitorFromPoint_t)(POINT,DWORD);
93typedef HMONITOR (WINAPI *MonitorFromWindow_t)(HWND,DWORD);
94typedef BOOL (WINAPI *GetMonitorInfo_t)(HMONITOR,LPMONITORINFO);
95
ef1717a9
VZ
96#ifndef __WXWINCE__
97// emulation of ChangeDisplaySettingsEx() for Win95
98LONG WINAPI ChangeDisplaySettingsExForWin95(LPCTSTR WXUNUSED(lpszDeviceName),
99 LPDEVMODE lpDevMode,
100 HWND WXUNUSED(hwnd),
101 DWORD dwFlags,
102 LPVOID WXUNUSED(lParam))
103{
104 return ::ChangeDisplaySettings(lpDevMode, dwFlags);
105}
106#endif // !__WXWINCE__
06efac1f 107
a536e411 108
06efac1f 109// ----------------------------------------------------------------------------
d5947fad 110// wxDisplayMSW declaration
06efac1f
VZ
111// ----------------------------------------------------------------------------
112
d5947fad 113class wxDisplayMSW : public wxDisplayImpl
01c54165 114{
ef1717a9 115public:
d5947fad 116 wxDisplayMSW(unsigned n, HMONITOR hmon)
ef1717a9 117 : wxDisplayImpl(n),
d5947fad 118 m_hmon(hmon)
01c54165 119 {
01c54165 120 }
01c54165 121
ef1717a9 122 virtual wxRect GetGeometry() const;
6c5d6291 123 virtual wxRect GetClientArea() const;
ef1717a9
VZ
124 virtual wxString GetName() const;
125 virtual bool IsPrimary() const;
06efac1f 126
ef1717a9 127 virtual wxVideoMode GetCurrentMode() const;
d5947fad
VZ
128 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
129 virtual bool ChangeMode(const wxVideoMode& mode);
06efac1f 130
ef1717a9
VZ
131protected:
132 // convert a DEVMODE to our wxVideoMode
133 static wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
134 {
135 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one"
136 // and although 0 is ok for us we don't want to return modes with 1hz
137 // refresh
138 return wxVideoMode(dm.dmPelsWidth,
139 dm.dmPelsHeight,
140 dm.dmBitsPerPel,
141 dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
142 }
143
473ca5f3
VZ
144 // Call GetMonitorInfo() and fill in the provided struct and return true if
145 // it succeeded, otherwise return false.
146 bool GetMonInfo(MONITORINFOEX& monInfo) const;
147
d5947fad
VZ
148 HMONITOR m_hmon;
149
150private:
151 wxDECLARE_NO_COPY_CLASS(wxDisplayMSW);
ef1717a9 152};
a536e411 153
d5947fad 154
8585e2b5 155// ----------------------------------------------------------------------------
d5947fad 156// wxDisplayFactoryMSW declaration
8585e2b5
VZ
157// ----------------------------------------------------------------------------
158
d5947fad
VZ
159WX_DEFINE_ARRAY(HMONITOR, wxMonitorHandleArray);
160
161// functions dynamically bound by wxDisplayFactoryMSW ctor.
ef1717a9
VZ
162static MonitorFromPoint_t gs_MonitorFromPoint = NULL;
163static MonitorFromWindow_t gs_MonitorFromWindow = NULL;
164static GetMonitorInfo_t gs_GetMonitorInfo = NULL;
d5947fad 165static EnumDisplayMonitors_t gs_EnumDisplayMonitors = NULL;
8585e2b5 166
d5947fad 167class wxDisplayFactoryMSW : public wxDisplayFactory
ef1717a9
VZ
168{
169public:
d5947fad
VZ
170 // ctor checks if the current system supports multimon API and dynamically
171 // bind the functions we need if this is the case and fills the
172 // m_displays array if they're available
173 wxDisplayFactoryMSW();
8585e2b5 174
ad6f09f5
VZ
175 // Dtor destroys the hidden window we use for getting WM_SETTINGCHANGE.
176 virtual ~wxDisplayFactoryMSW();
177
ef1717a9 178 bool IsOk() const { return !m_displays.empty(); }
8585e2b5 179
d5947fad 180 virtual wxDisplayImpl *CreateDisplay(unsigned n);
4e675101 181 virtual unsigned GetCount() { return unsigned(m_displays.size()); }
ef1717a9 182 virtual int GetFromPoint(const wxPoint& pt);
1e93d595 183 virtual int GetFromWindow(const wxWindow *window);
a536e411 184
ad6f09f5
VZ
185 // Called when we receive WM_SETTINGCHANGE to refresh the list of monitor
186 // handles.
187 static void RefreshMonitors() { ms_factory->DoRefreshMonitors(); }
188
189
ef1717a9
VZ
190private:
191 // EnumDisplayMonitors() callback
192 static BOOL CALLBACK MultimonEnumProc(HMONITOR hMonitor,
193 HDC hdcMonitor,
194 LPRECT lprcMonitor,
195 LPARAM dwData);
06efac1f 196
d5947fad
VZ
197 // find the monitor corresponding to the given handle,
198 // return wxNOT_FOUND if not found
199 int FindDisplayFromHMONITOR(HMONITOR hmon) const;
06efac1f 200
ad6f09f5
VZ
201 // Update m_displays array, used by RefreshMonitors().
202 void DoRefreshMonitors();
203
204
205 // The unique factory being used (as we don't have direct access to the
206 // global factory pointer in the common code so we just duplicate this
207 // variable (also making it of correct type for us) here).
208 static wxDisplayFactoryMSW* ms_factory;
209
210
d5947fad
VZ
211 // the array containing information about all available displays, filled by
212 // MultimonEnumProc()
213 wxMonitorHandleArray m_displays;
214
ad6f09f5
VZ
215 // The hidden window we use for receiving WM_SETTINGCHANGE and its class
216 // name.
217 HWND m_hiddenHwnd;
218 const wxChar* m_hiddenClass;
219
d5947fad
VZ
220 wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMSW);
221};
8585e2b5 222
ad6f09f5 223wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL;
a536e411 224
ef1717a9 225// ----------------------------------------------------------------------------
d5947fad 226// wxDisplay implementation
ef1717a9
VZ
227// ----------------------------------------------------------------------------
228
229/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
a536e411 230{
d5947fad 231 wxDisplayFactoryMSW *factoryMM = new wxDisplayFactoryMSW;
16e45865 232
ef1717a9
VZ
233 if ( factoryMM->IsOk() )
234 return factoryMM;
a536e411 235
ef1717a9
VZ
236 delete factoryMM;
237
d5947fad 238 // fall back to a stub implementation if no multimon support (Win95?)
ef1717a9 239 return new wxDisplayFactorySingle;
8585e2b5 240}
a536e411 241
16e45865 242
ef1717a9 243// ----------------------------------------------------------------------------
d5947fad 244// wxDisplayMSW implementation
ef1717a9
VZ
245// ----------------------------------------------------------------------------
246
473ca5f3 247bool wxDisplayMSW::GetMonInfo(MONITORINFOEX& monInfo) const
8585e2b5 248{
473ca5f3 249 if ( !gs_GetMonitorInfo(m_hmon, &monInfo) )
d5947fad 250 {
473ca5f3
VZ
251 wxLogLastError(wxT("GetMonitorInfo"));
252 return false;
ef1717a9 253 }
8585e2b5 254
473ca5f3
VZ
255 return true;
256}
257
258wxRect wxDisplayMSW::GetGeometry() const
259{
260 WinStruct<MONITORINFOEX> monInfo;
261
d5947fad 262 wxRect rect;
473ca5f3
VZ
263 if ( GetMonInfo(monInfo) )
264 wxCopyRECTToRect(monInfo.rcMonitor, rect);
06efac1f 265
d5947fad 266 return rect;
ef1717a9 267}
06efac1f 268
d5947fad 269wxRect wxDisplayMSW::GetClientArea() const
6c5d6291 270{
d5947fad
VZ
271 WinStruct<MONITORINFOEX> monInfo;
272
d5947fad 273 wxRect rectClient;
473ca5f3
VZ
274 if ( GetMonInfo(monInfo) )
275 wxCopyRECTToRect(monInfo.rcWork, rectClient);
6c5d6291 276
d5947fad 277 return rectClient;
6c5d6291
VZ
278}
279
d5947fad 280wxString wxDisplayMSW::GetName() const
ef1717a9 281{
d5947fad 282 WinStruct<MONITORINFOEX> monInfo;
06efac1f 283
473ca5f3
VZ
284 wxString name;
285 if ( GetMonInfo(monInfo) )
286 name = monInfo.szDevice;
d5947fad 287
473ca5f3 288 return name;
ef1717a9 289}
06efac1f 290
d5947fad 291bool wxDisplayMSW::IsPrimary() const
ef1717a9 292{
d5947fad
VZ
293 WinStruct<MONITORINFOEX> monInfo;
294
473ca5f3 295 if ( !GetMonInfo(monInfo) )
d5947fad 296 return false;
06efac1f 297
d5947fad 298 return (monInfo.dwFlags & MONITORINFOF_PRIMARY) != 0;
06efac1f
VZ
299}
300
d5947fad 301wxVideoMode wxDisplayMSW::GetCurrentMode() const
06efac1f 302{
ef1717a9 303 wxVideoMode mode;
01c54165 304
ef1717a9
VZ
305 // The first parameter of EnumDisplaySettings() must be NULL under Win95
306 // according to MSDN. The version of GetName() we implement for Win95
307 // returns an empty string.
308 const wxString name = GetName();
c9f78968
VS
309 const wxChar * const deviceName = name.empty()
310 ? (const wxChar*)NULL
311 : (const wxChar*)name.c_str();
06efac1f 312
ef1717a9
VZ
313 DEVMODE dm;
314 dm.dmSize = sizeof(dm);
315 dm.dmDriverExtra = 0;
d5947fad 316
ef1717a9 317 if ( !::EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, &dm) )
06efac1f 318 {
9a83f860 319 wxLogLastError(wxT("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
06efac1f 320 }
ef1717a9
VZ
321 else
322 {
323 mode = ConvertToVideoMode(dm);
324 }
325
326 return mode;
06efac1f
VZ
327}
328
d5947fad 329wxArrayVideoModes wxDisplayMSW::GetModes(const wxVideoMode& modeMatch) const
a536e411 330{
8585e2b5
VZ
331 wxArrayVideoModes modes;
332
01c54165
VZ
333 // The first parameter of EnumDisplaySettings() must be NULL under Win95
334 // according to MSDN. The version of GetName() we implement for Win95
335 // returns an empty string.
336 const wxString name = GetName();
c9f78968
VS
337 const wxChar * const deviceName = name.empty()
338 ? (const wxChar*)NULL
339 : (const wxChar*)name.c_str();
8585e2b5
VZ
340
341 DEVMODE dm;
01c54165
VZ
342 dm.dmSize = sizeof(dm);
343 dm.dmDriverExtra = 0;
d5947fad 344
8585e2b5
VZ
345 for ( int iModeNum = 0;
346 ::EnumDisplaySettings(deviceName, iModeNum, &dm);
347 iModeNum++ )
348 {
349 const wxVideoMode mode = ConvertToVideoMode(dm);
350 if ( mode.Matches(modeMatch) )
351 {
352 modes.Add(mode);
353 }
354 }
355
356 return modes;
a536e411
JS
357}
358
d5947fad 359bool wxDisplayMSW::ChangeMode(const wxVideoMode& mode)
a536e411 360{
8585e2b5 361 // prepare ChangeDisplaySettingsEx() parameters
61373fa8
WS
362 DEVMODE dm;
363 DEVMODE *pDevMode;
364
8585e2b5
VZ
365 int flags;
366
367 if ( mode == wxDefaultVideoMode )
368 {
369 // reset the video mode to default
370 pDevMode = NULL;
371 flags = 0;
372 }
373 else // change to the given mode
374 {
2edac25b 375 wxCHECK_MSG( mode.GetWidth() && mode.GetHeight(), false,
9a83f860 376 wxT("at least the width and height must be specified") );
8585e2b5
VZ
377
378 wxZeroMemory(dm);
379 dm.dmSize = sizeof(dm);
01c54165 380 dm.dmDriverExtra = 0;
8585e2b5 381 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2edac25b
RR
382 dm.dmPelsWidth = mode.GetWidth();
383 dm.dmPelsHeight = mode.GetHeight();
8585e2b5 384
2edac25b 385 if ( mode.GetDepth() )
8585e2b5
VZ
386 {
387 dm.dmFields |= DM_BITSPERPEL;
2edac25b 388 dm.dmBitsPerPel = mode.GetDepth();
8585e2b5
VZ
389 }
390
2edac25b 391 if ( mode.GetRefresh() )
8585e2b5
VZ
392 {
393 dm.dmFields |= DM_DISPLAYFREQUENCY;
2edac25b 394 dm.dmDisplayFrequency = mode.GetRefresh();
8585e2b5
VZ
395 }
396
397 pDevMode = &dm;
398
2ad495fb
WS
399#ifdef __WXWINCE__
400 flags = 0;
401#else // !__WXWINCE__
8585e2b5 402 flags = CDS_FULLSCREEN;
2ad495fb 403#endif // __WXWINCE__/!__WXWINCE__
8585e2b5
VZ
404 }
405
406
407 // get pointer to the function dynamically
408 //
409 // we're only called from the main thread, so it's ok to use static
410 // variable
411 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
412 if ( !pfnChangeDisplaySettingsEx )
413 {
d238d403
VZ
414 wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET);
415 if ( dllDisplay.IsLoaded() )
8585e2b5 416 {
d238d403 417 wxDL_INIT_FUNC_AW(pfn, ChangeDisplaySettingsEx, dllDisplay);
8585e2b5 418 }
d238d403 419 //else: huh, no this DLL must always be present, what's going on??
8585e2b5 420
2ad495fb 421#ifndef __WXWINCE__
8585e2b5
VZ
422 if ( !pfnChangeDisplaySettingsEx )
423 {
424 // we must be under Win95 and so there is no multiple monitors
425 // support anyhow
426 pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
427 }
2ad495fb 428#endif // !__WXWINCE__
8585e2b5
VZ
429 }
430
431 // do change the mode
432 switch ( pfnChangeDisplaySettingsEx
433 (
017dc06b 434 GetName().t_str(), // display name
e0a050e3
VS
435 pDevMode, // dev mode or NULL to reset
436 NULL, // reserved
8585e2b5 437 flags,
e0a050e3 438 NULL // pointer to video parameters (not used)
8585e2b5
VZ
439 ) )
440 {
441 case DISP_CHANGE_SUCCESSFUL:
442 // ok
920b9675
JS
443 {
444 // If we have a top-level, full-screen frame, emulate
4c51a665 445 // the DirectX behaviour and resize it. This makes this
920b9675
JS
446 // API quite a bit easier to use.
447 wxWindow *winTop = wxTheApp->GetTopWindow();
448 wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
449 if (frameTop && frameTop->IsFullScreen())
450 {
451 wxVideoMode current = GetCurrentMode();
2edac25b 452 frameTop->SetClientSize(current.GetWidth(), current.GetHeight());
920b9675
JS
453 }
454 }
06efac1f 455 return true;
8585e2b5
VZ
456
457 case DISP_CHANGE_BADMODE:
458 // don't complain about this, this is the only "expected" error
459 break;
460
461 default:
9a83f860 462 wxFAIL_MSG( wxT("unexpected ChangeDisplaySettingsEx() return value") );
8585e2b5
VZ
463 }
464
06efac1f
VZ
465 return false;
466}
467
d5947fad
VZ
468
469// ----------------------------------------------------------------------------
470// wxDisplayFactoryMSW implementation
471// ----------------------------------------------------------------------------
472
ad6f09f5
VZ
473LRESULT APIENTRY
474wxDisplayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
475{
476 if ( msg == WM_SETTINGCHANGE )
477 {
478 wxDisplayFactoryMSW::RefreshMonitors();
479
480 return 0;
481 }
482
483 return ::DefWindowProc(hwnd, msg, wParam, lParam);
484}
485
d5947fad
VZ
486wxDisplayFactoryMSW::wxDisplayFactoryMSW()
487{
ad6f09f5
VZ
488 // This is not supposed to happen with the current code, the factory is
489 // implicitly a singleton.
490 wxASSERT_MSG( !ms_factory, wxS("Using more than one factory?") );
491
492 ms_factory = this;
493
494 m_hiddenHwnd = NULL;
495 m_hiddenClass = NULL;
496
d5947fad
VZ
497 if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL
498 || gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
499 {
500 // First initialization, or last initialization failed.
501 wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET);
502
503 wxDL_INIT_FUNC(gs_, MonitorFromPoint, dllDisplay);
504 wxDL_INIT_FUNC(gs_, MonitorFromWindow, dllDisplay);
505 wxDL_INIT_FUNC_AW(gs_, GetMonitorInfo, dllDisplay);
506 wxDL_INIT_FUNC(gs_, EnumDisplayMonitors, dllDisplay);
507
508 // we can safely let dllDisplay go out of scope, the DLL itself will
509 // still remain loaded as all programs link to it statically anyhow
510 }
511
512 if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL
513 || gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
514 return;
515
ad6f09f5
VZ
516 DoRefreshMonitors();
517
518 // Also create a hidden window to listen for WM_SETTINGCHANGE that we
519 // receive when a monitor is added to or removed from the system as we must
520 // refresh our monitor handles information then.
521 m_hiddenHwnd = wxCreateHiddenWindow
522 (
523 &m_hiddenClass,
524 wxT("wxDisplayHiddenWindow"),
525 wxDisplayWndProc
526 );
527}
528
529wxDisplayFactoryMSW::~wxDisplayFactoryMSW()
530{
531 if ( m_hiddenHwnd )
532 {
533 if ( !::DestroyWindow(m_hiddenHwnd) )
534 {
535 wxLogLastError(wxT("DestroyWindow(wxDisplayHiddenWindow)"));
536 }
537
538 if ( m_hiddenClass )
539 {
540 if ( !::UnregisterClass(m_hiddenClass, wxGetInstance()) )
541 {
542 wxLogLastError(wxT("UnregisterClass(wxDisplayHiddenWindow)"));
543 }
544 }
545 }
546
547 ms_factory = NULL;
548}
549
550void wxDisplayFactoryMSW::DoRefreshMonitors()
551{
552 m_displays.Clear();
553
d5947fad
VZ
554 if ( !gs_EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) )
555 {
556 wxLogLastError(wxT("EnumDisplayMonitors"));
557 }
558}
559
560/* static */
561BOOL CALLBACK
562wxDisplayFactoryMSW::MultimonEnumProc(
563 HMONITOR hMonitor, // handle to display monitor
564 HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
565 LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle
566 LPARAM dwData) // data passed from EnumDisplayMonitors (this)
567{
568 wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData;
569
570 self->m_displays.Add(hMonitor);
571
572 // continue the enumeration
573 return TRUE;
574}
575
576wxDisplayImpl *wxDisplayFactoryMSW::CreateDisplay(unsigned n)
577{
578 wxCHECK_MSG( n < m_displays.size(), NULL, wxT("An invalid index was passed to wxDisplay") );
579
580 return new wxDisplayMSW(n, m_displays[n]);
581}
582
583// helper for GetFromPoint() and GetFromWindow()
584int wxDisplayFactoryMSW::FindDisplayFromHMONITOR(HMONITOR hmon) const
585{
586 if ( hmon )
587 {
588 const size_t count = m_displays.size();
589 for ( size_t n = 0; n < count; n++ )
590 {
591 if ( hmon == m_displays[n] )
592 return n;
593 }
594 }
595
596 return wxNOT_FOUND;
597}
598
599int wxDisplayFactoryMSW::GetFromPoint(const wxPoint& pt)
600{
601 POINT pt2;
602 pt2.x = pt.x;
603 pt2.y = pt.y;
604
605 return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2,
606 MONITOR_DEFAULTTONULL));
607}
608
609int wxDisplayFactoryMSW::GetFromWindow(const wxWindow *window)
610{
fa88bebe 611#ifdef __WXMSW__
d5947fad
VZ
612 return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window),
613 MONITOR_DEFAULTTONULL));
fa88bebe
VZ
614#else
615 const wxSize halfsize = window->GetSize() / 2;
616 wxPoint pt = window->GetScreenPosition();
617 pt.x += halfsize.x;
618 pt.y += halfsize.y;
619 return GetFromPoint(pt);
620#endif
d5947fad
VZ
621}
622
8585e2b5 623#endif // wxUSE_DISPLAY
5146904d
VZ
624
625void wxClientDisplayRect(int *x, int *y, int *width, int *height)
626{
627#if defined(__WXMICROWIN__)
628 *x = 0; *y = 0;
629 wxDisplaySize(width, height);
630#else
631 // Determine the desktop dimensions minus the taskbar and any other
632 // special decorations...
633 RECT r;
634
635 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
636 if (x) *x = r.left;
637 if (y) *y = r.top;
638 if (width) *width = r.right - r.left;
639 if (height) *height = r.bottom - r.top;
640#endif
641}