MFC Ribbon VisualManager 修改标题 颜色
想修改标题都是通过 OnNcPaint 来实现重绘边框
为了兼容不同 样式下有不同颜色的标题,所以通过VisualManager 来实现此功能
VisualManager Window10 的样板
网上找到两处不同的代码
个人觉得 gihub上的更加完美,而且 给出了各个需要修改的函数
修改标题颜色
上述样例唯独无法修改标题颜色,
如果把 virtual BOOL IsOwnerDrawCaption() { return TRUE; }
则需要修改 virtual BOOL OnNcPaint(CWnd* pWnd, const CObList& lstSysButtons, CRect rectRedraw)override;
能力不足,无法完美实现.
所以此处 我重绘Caption virtual void OnDrawRibbonCaption(CDC* pDC, CMFCRibbonBar* pBar, CRect rectCaption, CRect rectText);
重绘标题,底色,还有按钮
由于我不知道如何获取按钮宽度,所以此处我使用固定值46, 可自行修改计算按钮位置的函数
void CWindows10Style::OnDrawRibbonCaption(CDC* pDC, CMFCRibbonBar* pBar, CRect rectCaption, CRect rectText)
{
CWnd* pWnd = pBar->GetParent();
ASSERT_VALID(pWnd);
CDrawingManager dm(*pDC);
//重绘标题底色,
dm.DrawRect(rectCaption, BCG_BLUE, BCG_BLUE);
//重绘标题文字部分
DrawCaptionText(pDC, pBar, rectText);
//重绘正常状态下的三个按钮
CRect rectButton;
//计算按钮位置
rectButton = rectCaption;
rectButton.left = rectCaption.right - 46;
OnDrawMenuSystemButton(pDC, rectButton, SC_CLOSE);
rectButton.right = rectButton.left;
rectButton.left = rectButton.right - 46;
//如果时最大的情况,则最大化,和恢复按钮的图标则不同
if (IsZoomed(pBar->GetParent()->m_hWnd))
{
OnDrawMenuSystemButton(pDC, rectButton, SC_RESTORE);
}
else
{
OnDrawMenuSystemButton(pDC, rectButton, SC_MAXIMIZE);
}
rectButton.right = rectButton.left;
rectButton.left = rectButton.right - 46;
OnDrawMenuSystemButton(pDC, rectButton, SC_MINIMIZE);
}
void CWindows10Style::OnDrawMenuSystemButton(CDC* pDC, CRect rect, UINT uiSystemCommand, UINT nStyle, BOOL bHighlight)
{
int iIndex = -1;
//找到索引
switch (uiSystemCommand)
{
case SC_CLOSE:
iIndex = 0;
break;
case SC_MINIMIZE:
iIndex = 3;
break;
case SC_RESTORE:
iIndex = 6;
break;
case SC_MAXIMIZE:
iIndex = 9;
break;
default:
return;
}
CDrawingManager dm(*pDC);
COLORREF _clrFill;
COLORREF _clrLine;
if (bHighlight)
{
if (uiSystemCommand == SC_CLOSE)
{
_clrFill = RGB_LIGHTCORAL;
_clrLine = RGB_LIGHTCORAL;
}
else
{
_clrFill = RGB_SELECTSKYBLUE;
_clrLine = RGB_SELECTSKYBLUE;
}
}
else if (nStyle>0)
{
if (uiSystemCommand == SC_CLOSE)
{
_clrFill = RGB_BRIGHTREAD;
_clrLine = RGB_BRIGHTREAD;
}
else
{
_clrFill = RGB_JEWELBLUE;
_clrLine = RGB_JEWELBLUE;
}
}
else
{
_clrFill = BCG_BLUE;
_clrLine = BCG_BLUE;
}
dm.DrawRect(rect, _clrFill, _clrFill);
CRect rtBtnImage(CPoint(0, 0), pSysBtnImages.GetImageSize());
pSysBtnImages.DrawEx(pDC, rect, iIndex, CMFCToolBarImages::ImageAlignHorzCenter, CMFCToolBarImages::ImageAlignVertCenter, rtBtnImage);
}
//此 DrawCaptionText 代码是从复制出来的,主要就为了修改标题的颜色和样式
void DrawCaptionText(CDC* pDC, CMFCRibbonBar* pBar, CRect rectText)
{
ASSERT_VALID(pDC);
ASSERT_VALID(pBar);
CWnd* pWnd = pBar->GetParent();
ASSERT_VALID(pWnd);
CString strText;
pWnd->GetWindowText(strText);
const DWORD dwStyle = pWnd->GetStyle();
const DWORD dwStyleEx = pWnd->GetExStyle();
const BOOL bIsRTL = (dwStyleEx & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL;
const BOOL bActive = IsWindowActive(pWnd);
const BOOL bGlass = pBar->IsTransparentCaption();
CString strTitle(strText);
CString strDocument;
BOOL bPrefix = FALSE;
if ((dwStyle & FWS_ADDTOTITLE) == FWS_ADDTOTITLE)
{
bPrefix = (dwStyle & FWS_PREFIXTITLE) == FWS_PREFIXTITLE;
CFrameWnd* pFrameWnd = DYNAMIC_DOWNCAST(CFrameWnd, pWnd);
if (pFrameWnd != NULL)
{
strTitle = pFrameWnd->GetTitle();
if (!strTitle.IsEmpty())
{
int pos = strText.Find(strTitle);
if (pos != -1)
{
if (strText.GetLength() > strTitle.GetLength())
{
if (pos == 0)
{
bPrefix = FALSE; // avoid exception
strTitle = strText.Left(strTitle.GetLength() + 3);
strDocument = strText.Right(strText.GetLength() - strTitle.GetLength());
}
else
{
strTitle = strText.Right(strTitle.GetLength() + 3);
strDocument = strText.Left(strText.GetLength() - strTitle.GetLength());
}
}
}
}
else
{
strDocument = strText;
}
}
}
const BOOL bIsBlackCaption = TRUE;
DrawNcText(pDC, rectText, strTitle, strDocument, bPrefix, bActive, bIsRTL, m_bNcTextCenter, bGlass,
bIsBlackCaption ? 0 : 10, bIsBlackCaption ? RGB(255, 255, 255) : (COLORREF)-1);
}
实现的样式 ,标题修改成蓝色, 重绘出 系统按钮的样式
此处我添加了Systembutton 的图形文件
目前只用到了 0 3 6 9,四个图标,其他未使用
修改系统按钮事件
所以重载
ON_WM_NCMOUSEMOVE()
ON_WM_NCMOUSELEAVE()
ON_WM_NCLBUTTONDOWN()
BOOL CMainFrame::GetSystemButtonRect(UINT iID, CRect& cButttonRect)
{
CRect cRect;
//GetClientRect(cRect);
this->m_wndRibbonBar.GetClientRect(cRect);
//cButttonRect.SetRectEmpty();
cRect.top = cRect.top+ IsZoomed() * 4;
cRect.bottom = this->m_wndRibbonBar.GetCaptionHeight() + IsZoomed()*4;
int iIndex = 0;
switch (iID)
{
case SC_CLOSE:
iIndex = 1;
break;
case SC_RESTORE:
if (!IsZoomed())
return FALSE;
iIndex = 2;
break;
case SC_MAXIMIZE:
if (IsZoomed())
return FALSE;
iIndex = 2;
break;
case SC_MINIMIZE:
iIndex = 3;
break;
default:
return false;
break;
}
cRect.left = cRect.right - 46 * iIndex;
cRect.right = cRect.left + 46;
cButttonRect = cRect;
return TRUE;
}
void CMainFrame::DrawSystemButton(int iID, BOOL Hover,BOOL bClicked)
{
CRect cButttonRect;
GetSystemButtonRect(iID, cButttonRect);
CMFCVisualManager::GetInstance()->OnDrawMenuSystemButton(GetDC(), cButttonRect, iID, Hover, bClicked);
}
void CMainFrame::OnNcMouseMove(UINT nHitTest, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if ((!m_bTracking) && (m_bVisuaManager))
{
m_bTracking = TRUE; // 标记鼠标进入窗口
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme); //结构体缓冲区大小
tme.dwFlags = TME_NONCLIENT | TME_LEAVE;//TME_NONCLIENT | TME_HOVER | TME_LEAVE; //注册WM_MOUSEHOVER消息
tme.dwHoverTime = 100; //WM_MOUSEHOVER消息触发间隔时间
tme.hwndTrack = m_hWnd; //当前窗口句柄
::TrackMouseEvent(&tme); //注册发送消息
}
if (m_bVisuaManager)
{
DrawSystemButton(SC_CLOSE, nHitTest == HTCLOSE);
DrawSystemButton(SC_MINIMIZE, nHitTest == HTMINBUTTON);
if (IsZoomed())
DrawSystemButton(SC_RESTORE, nHitTest == HTMAXBUTTON);
else
DrawSystemButton(SC_MAXIMIZE, nHitTest == HTMAXBUTTON);
}
CFrameWndEx::OnNcMouseMove(nHitTest, point);
}
void CMainFrame::OnNcMouseLeave()
{
// 该功能要求使用 Windows 2000 或更高版本。
// 符号 _WIN32_WINNT 和 WINVER 必须 >= 0x0500。
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bVisuaManager)
{
m_bTracking = FALSE;
DrawSystemButton(SC_CLOSE);
DrawSystemButton(SC_MINIMIZE);
if (IsZoomed())DrawSystemButton(SC_RESTORE);
else DrawSystemButton(SC_MAXIMIZE);
}
CFrameWndEx::OnNcMouseLeave();
}
void CMainFrame::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bVisuaManager)
{
DrawSystemButton(SC_CLOSE, FALSE,nHitTest == HTCLOSE);
DrawSystemButton(SC_MINIMIZE, FALSE,nHitTest == HTMINBUTTON);
if (IsZoomed())
DrawSystemButton(SC_RESTORE, FALSE,nHitTest == HTMAXBUTTON);
else
DrawSystemButton(SC_MAXIMIZE, FALSE,nHitTest == HTMAXBUTTON);
}
CFrameWndEx::OnNcMButtonDown(nHitTest, point);
}
且定义了 两个变量 ,为了判断是否是否需要重画系统按钮
UINT m_bTracking = FALSE;
BOOL m_bVisuaManager = FALSE;
void CMainFrame::OnApplicationLook(UINT id)
{
//....... 其他代码
if (theApp.m_nAppLook!= ID_VIEW_APPLOOK_WINDOWS_10)
{
m_bVisuaManager = FALSE;
}
else
{
m_bVisuaManager = TRUE;
}
//..... 其他代码
}
实现作用未 鼠标放在上面 显示如下