【发布时间】:2010-01-18 19:10:51
【问题描述】:
我想更新一些类似工具栏的代码,我们必须对它们进行 Vista/Win7 渐变圆角。
目前,按钮具有 Windows 2000 的外观和感觉:块状、单色调。
我玩过 XP 主题,并使用过 DrawThemeBackground、DrawThemeEdge 等;但我对主题绘图机制非常不满意(按钮很大,主题将它们绘制为 2 音调,上半部分和下半部分,当按钮很小时看起来还不错 - 它给了它们一半体面的外观对它们来说是渐变或圆润的。但这些按钮虽然大,但看起来很愚蠢。
通过简单地观察在各种应用程序和控件中绘制了多少控件来进行实验,我可以看到它们中的大多数似乎都使用了渐变——控件的顶部显示为浅色,而底部则逐渐变暗颜色 - 或 - 顶部的颜色比背景颜色浅,在中间逐渐接近白色,然后在底部逐渐变暗。
我不确定从这里去哪里。 DrawThemeXXX 似乎不够用。我真的不想用一个改进了绘图的新控件替换整个控件,但需要我换掉一些代码以了解当前自定义控件的工作方式,并冒着与其他一些库出现各种问题的风险。 我宁愿有一种方法以我正在运行的当前版本的 Windows 的样式绘制任意对象。我原以为主题绘图功能会涵盖这一点。但正如我所描述的,它们的脑损伤相当严重。
有人能告诉我“现代 C++ 应用程序应该如何绘制自定义 GUI 元素,以便他们可以合理地期待在 XP、Vista 和 Windows 7 下的优雅外观?”
目前,我们在代码中使用 MFC、Gdiplus 和原始 Win32 API。
希望有人知道如何在 Windows 下使用 C++ 绘制现代 GUI!
只是为了让这不是一堵文字墙,这是当前版本的绘制处理程序,它在“热跟踪”时绘制带有蚀刻边框的按钮,以及蚀刻边框和图标 + 文本“按下” " (移动 1,1)当处于按下状态时:
void CPlacesButton::PaintButton(CDC & dc, CRect & rcClient)
{
const int kLabelHeight = 8;
COLORREF clrHiLt = GetSysColor(COLOR_BTNHIGHLIGHT);
COLORREF clrShdo = GetSysColor(COLOR_BTNSHADOW);
COLORREF clrText = GetSysColor(COLOR_BTNTEXT);
COLORREF clrFace = GetSysColor(COLOR_BTNFACE);
// draw the button's background & border
if (m_bPressed || m_bDrawPressed || m_bMouseOnButton)
{
COLORREF clrDarkened = Darken(clrFace, -0.01f);
dc.FillRect(rcClient, &CBrush(clrDarkened));
//dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
//dc.RoundRect(&rcClient, CPoint(10,10));
dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT|BF_FLAT);
//dc.DrawFrameControl(&rcClient, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
}
// else if (m_bMouseOnButton) // hot draw
// //dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
// dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT);
// //dc.RoundRect(&rcClient, CPoint(10,10));
else
dc.FillRect(rcClient, &CBrush(clrFace));
// use transparent mode for everything that follows
dc.SetBkMode(TRANSPARENT);
// center icon
CPoint ptIcon((rcClient.Width() - m_nIconSize) / 2, ((rcClient.Height() - m_nIconSize) / 2) - kLabelHeight);
if (m_bPressed || m_bDrawPressed)
ptIcon.Offset(1, 1);
// determine the state to draw ourselves in
const UINT nState = DST_ICON | (IsEnabled() ? DSS_NORMAL : DSS_DISABLED);
// draw our icon
dc.DrawState(ptIcon, CSize(m_nIconSize, m_nIconSize), m_hIcon, nState, (HBRUSH)NULL);
// create & select the font to use for the button's label
CFont guiFont;
VERIFY(guiFont.CreateStockObject(DEFAULT_GUI_FONT));
AutoSelectGDIObject select_font(dc, guiFont);
// determine clipping rect for label
CRect rcText(0, ptIcon.y+m_nIconSize+kLabelHeight, rcClient.Width(), ptIcon.y+m_nIconSize+kLabelHeight);
rcText.InflateRect(0,20);
if (m_bPressed || m_bDrawPressed)
rcText.OffsetRect(1, 1);
dc.SetTextColor(clrText);
if (IsEnabled())
dc.DrawText(m_strCaption, rcText, DT_VCENTER|DT_SINGLELINE|DT_CENTER);
else
dc.GrayString(NULL, NULL, (LPARAM)(LPCTSTR)m_strCaption, 0, rcText.TopLeft().x, rcText.TopLeft().y, rcText.Width(), rcText.Height());
}
我在代码中留下了一些被注释掉的变体,以表明一些关于我尝试过的其他可能性的提示。但是,它们只是一个提示,因为不存在完整的替代示例。
【问题讨论】:
标签: c++ user-interface visual-c++ mfc winapi