如何更改 CTabCtrl 选项卡颜色?
How to change CTabCtrl tab colors?
你好,新年快乐,(可以说到周四)
我正在尝试更改 CTabCtrl class 中选项卡的颜色。我正在尝试创建自己的 ReskinCTablCtrl,这样我就可以在单独的 classes 中调用它,并在我的程序中轻松使用它。
目前我可以更改 CTabCtrl 的背景颜色,但我无法修改选项卡本身。
我使用 ON_WM_ERASEBKGND()
绘制背景并且没有问题:
BOOL ReskinCTabCtrl::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(51, 51, 51)); // dialog background color
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SetBkColor(RGB(51, 51, 51));
pDC->FillRect(&rect, &myBrush);
return bRes;
}
但是,我自己更改标签颜色一直没有成功。它们仍然是默认的 MFC 颜色。我尝试实施 ON_WM_PAINT()
和 ON_WM_DRAWITEM()
但没有成功。我想我可以使用 OnDraw 和 DrawItem 进入特定的选项卡矩形,类似于我在这个问题末尾发布的第二个 link 示例。
void ReskinCTabCtrl::OnPaint() {
...
// paint the tabs first and then the borders
int nTab = GetItemCount();
int nSel = GetCurSel();
if (!nTab) // no pages added
return;
while (nTab--)
{
if (nTab != nSel)
{
dis.itemID = nTab;
dis.itemState = 0;
VERIFY(GetItemRect(nTab, &dis.rcItem));
dis.rcItem.bottom -= 2;
DrawItem(&dis);
DrawItemBorder(&dis);
}
}
...
}
我真的很感激至少有一些指导来解决这个问题,也许是更多的例子或者我应该重点使用哪些方法。我不需要标签有不同的颜色,也许有一种简单的方法可以做到这一点?
我一直在尝试遵循一些示例,例如以下 links,但我仍然无法找到正确的方法。
https://support.microsoft.com/en-us/help/179909/how-to-change-the-background-color-of-a-tab-control
https://www.codeproject.com/Articles/1786/Ownerdraw-Tab-Controls-Borders-and-All
在资源编辑器中为选项卡控件启用 OwnerDraw,或者在 OnInitDialog
中设置 TCS_OWNERDRAWFIXED
CTabCtrl
具有 WM_DRAWITEM
的消息反射,因此我们不想覆盖来自父 class 的 WM_DRAWITEM
/OnDrawItem
。而是覆盖 CTabCtrl::DrawItem(LPDRAWITEMSTRUCT)
.
不幸的是,结果相当丑陋。这有点像在按钮中覆盖 DrawItem
。
如果视觉样式可用并已启用,则您可以覆盖 CTabCtrl::OnPaint
并手动绘制所有内容。示例:
void CMyTabCtrl::OnPaint()
{
CPaintDC dc(this);
dc.SelectObject(GetFont());
CPen pen, pen_active;
COLORREF color_off = RGB(240, 240, 240);
COLORREF color_active = RGB(200, 240, 240);
CBrush brush_off, brush_active;
brush_off.CreateSolidBrush(color_off);
brush_active.CreateSolidBrush(color_active);
pen.CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
pen_active.CreatePen(PS_SOLID, 1, color_active);
CRect rcitem;
GetItemRect(0, &rcitem);
CRect rc;
GetClientRect(&rc);
rc.bottom = rcitem.bottom;
dc.FillSolidRect(&rc, GetSysColor(COLOR_3DFACE));
GetClientRect(&rc);
rc.top = rcitem.bottom - 1;
dc.SelectObject(&pen);
dc.SelectObject(&brush_active);
dc.Rectangle(&rc);
for(int i = 0; i < GetItemCount(); i++)
{
dc.SelectObject(&pen);
if(i == GetCurSel())
{
dc.SelectObject(&brush_active);
dc.SetBkColor(color_active);
}
else
{
dc.SelectObject(&brush_off);
dc.SetBkColor(color_off);
}
GetItemRect(i, &rcitem);
rcitem.right++;
dc.Rectangle(&rcitem);
if(i == GetCurSel())
{
dc.SelectObject(pen_active);
dc.MoveTo(rcitem.left+1, rcitem.bottom - 1);
dc.LineTo(rcitem.right, rcitem.bottom - 1);
}
TCITEM item = { 0 };
wchar_t buf[32];
item.pszText = buf;
item.cchTextMax = 32;
item.mask = TCIF_TEXT;
GetItem(i, &item);
dc.DrawText(buf, &rcitem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
BOOL CMyTabCtrl::OnEraseBkgnd(CDC*)
{
return TRUE;
}
你好,新年快乐,(可以说到周四)
我正在尝试更改 CTabCtrl class 中选项卡的颜色。我正在尝试创建自己的 ReskinCTablCtrl,这样我就可以在单独的 classes 中调用它,并在我的程序中轻松使用它。
目前我可以更改 CTabCtrl 的背景颜色,但我无法修改选项卡本身。
我使用 ON_WM_ERASEBKGND()
绘制背景并且没有问题:
BOOL ReskinCTabCtrl::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(51, 51, 51)); // dialog background color
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SetBkColor(RGB(51, 51, 51));
pDC->FillRect(&rect, &myBrush);
return bRes;
}
但是,我自己更改标签颜色一直没有成功。它们仍然是默认的 MFC 颜色。我尝试实施 ON_WM_PAINT()
和 ON_WM_DRAWITEM()
但没有成功。我想我可以使用 OnDraw 和 DrawItem 进入特定的选项卡矩形,类似于我在这个问题末尾发布的第二个 link 示例。
void ReskinCTabCtrl::OnPaint() {
...
// paint the tabs first and then the borders
int nTab = GetItemCount();
int nSel = GetCurSel();
if (!nTab) // no pages added
return;
while (nTab--)
{
if (nTab != nSel)
{
dis.itemID = nTab;
dis.itemState = 0;
VERIFY(GetItemRect(nTab, &dis.rcItem));
dis.rcItem.bottom -= 2;
DrawItem(&dis);
DrawItemBorder(&dis);
}
}
...
}
我真的很感激至少有一些指导来解决这个问题,也许是更多的例子或者我应该重点使用哪些方法。我不需要标签有不同的颜色,也许有一种简单的方法可以做到这一点?
我一直在尝试遵循一些示例,例如以下 links,但我仍然无法找到正确的方法。
https://support.microsoft.com/en-us/help/179909/how-to-change-the-background-color-of-a-tab-control
https://www.codeproject.com/Articles/1786/Ownerdraw-Tab-Controls-Borders-and-All
在资源编辑器中为选项卡控件启用 OwnerDraw,或者在 OnInitDialog
TCS_OWNERDRAWFIXED
CTabCtrl
具有 WM_DRAWITEM
的消息反射,因此我们不想覆盖来自父 class 的 WM_DRAWITEM
/OnDrawItem
。而是覆盖 CTabCtrl::DrawItem(LPDRAWITEMSTRUCT)
.
不幸的是,结果相当丑陋。这有点像在按钮中覆盖 DrawItem
。
如果视觉样式可用并已启用,则您可以覆盖 CTabCtrl::OnPaint
并手动绘制所有内容。示例:
void CMyTabCtrl::OnPaint()
{
CPaintDC dc(this);
dc.SelectObject(GetFont());
CPen pen, pen_active;
COLORREF color_off = RGB(240, 240, 240);
COLORREF color_active = RGB(200, 240, 240);
CBrush brush_off, brush_active;
brush_off.CreateSolidBrush(color_off);
brush_active.CreateSolidBrush(color_active);
pen.CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
pen_active.CreatePen(PS_SOLID, 1, color_active);
CRect rcitem;
GetItemRect(0, &rcitem);
CRect rc;
GetClientRect(&rc);
rc.bottom = rcitem.bottom;
dc.FillSolidRect(&rc, GetSysColor(COLOR_3DFACE));
GetClientRect(&rc);
rc.top = rcitem.bottom - 1;
dc.SelectObject(&pen);
dc.SelectObject(&brush_active);
dc.Rectangle(&rc);
for(int i = 0; i < GetItemCount(); i++)
{
dc.SelectObject(&pen);
if(i == GetCurSel())
{
dc.SelectObject(&brush_active);
dc.SetBkColor(color_active);
}
else
{
dc.SelectObject(&brush_off);
dc.SetBkColor(color_off);
}
GetItemRect(i, &rcitem);
rcitem.right++;
dc.Rectangle(&rcitem);
if(i == GetCurSel())
{
dc.SelectObject(pen_active);
dc.MoveTo(rcitem.left+1, rcitem.bottom - 1);
dc.LineTo(rcitem.right, rcitem.bottom - 1);
}
TCITEM item = { 0 };
wchar_t buf[32];
item.pszText = buf;
item.cchTextMax = 32;
item.mask = TCIF_TEXT;
GetItem(i, &item);
dc.DrawText(buf, &rcitem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
BOOL CMyTabCtrl::OnEraseBkgnd(CDC*)
{
return TRUE;
}