Fix confusion with LOGFONT{A,W} parameters to MSW GetTheme[Sys]Font().
Change the signature of GetThemeFont() and GetThemeSysFont() methods of wxUxThemeEngine to take an artificial wxUxThemeFont::Ptr type instead of LOGFONT which allows the broken code to compile correctly and even work in Unicode builds but crashed in ANSI ones under Windows Vista/7 as these functions expect a LOGFONTW and not LOGFONTA even in non-Unicode build under these systems. This generalizes the previous fix/workaround for the same problem in wxStaticBox so remove it now and use wxUxThemeFont both there and in wxMenuItem to avoid crashes when using owner-drawn menus in ANSI build. Closes #12364. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65955 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -17,6 +17,74 @@
|
|||||||
#include "wx/msw/private.h" // we use GetHwndOf()
|
#include "wx/msw/private.h" // we use GetHwndOf()
|
||||||
#include "wx/msw/uxthemep.h"
|
#include "wx/msw/uxthemep.h"
|
||||||
|
|
||||||
|
// Amazingly, GetThemeFont() and GetThemeSysFont() functions use LOGFONTA under
|
||||||
|
// XP but LOGFONTW (even in non-Unicode build) under later versions of Windows.
|
||||||
|
// If we declare them as taking LOGFONT below, the code would be able to
|
||||||
|
// silently pass LOGFONTA to them in ANSI build and would crash at run-time
|
||||||
|
// under Windows Vista/7 because of a buffer overrun (LOGFONTA being smaller
|
||||||
|
// than LOGFONTW expected by these functions). If we we declare them as taking
|
||||||
|
// LOGFONTW, the code wouldn't work correctly under XP. So we use a special
|
||||||
|
// wxUxThemeFont class to encapsulate this and intentionally change the LOGFONT
|
||||||
|
// output parameters of the theme functions to take it instead.
|
||||||
|
|
||||||
|
class wxUxThemeFont
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Trivial default ctor.
|
||||||
|
wxUxThemeFont() { }
|
||||||
|
|
||||||
|
// Just some unique type.
|
||||||
|
struct Ptr { };
|
||||||
|
|
||||||
|
#if wxUSE_UNICODE
|
||||||
|
// In Unicode build we always use LOGFONT anyhow so this class is
|
||||||
|
// completely trivial.
|
||||||
|
Ptr *GetPtr() { return reinterpret_cast<Ptr *>(&m_lfW); }
|
||||||
|
const LOGFONTW& GetLOGFONT() { return m_lfW; }
|
||||||
|
#else // !wxUSE_UNICODE
|
||||||
|
// Return either LOGFONTA or LOGFONTW pointer as required by the current
|
||||||
|
// Windows version.
|
||||||
|
Ptr *GetPtr()
|
||||||
|
{
|
||||||
|
return UseLOGFONTW() ? reinterpret_cast<Ptr *>(&m_lfW)
|
||||||
|
: reinterpret_cast<Ptr *>(&m_lfA);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method returns LOGFONT (i.e. LOGFONTA in ANSI build and LOGFONTW in
|
||||||
|
// Unicode one) which can be used with other, normal, Windows or wx
|
||||||
|
// functions. Internally it may need to transform LOGFONTW to LOGFONTA.
|
||||||
|
const LOGFONTA& GetLOGFONT()
|
||||||
|
{
|
||||||
|
if ( UseLOGFONTW() )
|
||||||
|
{
|
||||||
|
// Most of the fields are the same in LOGFONTA and LOGFONTW so just
|
||||||
|
// copy everything by default.
|
||||||
|
memcpy(&m_lfA, &m_lfW, sizeof(m_lfA));
|
||||||
|
|
||||||
|
// But the face name must be converted from Unicode.
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, m_lfW.lfFaceName, -1,
|
||||||
|
m_lfA.lfFaceName, sizeof(m_lfA.lfFaceName),
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_lfA;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool UseLOGFONTW()
|
||||||
|
{
|
||||||
|
return wxGetWinVersion() >= wxWinVersion_Vista;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGFONTA m_lfA;
|
||||||
|
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
|
||||||
|
|
||||||
|
private:
|
||||||
|
LOGFONTW m_lfW;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxUxThemeFont);
|
||||||
|
};
|
||||||
|
|
||||||
typedef HTHEME (__stdcall *PFNWXUOPENTHEMEDATA)(HWND, const wchar_t *);
|
typedef HTHEME (__stdcall *PFNWXUOPENTHEMEDATA)(HWND, const wchar_t *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUCLOSETHEMEDATA)(HTHEME);
|
typedef HRESULT (__stdcall *PFNWXUCLOSETHEMEDATA)(HTHEME);
|
||||||
typedef HRESULT (__stdcall *PFNWXUDRAWTHEMEBACKGROUND)(HTHEME, HDC, int, int, const RECT *, const RECT *);
|
typedef HRESULT (__stdcall *PFNWXUDRAWTHEMEBACKGROUND)(HTHEME, HDC, int, int, const RECT *, const RECT *);
|
||||||
@@ -39,7 +107,7 @@ typedef HRESULT (__stdcall *PFNWXUGETTHEMEBOOL)(HTHEME, int, int, int, BOOL *);
|
|||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEINT)(HTHEME, int, int, int, int *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEINT)(HTHEME, int, int, int, int *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEENUMVALUE)(HTHEME, int, int, int, int *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEENUMVALUE)(HTHEME, int, int, int, int *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEPOSITION)(HTHEME, int, int, int, POINT *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEPOSITION)(HTHEME, int, int, int, POINT *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEFONT)(HTHEME, HDC, int, int, int, LOGFONT *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEFONT)(HTHEME, HDC, int, int, int, wxUxThemeFont::Ptr *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMERECT)(HTHEME, int, int, int, RECT *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMERECT)(HTHEME, int, int, int, RECT *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEMARGINS)(HTHEME, HDC, int, int, int, RECT *, MARGINS *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEMARGINS)(HTHEME, HDC, int, int, int, RECT *, MARGINS *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMEINTLIST)(HTHEME, int, int, int, INTLIST*);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMEINTLIST)(HTHEME, int, int, int, INTLIST*);
|
||||||
@@ -50,7 +118,7 @@ typedef COLORREF(__stdcall *PFNWXUGETTHEMESYSCOLOR)(HTHEME, int);
|
|||||||
typedef HBRUSH (__stdcall *PFNWXUGETTHEMESYSCOLORBRUSH)(HTHEME, int);
|
typedef HBRUSH (__stdcall *PFNWXUGETTHEMESYSCOLORBRUSH)(HTHEME, int);
|
||||||
typedef BOOL (__stdcall *PFNWXUGETTHEMESYSBOOL)(HTHEME, int);
|
typedef BOOL (__stdcall *PFNWXUGETTHEMESYSBOOL)(HTHEME, int);
|
||||||
typedef int (__stdcall *PFNWXUGETTHEMESYSSIZE)(HTHEME, int);
|
typedef int (__stdcall *PFNWXUGETTHEMESYSSIZE)(HTHEME, int);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSFONT)(HTHEME, int, LOGFONT *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSFONT)(HTHEME, int, wxUxThemeFont::Ptr *);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSSTRING)(HTHEME, int, wchar_t *, int);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSSTRING)(HTHEME, int, wchar_t *, int);
|
||||||
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSINT)(HTHEME, int, int *);
|
typedef HRESULT (__stdcall *PFNWXUGETTHEMESYSINT)(HTHEME, int, int *);
|
||||||
typedef BOOL (__stdcall *PFNWXUISTHEMEACTIVE)();
|
typedef BOOL (__stdcall *PFNWXUISTHEMEACTIVE)();
|
||||||
|
@@ -367,9 +367,9 @@ void MenuDrawData::Init()
|
|||||||
|
|
||||||
Offset = -14;
|
Offset = -14;
|
||||||
|
|
||||||
wxNativeFontInfo fontInfo;
|
wxUxThemeFont themeFont;
|
||||||
theme->GetThemeSysFont(hTheme, TMT_MENUFONT, &fontInfo.lf);
|
theme->GetThemeSysFont(hTheme, TMT_MENUFONT, themeFont.GetPtr());
|
||||||
Font = wxFont(fontInfo);
|
Font = wxFont(themeFont.GetLOGFONT());
|
||||||
|
|
||||||
Theme = true;
|
Theme = true;
|
||||||
|
|
||||||
|
@@ -430,11 +430,7 @@ void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc)
|
|||||||
wxUxThemeHandle hTheme(this, L"BUTTON");
|
wxUxThemeHandle hTheme(this, L"BUTTON");
|
||||||
if ( hTheme )
|
if ( hTheme )
|
||||||
{
|
{
|
||||||
// GetThemeFont() expects its parameter to be LOGFONTW and not
|
wxUxThemeFont themeFont;
|
||||||
// LOGFONTA even in ANSI programs and will happily corrupt
|
|
||||||
// memory after the struct end if we pass a LOGFONTA (which is
|
|
||||||
// smaller) to it!
|
|
||||||
LOGFONTW lfw;
|
|
||||||
if ( wxUxThemeEngine::Get()->GetThemeFont
|
if ( wxUxThemeEngine::Get()->GetThemeFont
|
||||||
(
|
(
|
||||||
hTheme,
|
hTheme,
|
||||||
@@ -442,24 +438,10 @@ void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc)
|
|||||||
BP_GROUPBOX,
|
BP_GROUPBOX,
|
||||||
GBS_NORMAL,
|
GBS_NORMAL,
|
||||||
TMT_FONT,
|
TMT_FONT,
|
||||||
(LOGFONT *)&lfw
|
themeFont.GetPtr()
|
||||||
) == S_OK )
|
) == S_OK )
|
||||||
{
|
{
|
||||||
#if wxUSE_UNICODE
|
font.Init(themeFont.GetLOGFONT());
|
||||||
// ok, no conversion necessary
|
|
||||||
const LOGFONT& lf = lfw;
|
|
||||||
#else // !wxUSE_UNICODE
|
|
||||||
// most of the fields are the same in LOGFONTA and LOGFONTW
|
|
||||||
LOGFONT lf;
|
|
||||||
memcpy(&lf, &lfw, sizeof(lf));
|
|
||||||
|
|
||||||
// but the face name must be converted
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, lfw.lfFaceName, -1,
|
|
||||||
lf.lfFaceName, sizeof(lf.lfFaceName),
|
|
||||||
NULL, NULL);
|
|
||||||
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
|
|
||||||
|
|
||||||
font.Init(lf);
|
|
||||||
if ( font )
|
if ( font )
|
||||||
selFont.Init(hdc, font);
|
selFont.Init(hdc, font);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user