Applied patch by snowleopard2 fixing a bunch of typos such as misspellings and double words in the documentation. Combined the patch with some local queued typos waiting to be committed as well as adding new typo fixes inspired by the patch.
Function names with American spelling were not changed nor was third-party code touched. The only code changes involve some changes in strings that are translated ("Can not" -> "Cannot").
Closes #13063 (again).
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67280 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
532 lines
16 KiB
C++
532 lines
16 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/msw/display.cpp
|
|
// Purpose: MSW Implementation of wxDisplay class
|
|
// Author: Royce Mitchell III, Vadim Zeitlin
|
|
// Modified by: Ryan Norton (IsPrimary override)
|
|
// Created: 06/21/02
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) wxWidgets team
|
|
// Copyright: (c) 2002-2006 wxWidgets team
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ===========================================================================
|
|
// declarations
|
|
// ===========================================================================
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// headers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_DISPLAY
|
|
|
|
#include "wx/display.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/dynarray.h"
|
|
#include "wx/app.h"
|
|
#include "wx/frame.h"
|
|
#endif
|
|
|
|
#include "wx/dynload.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"
|
|
|
|
#ifndef __WXWINCE__
|
|
// Older versions of windef.h don't define HMONITOR. Unfortunately, we
|
|
// can't directly test whether HMONITOR is defined or not in windef.h as
|
|
// it's not a macro but a typedef, so we test for an unrelated symbol which
|
|
// is only defined in winuser.h if WINVER >= 0x0500
|
|
#if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK)
|
|
DECLARE_HANDLE(HMONITOR);
|
|
typedef BOOL(CALLBACK * MONITORENUMPROC )(HMONITOR, HDC, LPRECT, LPARAM);
|
|
typedef struct tagMONITORINFO
|
|
{
|
|
DWORD cbSize;
|
|
RECT rcMonitor;
|
|
RECT rcWork;
|
|
DWORD dwFlags;
|
|
} MONITORINFO, *LPMONITORINFO;
|
|
typedef struct tagMONITORINFOEX : public tagMONITORINFO
|
|
{
|
|
TCHAR szDevice[CCHDEVICENAME];
|
|
} MONITORINFOEX, *LPMONITORINFOEX;
|
|
#define MONITOR_DEFAULTTONULL 0x00000000
|
|
#define MONITOR_DEFAULTTOPRIMARY 0x00000001
|
|
#define MONITOR_DEFAULTTONEAREST 0x00000002
|
|
#define MONITORINFOF_PRIMARY 0x00000001
|
|
#define HMONITOR_DECLARED
|
|
#endif
|
|
#endif // !__WXWINCE__
|
|
|
|
// display functions are found in different DLLs under WinCE and normal Win32
|
|
#ifdef __WXWINCE__
|
|
static const wxChar displayDllName[] = wxT("coredll.dll");
|
|
#else
|
|
static const wxChar displayDllName[] = wxT("user32.dll");
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// typedefs for dynamically loaded Windows functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
typedef LONG (WINAPI *ChangeDisplaySettingsEx_t)(LPCTSTR lpszDeviceName,
|
|
LPDEVMODE lpDevMode,
|
|
HWND hwnd,
|
|
DWORD dwFlags,
|
|
LPVOID lParam);
|
|
|
|
typedef BOOL (WINAPI *EnumDisplayMonitors_t)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
|
|
typedef HMONITOR (WINAPI *MonitorFromPoint_t)(POINT,DWORD);
|
|
typedef HMONITOR (WINAPI *MonitorFromWindow_t)(HWND,DWORD);
|
|
typedef BOOL (WINAPI *GetMonitorInfo_t)(HMONITOR,LPMONITORINFO);
|
|
|
|
#ifndef __WXWINCE__
|
|
// emulation of ChangeDisplaySettingsEx() for Win95
|
|
LONG WINAPI ChangeDisplaySettingsExForWin95(LPCTSTR WXUNUSED(lpszDeviceName),
|
|
LPDEVMODE lpDevMode,
|
|
HWND WXUNUSED(hwnd),
|
|
DWORD dwFlags,
|
|
LPVOID WXUNUSED(lParam))
|
|
{
|
|
return ::ChangeDisplaySettings(lpDevMode, dwFlags);
|
|
}
|
|
#endif // !__WXWINCE__
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDisplayMSW declaration
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxDisplayMSW : public wxDisplayImpl
|
|
{
|
|
public:
|
|
wxDisplayMSW(unsigned n, HMONITOR hmon)
|
|
: wxDisplayImpl(n),
|
|
m_hmon(hmon)
|
|
{
|
|
}
|
|
|
|
virtual wxRect GetGeometry() const;
|
|
virtual wxRect GetClientArea() const;
|
|
virtual wxString GetName() const;
|
|
virtual bool IsPrimary() const;
|
|
|
|
virtual wxVideoMode GetCurrentMode() const;
|
|
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
|
|
virtual bool ChangeMode(const wxVideoMode& mode);
|
|
|
|
protected:
|
|
// convert a DEVMODE to our wxVideoMode
|
|
static wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
|
|
{
|
|
// note that dmDisplayFrequency may be 0 or 1 meaning "standard one"
|
|
// and although 0 is ok for us we don't want to return modes with 1hz
|
|
// refresh
|
|
return wxVideoMode(dm.dmPelsWidth,
|
|
dm.dmPelsHeight,
|
|
dm.dmBitsPerPel,
|
|
dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
|
|
}
|
|
|
|
// Call GetMonitorInfo() and fill in the provided struct and return true if
|
|
// it succeeded, otherwise return false.
|
|
bool GetMonInfo(MONITORINFOEX& monInfo) const;
|
|
|
|
HMONITOR m_hmon;
|
|
|
|
private:
|
|
wxDECLARE_NO_COPY_CLASS(wxDisplayMSW);
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDisplayFactoryMSW declaration
|
|
// ----------------------------------------------------------------------------
|
|
|
|
WX_DEFINE_ARRAY(HMONITOR, wxMonitorHandleArray);
|
|
|
|
// functions dynamically bound by wxDisplayFactoryMSW ctor.
|
|
static MonitorFromPoint_t gs_MonitorFromPoint = NULL;
|
|
static MonitorFromWindow_t gs_MonitorFromWindow = NULL;
|
|
static GetMonitorInfo_t gs_GetMonitorInfo = NULL;
|
|
static EnumDisplayMonitors_t gs_EnumDisplayMonitors = NULL;
|
|
|
|
class wxDisplayFactoryMSW : public wxDisplayFactory
|
|
{
|
|
public:
|
|
// ctor checks if the current system supports multimon API and dynamically
|
|
// bind the functions we need if this is the case and fills the
|
|
// m_displays array if they're available
|
|
wxDisplayFactoryMSW();
|
|
|
|
bool IsOk() const { return !m_displays.empty(); }
|
|
|
|
virtual wxDisplayImpl *CreateDisplay(unsigned n);
|
|
virtual unsigned GetCount() { return unsigned(m_displays.size()); }
|
|
virtual int GetFromPoint(const wxPoint& pt);
|
|
virtual int GetFromWindow(const wxWindow *window);
|
|
|
|
private:
|
|
// EnumDisplayMonitors() callback
|
|
static BOOL CALLBACK MultimonEnumProc(HMONITOR hMonitor,
|
|
HDC hdcMonitor,
|
|
LPRECT lprcMonitor,
|
|
LPARAM dwData);
|
|
|
|
// find the monitor corresponding to the given handle,
|
|
// return wxNOT_FOUND if not found
|
|
int FindDisplayFromHMONITOR(HMONITOR hmon) const;
|
|
|
|
// the array containing information about all available displays, filled by
|
|
// MultimonEnumProc()
|
|
wxMonitorHandleArray m_displays;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMSW);
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDisplay implementation
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
|
|
{
|
|
wxDisplayFactoryMSW *factoryMM = new wxDisplayFactoryMSW;
|
|
|
|
if ( factoryMM->IsOk() )
|
|
return factoryMM;
|
|
|
|
delete factoryMM;
|
|
|
|
// fall back to a stub implementation if no multimon support (Win95?)
|
|
return new wxDisplayFactorySingle;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDisplayMSW implementation
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxDisplayMSW::GetMonInfo(MONITORINFOEX& monInfo) const
|
|
{
|
|
if ( !gs_GetMonitorInfo(m_hmon, &monInfo) )
|
|
{
|
|
wxLogLastError(wxT("GetMonitorInfo"));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
wxRect wxDisplayMSW::GetGeometry() const
|
|
{
|
|
WinStruct<MONITORINFOEX> monInfo;
|
|
|
|
wxRect rect;
|
|
if ( GetMonInfo(monInfo) )
|
|
wxCopyRECTToRect(monInfo.rcMonitor, rect);
|
|
|
|
return rect;
|
|
}
|
|
|
|
wxRect wxDisplayMSW::GetClientArea() const
|
|
{
|
|
WinStruct<MONITORINFOEX> monInfo;
|
|
|
|
wxRect rectClient;
|
|
if ( GetMonInfo(monInfo) )
|
|
wxCopyRECTToRect(monInfo.rcWork, rectClient);
|
|
|
|
return rectClient;
|
|
}
|
|
|
|
wxString wxDisplayMSW::GetName() const
|
|
{
|
|
WinStruct<MONITORINFOEX> monInfo;
|
|
|
|
wxString name;
|
|
if ( GetMonInfo(monInfo) )
|
|
name = monInfo.szDevice;
|
|
|
|
return name;
|
|
}
|
|
|
|
bool wxDisplayMSW::IsPrimary() const
|
|
{
|
|
WinStruct<MONITORINFOEX> monInfo;
|
|
|
|
if ( !GetMonInfo(monInfo) )
|
|
return false;
|
|
|
|
return (monInfo.dwFlags & MONITORINFOF_PRIMARY) != 0;
|
|
}
|
|
|
|
wxVideoMode wxDisplayMSW::GetCurrentMode() const
|
|
{
|
|
wxVideoMode mode;
|
|
|
|
// The first parameter of EnumDisplaySettings() must be NULL under Win95
|
|
// according to MSDN. The version of GetName() we implement for Win95
|
|
// returns an empty string.
|
|
const wxString name = GetName();
|
|
const wxChar * const deviceName = name.empty()
|
|
? (const wxChar*)NULL
|
|
: (const wxChar*)name.c_str();
|
|
|
|
DEVMODE dm;
|
|
dm.dmSize = sizeof(dm);
|
|
dm.dmDriverExtra = 0;
|
|
|
|
if ( !::EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, &dm) )
|
|
{
|
|
wxLogLastError(wxT("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
|
|
}
|
|
else
|
|
{
|
|
mode = ConvertToVideoMode(dm);
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
wxArrayVideoModes wxDisplayMSW::GetModes(const wxVideoMode& modeMatch) const
|
|
{
|
|
wxArrayVideoModes modes;
|
|
|
|
// The first parameter of EnumDisplaySettings() must be NULL under Win95
|
|
// according to MSDN. The version of GetName() we implement for Win95
|
|
// returns an empty string.
|
|
const wxString name = GetName();
|
|
const wxChar * const deviceName = name.empty()
|
|
? (const wxChar*)NULL
|
|
: (const wxChar*)name.c_str();
|
|
|
|
DEVMODE dm;
|
|
dm.dmSize = sizeof(dm);
|
|
dm.dmDriverExtra = 0;
|
|
|
|
for ( int iModeNum = 0;
|
|
::EnumDisplaySettings(deviceName, iModeNum, &dm);
|
|
iModeNum++ )
|
|
{
|
|
const wxVideoMode mode = ConvertToVideoMode(dm);
|
|
if ( mode.Matches(modeMatch) )
|
|
{
|
|
modes.Add(mode);
|
|
}
|
|
}
|
|
|
|
return modes;
|
|
}
|
|
|
|
bool wxDisplayMSW::ChangeMode(const wxVideoMode& mode)
|
|
{
|
|
// prepare ChangeDisplaySettingsEx() parameters
|
|
DEVMODE dm;
|
|
DEVMODE *pDevMode;
|
|
|
|
int flags;
|
|
|
|
if ( mode == wxDefaultVideoMode )
|
|
{
|
|
// reset the video mode to default
|
|
pDevMode = NULL;
|
|
flags = 0;
|
|
}
|
|
else // change to the given mode
|
|
{
|
|
wxCHECK_MSG( mode.GetWidth() && mode.GetHeight(), false,
|
|
wxT("at least the width and height must be specified") );
|
|
|
|
wxZeroMemory(dm);
|
|
dm.dmSize = sizeof(dm);
|
|
dm.dmDriverExtra = 0;
|
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
dm.dmPelsWidth = mode.GetWidth();
|
|
dm.dmPelsHeight = mode.GetHeight();
|
|
|
|
if ( mode.GetDepth() )
|
|
{
|
|
dm.dmFields |= DM_BITSPERPEL;
|
|
dm.dmBitsPerPel = mode.GetDepth();
|
|
}
|
|
|
|
if ( mode.GetRefresh() )
|
|
{
|
|
dm.dmFields |= DM_DISPLAYFREQUENCY;
|
|
dm.dmDisplayFrequency = mode.GetRefresh();
|
|
}
|
|
|
|
pDevMode = &dm;
|
|
|
|
#ifdef __WXWINCE__
|
|
flags = 0;
|
|
#else // !__WXWINCE__
|
|
flags = CDS_FULLSCREEN;
|
|
#endif // __WXWINCE__/!__WXWINCE__
|
|
}
|
|
|
|
|
|
// get pointer to the function dynamically
|
|
//
|
|
// we're only called from the main thread, so it's ok to use static
|
|
// variable
|
|
static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
|
|
if ( !pfnChangeDisplaySettingsEx )
|
|
{
|
|
wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET);
|
|
if ( dllDisplay.IsLoaded() )
|
|
{
|
|
wxDL_INIT_FUNC_AW(pfn, ChangeDisplaySettingsEx, dllDisplay);
|
|
}
|
|
//else: huh, no this DLL must always be present, what's going on??
|
|
|
|
#ifndef __WXWINCE__
|
|
if ( !pfnChangeDisplaySettingsEx )
|
|
{
|
|
// we must be under Win95 and so there is no multiple monitors
|
|
// support anyhow
|
|
pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
|
|
}
|
|
#endif // !__WXWINCE__
|
|
}
|
|
|
|
// do change the mode
|
|
switch ( pfnChangeDisplaySettingsEx
|
|
(
|
|
GetName().wx_str(), // display name
|
|
pDevMode, // dev mode or NULL to reset
|
|
NULL, // reserved
|
|
flags,
|
|
NULL // pointer to video parameters (not used)
|
|
) )
|
|
{
|
|
case DISP_CHANGE_SUCCESSFUL:
|
|
// ok
|
|
{
|
|
// If we have a top-level, full-screen frame, emulate
|
|
// the DirectX behaviour and resize it. This makes this
|
|
// API quite a bit easier to use.
|
|
wxWindow *winTop = wxTheApp->GetTopWindow();
|
|
wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
|
|
if (frameTop && frameTop->IsFullScreen())
|
|
{
|
|
wxVideoMode current = GetCurrentMode();
|
|
frameTop->SetClientSize(current.GetWidth(), current.GetHeight());
|
|
}
|
|
}
|
|
return true;
|
|
|
|
case DISP_CHANGE_BADMODE:
|
|
// don't complain about this, this is the only "expected" error
|
|
break;
|
|
|
|
default:
|
|
wxFAIL_MSG( wxT("unexpected ChangeDisplaySettingsEx() return value") );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDisplayFactoryMSW implementation
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxDisplayFactoryMSW::wxDisplayFactoryMSW()
|
|
{
|
|
if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL
|
|
|| gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
|
|
{
|
|
// First initialization, or last initialization failed.
|
|
wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET);
|
|
|
|
wxDL_INIT_FUNC(gs_, MonitorFromPoint, dllDisplay);
|
|
wxDL_INIT_FUNC(gs_, MonitorFromWindow, dllDisplay);
|
|
wxDL_INIT_FUNC_AW(gs_, GetMonitorInfo, dllDisplay);
|
|
wxDL_INIT_FUNC(gs_, EnumDisplayMonitors, dllDisplay);
|
|
|
|
// we can safely let dllDisplay go out of scope, the DLL itself will
|
|
// still remain loaded as all programs link to it statically anyhow
|
|
}
|
|
|
|
if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL
|
|
|| gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL )
|
|
return;
|
|
|
|
// enumerate all displays
|
|
if ( !gs_EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) )
|
|
{
|
|
wxLogLastError(wxT("EnumDisplayMonitors"));
|
|
}
|
|
}
|
|
|
|
/* static */
|
|
BOOL CALLBACK
|
|
wxDisplayFactoryMSW::MultimonEnumProc(
|
|
HMONITOR hMonitor, // handle to display monitor
|
|
HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
|
|
LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle
|
|
LPARAM dwData) // data passed from EnumDisplayMonitors (this)
|
|
{
|
|
wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData;
|
|
|
|
self->m_displays.Add(hMonitor);
|
|
|
|
// continue the enumeration
|
|
return TRUE;
|
|
}
|
|
|
|
wxDisplayImpl *wxDisplayFactoryMSW::CreateDisplay(unsigned n)
|
|
{
|
|
wxCHECK_MSG( n < m_displays.size(), NULL, wxT("An invalid index was passed to wxDisplay") );
|
|
|
|
return new wxDisplayMSW(n, m_displays[n]);
|
|
}
|
|
|
|
// helper for GetFromPoint() and GetFromWindow()
|
|
int wxDisplayFactoryMSW::FindDisplayFromHMONITOR(HMONITOR hmon) const
|
|
{
|
|
if ( hmon )
|
|
{
|
|
const size_t count = m_displays.size();
|
|
for ( size_t n = 0; n < count; n++ )
|
|
{
|
|
if ( hmon == m_displays[n] )
|
|
return n;
|
|
}
|
|
}
|
|
|
|
return wxNOT_FOUND;
|
|
}
|
|
|
|
int wxDisplayFactoryMSW::GetFromPoint(const wxPoint& pt)
|
|
{
|
|
POINT pt2;
|
|
pt2.x = pt.x;
|
|
pt2.y = pt.y;
|
|
|
|
return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2,
|
|
MONITOR_DEFAULTTONULL));
|
|
}
|
|
|
|
int wxDisplayFactoryMSW::GetFromWindow(const wxWindow *window)
|
|
{
|
|
return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window),
|
|
MONITOR_DEFAULTTONULL));
|
|
}
|
|
|
|
#endif // wxUSE_DISPLAY
|