X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d3211838bf578eb8ada5a608b66626a6bde6846a..74a8f67d96591cec101def2a7d47c64072aff7fd:/src/msw/settings.cpp diff --git a/src/msw/settings.cpp b/src/msw/settings.cpp index 133c23ab95..4fbc2299f6 100644 --- a/src/msw/settings.cpp +++ b/src/msw/settings.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/settings.cpp -// Purpose: wxSystemSettings +// Name: src/msw/settings.cpp +// Purpose: wxSystemSettingsNative implementation for MSW // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,116 +17,214 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "settings.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif +#include "wx/settings.h" + #ifndef WX_PRECOMP - #include - #include "wx/defs.h" - #include "wx/pen.h" - #include "wx/brush.h" + #include "wx/utils.h" #include "wx/gdicmn.h" + #include "wx/module.h" #endif -#include "wx/settings.h" -#include "wx/window.h" #include "wx/msw/private.h" -#include "wx/module.h" +#include "wx/msw/missing.h" // for SM_CXCURSOR, SM_CYCURSOR, SM_TABLETPC +#include "wx/msw/private/metrics.h" + +#ifndef SPI_GETFLATMENU +#define SPI_GETFLATMENU 0x1022 +#endif + +#include "wx/fontutil.h" +#include "wx/fontenum.h" // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- -// the module which is used to clean up wxSystemSettings data (this is a +// the module which is used to clean up wxSystemSettingsNative data (this is a // singleton class so it can't be done in the dtor) class wxSystemSettingsModule : public wxModule { - friend class wxSystemSettings; public: virtual bool OnInit(); virtual void OnExit(); private: DECLARE_DYNAMIC_CLASS(wxSystemSettingsModule) - - static wxArrayString sm_optionNames; - static wxArrayString sm_optionValues; }; // ---------------------------------------------------------------------------- // global data // ---------------------------------------------------------------------------- +// the font returned by GetFont(wxSYS_DEFAULT_GUI_FONT): it is created when +// GetFont() is called for the first time and deleted by wxSystemSettingsModule static wxFont *gs_fontDefault = NULL; // ============================================================================ // implementation // ============================================================================ +// TODO: see ::SystemParametersInfo for all sorts of Windows settings. +// Different args are required depending on the id. How does this differ +// from GetSystemMetric, and should it? Perhaps call it GetSystemParameter +// and pass an optional void* arg to get further info. +// Should also have SetSystemParameter. +// Also implement WM_WININICHANGE (NT) / WM_SETTINGCHANGE (Win95) + // ---------------------------------------------------------------------------- // wxSystemSettingsModule // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxSystemSettingsModule, wxModule) -wxArrayString wxSystemSettingsModule::sm_optionNames; -wxArrayString wxSystemSettingsModule::sm_optionValues; - bool wxSystemSettingsModule::OnInit() { - return TRUE; + return true; } void wxSystemSettingsModule::OnExit() { - sm_optionNames.Clear(); - sm_optionValues.Clear(); - delete gs_fontDefault; + wxDELETE(gs_fontDefault); } // ---------------------------------------------------------------------------- -// wxSystemSettings +// wxSystemSettingsNative // ---------------------------------------------------------------------------- -// TODO: see ::SystemParametersInfo for all sorts of Windows settings. -// Different args are required depending on the id. How does this differ -// from GetSystemMetric, and should it? Perhaps call it GetSystemParameter -// and pass an optional void* arg to get further info. -// Should also have SetSystemParameter. -// Also implement WM_WININICHANGE (NT) / WM_SETTINGCHANGE (Win95) +// ---------------------------------------------------------------------------- +// colours +// ---------------------------------------------------------------------------- -wxColour wxSystemSettings::GetSystemColour(int index) +wxColour wxSystemSettingsNative::GetColour(wxSystemColour index) { - switch (index) + // we use 0 as the default value just to avoid compiler warnings, as there + // is no invalid colour value we use hasCol as the real indicator of + // whether colSys was initialized or not + COLORREF colSys = 0; + bool hasCol = false; + + // the default colours for the entries after BTNHIGHLIGHT + static const COLORREF s_defaultSysColors[] = + { + 0x000000, // 3DDKSHADOW + 0xdfdfdf, // 3DLIGHT + 0x000000, // INFOTEXT + 0xe1ffff, // INFOBK + + 0, // filler - no std colour with this index + + // TODO: please fill in the standard values of those, I don't have them + 0, // HOTLIGHT + 0, // GRADIENTACTIVECAPTION + 0, // GRADIENTINACTIVECAPTION + 0, // MENU + 0, // MENUBAR (unused) + }; + + if ( index == wxSYS_COLOUR_LISTBOXTEXT) + { + // there is no standard colour with this index, map to another one + index = wxSYS_COLOUR_WINDOWTEXT; + } + else if ( index == wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT) + { + // there is no standard colour with this index, map to another one + index = wxSYS_COLOUR_HIGHLIGHTTEXT; + } + else if ( index == wxSYS_COLOUR_LISTBOX ) { - case wxSYS_COLOUR_LISTBOX: - return *wxWHITE; + // there is no standard colour with this index, map to another one + index = wxSYS_COLOUR_WINDOW; + } + else if ( index > wxSYS_COLOUR_BTNHIGHLIGHT ) + { + // the indices before BTNHIGHLIGHT are understood by GetSysColor() in + // all Windows version, for the other ones we have to check + bool useDefault; - default: - COLORREF ref = ::GetSysColor(index); - wxColour col(GetRValue(ref), GetGValue(ref), GetBValue(ref)); - return col; + int verMaj, verMin; + wxGetOsVersion(&verMaj, &verMin); + if ( verMaj < 4 ) + { + // NT 3.5 + useDefault = true; + } + else if ( verMaj == 4 ) + { + // Win95/NT 4.0 + useDefault = index > wxSYS_COLOUR_INFOBK; + } + else if ( verMaj == 5 && verMin == 0 ) + { + // Win98/Win2K + useDefault = index > wxSYS_COLOUR_GRADIENTINACTIVECAPTION; + } + else // >= 5.1 + { + // 5.1 is Windows XP + useDefault = false; + // Determine if we are using flat menus, only then allow wxSYS_COLOUR_MENUBAR + if ( index == wxSYS_COLOUR_MENUBAR ) + { + BOOL isFlat ; + if ( SystemParametersInfo( SPI_GETFLATMENU , 0 ,&isFlat, 0 ) ) + { + if ( !isFlat ) + index = wxSYS_COLOUR_MENU ; + } + } + } + + if ( useDefault ) + { + // special handling for MENUBAR colour: we use this in wxToolBar + // and wxStatusBar to have correct bg colour under Windows XP + // (which uses COLOR_MENUBAR for them) but they should still look + // correctly under previous Windows versions as well + if ( index == wxSYS_COLOUR_MENUBAR ) + { + index = wxSYS_COLOUR_3DFACE; + } + else // replace with default colour + { + unsigned int n = index - wxSYS_COLOUR_BTNHIGHLIGHT; + + wxASSERT_MSG( n < WXSIZEOF(s_defaultSysColors), + wxT("forgot tp update the default colours array") ); + + colSys = s_defaultSysColors[n]; + hasCol = true; + } + } } -} -wxFont wxSystemSettings::GetSystemFont(int index) -{ - // wxWindow ctor calls GetSystemFont(wxSYS_DEFAULT_GUI_FONT) so we're - // called fairly often - this is why we cache this particular font - bool isDefaultRequested = index == wxSYS_DEFAULT_GUI_FONT; - if ( isDefaultRequested && gs_fontDefault ) + if ( !hasCol ) { - return *gs_fontDefault; +#ifdef __WXWINCE__ + colSys = ::GetSysColor(index|SYS_COLOR_INDEX_FLAG); +#else + colSys = ::GetSysColor(index); +#endif } + wxColour ret = wxRGBToColour(colSys); + wxASSERT(ret.IsOk()); + return ret; +} + +// ---------------------------------------------------------------------------- +// fonts +// ---------------------------------------------------------------------------- + +wxFont wxCreateFontFromStockObject(int index) +{ wxFont font; HFONT hFont = (HFONT) ::GetStockObject(index); @@ -135,162 +233,286 @@ wxFont wxSystemSettings::GetSystemFont(int index) LOGFONT lf; if ( ::GetObject(hFont, sizeof(LOGFONT), &lf) != 0 ) { - font = wxCreateFontFromLogFont(&lf); + wxNativeFontInfo info; + info.lf = lf; + // Under MicroWindows we pass the HFONT as well + // because it's hard to convert HFONT -> LOGFONT -> HFONT + // It's OK to delete stock objects, the delete will be ignored. +#ifdef __WXMICROWIN__ + font.Create(info, (WXHFONT) hFont); +#else + font.Create(info); +#endif } else { - wxFAIL_MSG( _T("failed to get LOGFONT") ); + wxFAIL_MSG( wxT("failed to get LOGFONT") ); } } else // GetStockObject() failed { - wxFAIL_MSG( _T("stock font not found") ); + wxFAIL_MSG( wxT("stock font not found") ); } - if ( isDefaultRequested ) + return font; +} + +wxFont wxSystemSettingsNative::GetFont(wxSystemFont index) +{ +#ifdef __WXWINCE__ + // under CE only a single SYSTEM_FONT exists + index; + + if ( !gs_fontDefault ) { - // if we got here it means we hadn't cached it yet - do now - gs_fontDefault = new wxFont(font); + gs_fontDefault = new wxFont(wxCreateFontFromStockObject(SYSTEM_FONT)); } + wxASSERT(gs_fontDefault->IsOk() && + wxFontEnumerator::IsValidFacename(gs_fontDefault->GetFaceName())); + return *gs_fontDefault; +#else // !__WXWINCE__ + // wxWindow ctor calls GetFont(wxSYS_DEFAULT_GUI_FONT) so we're + // called fairly often -- this is why we cache this particular font + if ( index == wxSYS_DEFAULT_GUI_FONT ) + { + if ( !gs_fontDefault ) + { + // http://blogs.msdn.com/oldnewthing/archive/2005/07/07/436435.aspx + // explains why neither SYSTEM_FONT nor DEFAULT_GUI_FONT should be + // used here + // + // the message box font seems to be the one which should be used + // for most (simple) controls, e.g. buttons and such but other + // controls may prefer to use lfStatusFont or lfCaptionFont if it + // is more appropriate for them + wxNativeFontInfo info; + info.lf = wxMSWImpl::GetNonClientMetrics().lfMessageFont; + gs_fontDefault = new wxFont(info); + } + + return *gs_fontDefault; + } + + wxFont font = wxCreateFontFromStockObject(index); + + wxASSERT(font.IsOk()); + +#if wxUSE_FONTENUM + wxASSERT(wxFontEnumerator::IsValidFacename(font.GetFaceName())); +#endif // wxUSE_FONTENUM + return font; +#endif // __WXWINCE__/!__WXWINCE__ } -// Get a system metric, e.g. scrollbar size -int wxSystemSettings::GetSystemMetric(int index) +// ---------------------------------------------------------------------------- +// system metrics/features +// ---------------------------------------------------------------------------- + +// TODO: some of the "metrics" clearly should be features now that we have +// HasFeature()! + +// the conversion table from wxSystemMetric enum to GetSystemMetrics() param +// +// if the constant is not defined, put -1 in the table to indicate that it is +// unknown +static const int gs_metricsMap[] = { - switch ( index) - { -#ifdef __WIN32__ - case wxSYS_MOUSE_BUTTONS: - return ::GetSystemMetrics(SM_CMOUSEBUTTONS); + -1, // wxSystemMetric enums start at 1, so give a dummy value for pos 0. +#if defined(__WIN32__) && !defined(__WXWINCE__) + SM_CMOUSEBUTTONS, +#else + -1, #endif - case wxSYS_BORDER_X: - return ::GetSystemMetrics(SM_CXBORDER); - case wxSYS_BORDER_Y: - return ::GetSystemMetrics(SM_CYBORDER); - case wxSYS_CURSOR_X: - return ::GetSystemMetrics(SM_CXCURSOR); - case wxSYS_CURSOR_Y: - return ::GetSystemMetrics(SM_CYCURSOR); - case wxSYS_DCLICK_X: - return ::GetSystemMetrics(SM_CXDOUBLECLK); - case wxSYS_DCLICK_Y: - return ::GetSystemMetrics(SM_CYDOUBLECLK); + SM_CXBORDER, + SM_CYBORDER, +#ifdef SM_CXCURSOR + SM_CXCURSOR, + SM_CYCURSOR, +#else + -1, -1, +#endif + SM_CXDOUBLECLK, + SM_CYDOUBLECLK, #if defined(__WIN32__) && defined(SM_CXDRAG) - case wxSYS_DRAG_X: - return ::GetSystemMetrics(SM_CXDRAG); - case wxSYS_DRAG_Y: - return ::GetSystemMetrics(SM_CYDRAG); - case wxSYS_EDGE_X: - return ::GetSystemMetrics(SM_CXEDGE); - case wxSYS_EDGE_Y: - return ::GetSystemMetrics(SM_CYEDGE); + SM_CXDRAG, + SM_CYDRAG, + SM_CXEDGE, + SM_CYEDGE, +#else + -1, -1, -1, -1, +#endif + SM_CXHSCROLL, + SM_CYHSCROLL, +#ifdef SM_CXHTHUMB + SM_CXHTHUMB, +#else + -1, +#endif + SM_CXICON, + SM_CYICON, + SM_CXICONSPACING, + SM_CYICONSPACING, +#ifdef SM_CXHTHUMB + SM_CXMIN, + SM_CYMIN, +#else + -1, -1, #endif - case wxSYS_HSCROLL_ARROW_X: - return ::GetSystemMetrics(SM_CXHSCROLL); - case wxSYS_HSCROLL_ARROW_Y: - return ::GetSystemMetrics(SM_CYHSCROLL); - case wxSYS_HTHUMB_X: - return ::GetSystemMetrics(SM_CXHTHUMB); - case wxSYS_ICON_X: - return ::GetSystemMetrics(SM_CXICON); - case wxSYS_ICON_Y: - return ::GetSystemMetrics(SM_CYICON); - case wxSYS_ICONSPACING_X: - return ::GetSystemMetrics(SM_CXICONSPACING); - case wxSYS_ICONSPACING_Y: - return ::GetSystemMetrics(SM_CYICONSPACING); - case wxSYS_WINDOWMIN_X: - return ::GetSystemMetrics(SM_CXMIN); - case wxSYS_WINDOWMIN_Y: - return ::GetSystemMetrics(SM_CYMIN); - case wxSYS_SCREEN_X: - return ::GetSystemMetrics(SM_CXSCREEN); - case wxSYS_SCREEN_Y: - return ::GetSystemMetrics(SM_CYSCREEN); + SM_CXSCREEN, + SM_CYSCREEN, #if defined(__WIN32__) && defined(SM_CXSIZEFRAME) - case wxSYS_FRAMESIZE_X: - return ::GetSystemMetrics(SM_CXSIZEFRAME); - case wxSYS_FRAMESIZE_Y: - return ::GetSystemMetrics(SM_CYSIZEFRAME); - case wxSYS_SMALLICON_X: - return ::GetSystemMetrics(SM_CXSMICON); - case wxSYS_SMALLICON_Y: - return ::GetSystemMetrics(SM_CYSMICON); + SM_CXSIZEFRAME, + SM_CYSIZEFRAME, + SM_CXSMICON, + SM_CYSMICON, +#else + -1, -1, -1, -1, #endif - case wxSYS_HSCROLL_Y: - return ::GetSystemMetrics(SM_CYHSCROLL); - case wxSYS_VSCROLL_X: - return ::GetSystemMetrics(SM_CXVSCROLL); - case wxSYS_VSCROLL_ARROW_X: - return ::GetSystemMetrics(SM_CXVSCROLL); - case wxSYS_VSCROLL_ARROW_Y: - return ::GetSystemMetrics(SM_CYVSCROLL); - case wxSYS_VTHUMB_Y: - return ::GetSystemMetrics(SM_CYVTHUMB); - case wxSYS_CAPTION_Y: - return ::GetSystemMetrics(SM_CYCAPTION); - case wxSYS_MENU_Y: - return ::GetSystemMetrics(SM_CYMENU); + SM_CYHSCROLL, + SM_CXHSCROLL, + SM_CXVSCROLL, + SM_CYVSCROLL, +#ifdef SM_CYVTHUMB + SM_CYVTHUMB, +#else + -1, +#endif + SM_CYCAPTION, + SM_CYMENU, #if defined(__WIN32__) && defined(SM_NETWORK) - case wxSYS_NETWORK_PRESENT: - return ::GetSystemMetrics(SM_NETWORK) & 0x0001; + SM_NETWORK, +#else + -1, +#endif +#ifdef SM_PENWINDOWS + SM_PENWINDOWS, +#else + -1, #endif - case wxSYS_PENWINDOWS_PRESENT: - return ::GetSystemMetrics(SM_PENWINDOWS); #if defined(__WIN32__) && defined(SM_SHOWSOUNDS) - case wxSYS_SHOW_SOUNDS: - return ::GetSystemMetrics(SM_SHOWSOUNDS); + SM_SHOWSOUNDS, +#else + -1, #endif - case wxSYS_SWAP_BUTTONS: - return ::GetSystemMetrics(SM_SWAPBUTTON); - default: - return 0; - } -} + // SM_SWAPBUTTON is not available under CE and it doesn't make sense to ask + // for it there +#ifdef SM_SWAPBUTTON + SM_SWAPBUTTON, +#else + -1, +#endif + -1 // wxSYS_DCLICK_MSEC - not available as system metric +}; -// Option functions (arbitrary name/value mapping) -void wxSystemSettings::SetOption(const wxString& name, const wxString& value) +// Get a system metric, e.g. scrollbar size +int wxSystemSettingsNative::GetMetric(wxSystemMetric index, wxWindow* WXUNUSED(win)) { - int idx = wxSystemSettingsModule::sm_optionNames.Index(name, FALSE); - if (idx == wxNOT_FOUND) +#ifdef __WXMICROWIN__ + // TODO: probably use wxUniv themes functionality + return 0; +#else // !__WXMICROWIN__ + wxCHECK_MSG( index > 0 && (size_t)index < WXSIZEOF(gs_metricsMap), 0, + wxT("invalid metric") ); + + if ( index == wxSYS_DCLICK_MSEC ) { - wxSystemSettingsModule::sm_optionNames.Add(name); - wxSystemSettingsModule::sm_optionValues.Add(value); + // This one is not a Win32 system metric + return ::GetDoubleClickTime(); } - else + + int indexMSW = gs_metricsMap[index]; + if ( indexMSW == -1 ) { - wxSystemSettingsModule::sm_optionNames[idx] = name; - wxSystemSettingsModule::sm_optionValues[idx] = value; + // not supported under current system + return -1; } -} -void wxSystemSettings::SetOption(const wxString& name, int value) -{ - wxString valStr; - valStr.Printf(wxT("%d"), value); - SetOption(name, valStr); -} + int rc = ::GetSystemMetrics(indexMSW); + if ( index == wxSYS_NETWORK_PRESENT ) + { + // only the last bit is significant according to the MSDN + rc &= 1; + } -wxString wxSystemSettings::GetOption(const wxString& name) -{ - int idx = wxSystemSettingsModule::sm_optionNames.Index(name, FALSE); - if (idx == wxNOT_FOUND) - return wxEmptyString; - else - return wxSystemSettingsModule::sm_optionValues[idx]; + return rc; +#endif // __WXMICROWIN__/!__WXMICROWIN__ } -int wxSystemSettings::GetOptionInt(const wxString& name) +bool wxSystemSettingsNative::HasFeature(wxSystemFeature index) { - return wxAtoi(GetOption(name)); + switch ( index ) + { + case wxSYS_CAN_ICONIZE_FRAME: + case wxSYS_CAN_DRAW_FRAME_DECORATIONS: + return true; + + case wxSYS_TABLET_PRESENT: + return ::GetSystemMetrics(SM_TABLETPC) != 0; + + default: + wxFAIL_MSG( wxT("unknown system feature") ); + + return false; + } } -bool wxSystemSettings::HasOption(const wxString& name) +// ---------------------------------------------------------------------------- +// function from wx/msw/wrapcctl.h: there is really no other place for it... +// ---------------------------------------------------------------------------- + +#if wxUSE_LISTCTRL || wxUSE_TREECTRL + +extern wxFont wxGetCCDefaultFont() { - return (wxSystemSettingsModule::sm_optionNames.Index(name, FALSE) != wxNOT_FOUND); +#ifndef __WXWINCE__ + // under the systems enumerated below (anything released after Win98), the + // default font used for the common controls seems to be the desktop font + // which is also used for the icon titles and not the stock default GUI + // font + bool useIconFont; + int verMaj, verMin; + switch ( wxGetOsVersion(&verMaj, &verMin) ) + { + case wxOS_WINDOWS_9X: + // 4.10 is Win98 + useIconFont = verMaj == 4 && verMin >= 10; + break; + + case wxOS_WINDOWS_NT: + // 5.0 is Win2k + useIconFont = verMaj >= 5; + break; + + default: + useIconFont = false; + } + + if ( useIconFont ) + { + LOGFONT lf; + if ( ::SystemParametersInfo + ( + SPI_GETICONTITLELOGFONT, + sizeof(lf), + &lf, + 0 + ) ) + { + return wxFont(wxCreateFontFromLogFont(&lf)); + } + else + { + wxLogLastError(wxT("SystemParametersInfo(SPI_GETICONTITLELOGFONT")); + } + } +#endif // __WXWINCE__ + + // fall back to the default font for the normal controls + return wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); } +#endif // wxUSE_LISTCTRL || wxUSE_TREECTRL