No real changes, just cleanup of wxMSW MenuDrawData.

Derive MenuDrawData::Margins from Windows MARGINS struct to avoid ugly (and
potentially dangerous) reinterpret_cast<>s when using it.

Also add some helper functions to Margins to make using it less painful.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65954 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-10-30 23:50:08 +00:00
parent 7eae80a04b
commit abaa31e7ea

View File

@@ -192,20 +192,36 @@ namespace
class MenuDrawData class MenuDrawData
{ {
public: public:
// Wrapper around standard MARGINS structure providing some helper
struct Margins // functions and automatically initializing the margin fields to 0.
struct Margins : MARGINS
{ {
int left;
int right;
int top;
int bottom;
Margins() Margins()
: left(0), {
right(0), cxLeftWidth =
top(0), cxRightWidth =
bottom(0) cyTopHeight =
{} cyBottomHeight = 0;
}
int GetTotalX() const { return cxLeftWidth + cxRightWidth; }
int GetTotalY() const { return cyTopHeight + cyBottomHeight; }
void ApplyTo(RECT& rect) const
{
rect.top += cyTopHeight;
rect.left += cxLeftWidth;
rect.right -= cyTopHeight;
rect.bottom -= cyBottomHeight;
}
void UnapplyFrom(RECT& rect) const
{
rect.top -= cyTopHeight;
rect.left -= cxLeftWidth;
rect.right += cyTopHeight;
rect.bottom += cyBottomHeight;
}
}; };
Margins ItemMargin; // popup item margins Margins ItemMargin; // popup item margins
@@ -318,22 +334,22 @@ void MenuDrawData::Init()
theme->GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0, theme->GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0,
TMT_CONTENTMARGINS, NULL, TMT_CONTENTMARGINS, NULL,
reinterpret_cast<MARGINS*>(&ItemMargin)); &ItemMargin);
theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECK, 0, theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECK, 0,
TMT_CONTENTMARGINS, NULL, TMT_CONTENTMARGINS, NULL,
reinterpret_cast<MARGINS*>(&CheckMargin)); &CheckMargin);
theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECKBACKGROUND, 0, theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECKBACKGROUND, 0,
TMT_CONTENTMARGINS, NULL, TMT_CONTENTMARGINS, NULL,
reinterpret_cast<MARGINS*>(&CheckBgMargin)); &CheckBgMargin);
theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSUBMENU, 0, theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSUBMENU, 0,
TMT_CONTENTMARGINS, NULL, TMT_CONTENTMARGINS, NULL,
reinterpret_cast<MARGINS*>(&ArrowMargin)); &ArrowMargin);
theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSEPARATOR, 0, theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
TMT_SIZINGMARGINS, NULL, TMT_SIZINGMARGINS, NULL,
reinterpret_cast<MARGINS*>(&SeparatorMargin)); &SeparatorMargin);
theme->GetThemePartSize(hTheme, NULL, MENU_POPUPCHECK, 0, theme->GetThemePartSize(hTheme, NULL, MENU_POPUPCHECK, 0,
NULL, TS_TRUE, &CheckSize); NULL, TS_TRUE, &CheckSize);
@@ -358,43 +374,38 @@ void MenuDrawData::Init()
Theme = true; Theme = true;
// native menu doesn't uses the vertical margins // native menu doesn't uses the vertical margins
ItemMargin.top = ItemMargin.bottom = 0; ItemMargin.cyTopHeight =
ItemMargin.cyBottomHeight = 0;
// native menu uses small top margin for separator // native menu uses small top margin for separator
if ( SeparatorMargin.top >= 2 ) if ( SeparatorMargin.cyTopHeight >= 2 )
SeparatorMargin.top -= 2; SeparatorMargin.cyTopHeight -= 2;
} }
else else
#endif // wxUSE_UXTHEME #endif // wxUSE_UXTHEME
{ {
const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics(); const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics();
ItemMargin = Margins(); CheckMargin.cxLeftWidth =
CheckMargin.cxRightWidth = ::GetSystemMetrics(SM_CXEDGE);
CheckMargin.left = CheckMargin.cyTopHeight =
CheckMargin.right = ::GetSystemMetrics(SM_CXEDGE); CheckMargin.cyBottomHeight = ::GetSystemMetrics(SM_CYEDGE);
CheckMargin.top =
CheckMargin.bottom = ::GetSystemMetrics(SM_CYEDGE);
CheckBgMargin = Margins();
CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK); CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK); CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
ArrowMargin = Margins();
ArrowSize = CheckSize; ArrowSize = CheckSize;
// separator height with margins // separator height with margins
int sepFullSize = metrics.iMenuHeight / 2; int sepFullSize = metrics.iMenuHeight / 2;
SeparatorMargin.left = SeparatorMargin.cxLeftWidth =
SeparatorMargin.right = 1; SeparatorMargin.cxRightWidth = 1;
SeparatorMargin.top = SeparatorMargin.cyTopHeight =
SeparatorMargin.bottom = sepFullSize / 2 - 1; SeparatorMargin.cyBottomHeight = sepFullSize / 2 - 1;
SeparatorSize.cx = 1; SeparatorSize.cx = 1;
SeparatorSize.cy = sepFullSize - SeparatorMargin.top - SeparatorMargin.bottom; SeparatorSize.cy = sepFullSize - SeparatorMargin.GetTotalY();
TextBorder = 0; TextBorder = 0;
AccelBorder = 8; AccelBorder = 8;
@@ -745,15 +756,15 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
if ( IsOwnerDrawn() ) if ( IsOwnerDrawn() )
{ {
*width = data->ItemMargin.left + data->ItemMargin.right; *width = data->ItemMargin.GetTotalX();
*height = data->ItemMargin.top + data->ItemMargin.bottom; *height = data->ItemMargin.GetTotalY();
if ( IsSeparator() ) if ( IsSeparator() )
{ {
*width += data->SeparatorSize.cx *width += data->SeparatorSize.cx
+ data->SeparatorMargin.left + data->SeparatorMargin.right; + data->SeparatorMargin.GetTotalX();
*height += data->SeparatorSize.cy *height += data->SeparatorSize.cy
+ data->SeparatorMargin.top + data->SeparatorMargin.bottom; + data->SeparatorMargin.GetTotalY();
return true; return true;
} }
@@ -775,7 +786,7 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
*width += w + data->ArrowBorder; *width += w + data->ArrowBorder;
*width += data->Offset; *width += data->Offset;
*width += data->ArrowMargin.left + data->ArrowSize.cx + data->ArrowMargin.right; *width += data->ArrowMargin.GetTotalX() + data->ArrowSize.cx;
} }
else // don't draw the text, just the bitmap (if any) else // don't draw the text, just the bitmap (if any)
{ {
@@ -794,9 +805,9 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
// bitmap in menu (GetMarginWidth()) unless std check mark is wider, // bitmap in menu (GetMarginWidth()) unless std check mark is wider,
// then it's is set to std mark's width // then it's is set to std mark's width
int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx) int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx)
+ data->CheckMargin.left + data->CheckMargin.right; + data->CheckMargin.GetTotalX();
*width += imgWidth + data->CheckBgMargin.left + data->CheckBgMargin.right; *width += imgWidth + data->CheckBgMargin.GetTotalX();
} }
if ( m_bmpChecked.IsOk() || m_bmpChecked.IsOk() ) if ( m_bmpChecked.IsOk() || m_bmpChecked.IsOk() )
@@ -808,7 +819,7 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
if ( IsOwnerDrawn() ) if ( IsOwnerDrawn() )
{ {
heightBmp += data->CheckMargin.top + data->CheckMargin.bottom; heightBmp += data->CheckMargin.GetTotalY();
} }
else else
{ {
@@ -822,7 +833,7 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
} }
// make sure that this item is at least as tall as the system menu height // make sure that this item is at least as tall as the system menu height
const size_t menuHeight = data->CheckMargin.top + data->CheckMargin.bottom const size_t menuHeight = data->CheckMargin.GetTotalY()
+ data->CheckSize.cy; + data->CheckSize.cy;
if (*height < menuHeight) if (*height < menuHeight)
*height = menuHeight; *height = menuHeight;
@@ -856,32 +867,21 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
DWORD colBack = wxColourToPalRGB(colBack1); DWORD colBack = wxColourToPalRGB(colBack1);
// calculate metrics of item parts // calculate metrics of item parts
RECT rcSelection; RECT rcSelection = rect;
RECT rcSeparator; data->ItemMargin.ApplyTo(rcSelection);
RECT rcGutter;
RECT rcText;
SetRect(&rcSelection, RECT rcSeparator = rcSelection;
rect.left + data->ItemMargin.left, data->SeparatorMargin.ApplyTo(rcSeparator);
rect.top + data->ItemMargin.top,
rect.right - data->ItemMargin.right,
rect.bottom - data->ItemMargin.bottom);
SetRect(&rcSeparator, RECT rcGutter = rcSelection;
rcSelection.left + data->SeparatorMargin.left, rcGutter.right = data->ItemMargin.cxLeftWidth
rcSelection.top + data->SeparatorMargin.top, + data->CheckBgMargin.cxLeftWidth
rcSelection.right - data->SeparatorMargin.right, + data->CheckMargin.cxLeftWidth
rcSelection.bottom - data->SeparatorMargin.bottom);
CopyRect(&rcGutter, &rcSelection);
rcGutter.right = data->ItemMargin.left
+ data->CheckBgMargin.left
+ data->CheckMargin.left
+ imgWidth + imgWidth
+ data->CheckMargin.right + data->CheckMargin.cxRightWidth
+ data->CheckBgMargin.right; + data->CheckBgMargin.cxRightWidth;
CopyRect(&rcText, &rcSelection); RECT rcText = rcSelection;
rcText.left = rcGutter.right + data->TextBorder; rcText.left = rcGutter.right + data->TextBorder;
// we draw the text label vertically centered, but this results in it // we draw the text label vertically centered, but this results in it
@@ -998,9 +998,8 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
(stat & wxODDisabled) && !(stat & wxODSelected) ) (stat & wxODDisabled) && !(stat & wxODSelected) )
flags |= DSS_DISABLED; flags |= DSS_DISABLED;
int x = rcText.right - data->ArrowMargin.left int x = rcText.right - data->ArrowMargin.GetTotalX()
- data->ArrowSize.cx - data->ArrowSize.cx
- data->ArrowMargin.right
- data->ArrowBorder; - data->ArrowBorder;
// right align accel on FullTheme menu, left otherwise // right align accel on FullTheme menu, left otherwise
@@ -1025,19 +1024,19 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
RECT rcImg; RECT rcImg;
SetRect(&rcImg, SetRect(&rcImg,
rect.left + data->ItemMargin.left rect.left + data->ItemMargin.cxLeftWidth
+ data->CheckBgMargin.left + data->CheckBgMargin.cxLeftWidth
+ data->CheckMargin.left, + data->CheckMargin.cxLeftWidth,
rect.top + data->ItemMargin.top rect.top + data->ItemMargin.cyTopHeight
+ data->CheckBgMargin.top + data->CheckBgMargin.cyTopHeight
+ data->CheckMargin.top, + data->CheckMargin.cyTopHeight,
rect.left + data->ItemMargin.left rect.left + data->ItemMargin.cxLeftWidth
+ data->CheckBgMargin.left + data->CheckBgMargin.cxLeftWidth
+ data->CheckMargin.left + data->CheckMargin.cxLeftWidth
+ imgWidth, + imgWidth,
rect.bottom - data->ItemMargin.bottom rect.bottom - data->ItemMargin.cyBottomHeight
- data->CheckBgMargin.bottom - data->CheckBgMargin.cyBottomHeight
- data->CheckMargin.bottom); - data->CheckMargin.cyBottomHeight);
if ( IsCheckable() && !m_bmpChecked.Ok() ) if ( IsCheckable() && !m_bmpChecked.Ok() )
{ {
@@ -1154,12 +1153,8 @@ void wxMenuItem::DrawStdCheckMark(WXHDC hdc_, const RECT* rc, wxODStatus stat)
const MenuDrawData* data = MenuDrawData::Get(); const MenuDrawData* data = MenuDrawData::Get();
// rect for background must be without check margins // rect for background must be without check margins
RECT rcBg; RECT rcBg = *rc;
SetRect(&rcBg, data->CheckMargin.UnapplyFrom(rcBg);
rc->left - data->CheckMargin.left,
rc->top - data->CheckMargin.top,
rc->right + data->CheckMargin.right,
rc->bottom + data->CheckMargin.bottom);
POPUPCHECKBACKGROUNDSTATES stateCheckBg = (stat & wxODDisabled) POPUPCHECKBACKGROUNDSTATES stateCheckBg = (stat & wxODDisabled)
? MCB_DISABLED ? MCB_DISABLED