MFC VisualManager 实现 Ribbon 修改标题 颜色

MFC Ribbon VisualManager 修改标题 颜色

想修改标题都是通过 OnNcPaint 来实现重绘边框
为了兼容不同 样式下有不同颜色的标题,所以通过VisualManager 来实现此功能

VisualManager Window10 的样板

网上找到两处不同的代码

csdn

github

个人觉得 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 的图形文件IDB_SYSTEM_BUTTONS
目前只用到了 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;
	}
//..... 其他代码
}

实现作用未 鼠标放在上面 显示如下 在这里插入图片描述

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值