【转载】MFC标题栏重绘

源地址:http://blog.csdn.net/xshown/article/details/6712140

  • 1.mfc对话框

1.1 保留原标题栏

1.如果需要加高标题栏(用于贴图等),就要调用OnNcCalcSize追加部分空间(非客户区间):

void CMy2011082302Dlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
    lpncsp->rgrc[0].top += 25;//尺度自己把握
    //lpncsp->rgrc[0].bottom -= 100;//类似增加底边栏,此例无用
    CDialog::OnNcCalcSize(bCalcValidRects, lpncsp);
}

2.添加绘制标题栏函数DrawTitleBar():

void CMy2011082302Dlg::DrawTitleBar(CDC *pDC)
{
    if (m_hWnd)
    {
        CBrush Brush(RGB(0,100,255));
        CBrush* pOldBrush = pDC->SelectObject(&Brush);

        CRect rtWnd, rtTitle, rtButtons;
        GetWindowRect(&rtWnd);
        //取得标题栏的位置
        rtTitle.left = GetSystemMetrics(SM_CXFRAME);
        rtTitle.top = GetSystemMetrics(SM_CYFRAME);
        rtTitle.right = rtWnd.right - rtWnd.left - GetSystemMetrics(SM_CXFRAME);
        rtTitle.bottom = rtTitle.top + GetSystemMetrics(SM_CYSIZE);

        CPoint point;
        //填充顶部框架
        point.x = rtWnd.Width();
        point.y = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME)+20;
        pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
        //填充左侧框架
        point.x = GetSystemMetrics(SM_CXFRAME) + 1;
        point.y = rtWnd.Height();
        pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
        //填充底部框架
        point.x = rtWnd.Width();
        point.y = GetSystemMetrics(SM_CYFRAME) + 1;
        pDC->PatBlt(0, rtWnd.Height()-point.y, point.x, point.y, PATCOPY);
        //填充右侧框架
        point.x = GetSystemMetrics(SM_CXFRAME) + 1;
        point.y = rtWnd.Height();
        pDC->PatBlt(rtWnd.Width()-point.x, 0, point.x, point.y, PATCOPY);
        pDC->SelectObject(pOldBrush);

        //重画图标
        m_rtIcon.left = rtWnd.Width() - 135;
        m_rtIcon.top = GetSystemMetrics(SM_CYFRAME);
        m_rtIcon.right = m_rtIcon.left + 32;
        m_rtIcon.bottom = m_rtIcon.top + 32;
        ::DrawIconEx(pDC->m_hDC, m_rtIcon.left, m_rtIcon.top, m_hIcon,
            m_rtIcon.Width(), m_rtIcon.Height(), 0, NULL, DI_NORMAL);
        m_rtIcon.OffsetRect(rtWnd.TopLeft());

        //准备画XP风格按钮
        CBitmap* pBitmap = new CBitmap;
        CBitmap* pOldBitmap;
        CDC* pDisplayMemDC=new CDC;
        pDisplayMemDC->CreateCompatibleDC(pDC);

        //重画关闭button
        rtButtons.left = rtTitle.right - 19;
        rtButtons.top = rtTitle.top;
        rtButtons.right = rtButtons.left + 19;
        rtButtons.bottom = rtButtons.top + 19;
        pBitmap->LoadBitmap(IDB_EXIT_NORMAL);
        pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
        pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
        pDisplayMemDC->SelectObject(pOldBitmap);
        m_rtButtExit = rtButtons;
        m_rtButtExit.OffsetRect(rtWnd.TopLeft());
        pBitmap->DeleteObject();

        //重画最大化/恢复button
        rtButtons.right = rtButtons.left - 3;
        rtButtons.left = rtButtons.right - 19;
        if (IsZoomed())
            pBitmap->LoadBitmap(IDB_RESTORE_NORMAL);
        else
            pBitmap->LoadBitmap(IDB_MAX_NORMAL);
        pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
        pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
        pDisplayMemDC->SelectObject(pOldBitmap);
        m_rtButtMax = rtButtons;
        m_rtButtMax.OffsetRect(rtWnd.TopLeft());
        pBitmap->DeleteObject();

        //重画最小化button
        rtButtons.right = rtButtons.left - 3;
        rtButtons.left = rtButtons.right - 19;
        pBitmap->LoadBitmap(IDB_MIN_NORMAL);
        pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
        pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
        pDisplayMemDC->SelectObject(pOldBitmap);
        m_rtButtMin = rtButtons;
        m_rtButtMin.OffsetRect(rtWnd.TopLeft());
        pBitmap->DeleteObject();
        //重画帮助button
        rtButtons.right = rtButtons.left - 3;
        rtButtons.left = rtButtons.right - 19;
        pBitmap->LoadBitmap(IDB_HELP_NORMAL);
        pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
        pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
        pDisplayMemDC->SelectObject(pOldBitmap);
        m_rtButtHelp = rtButtons;
        m_rtButtHelp.OffsetRect(rtWnd.TopLeft());
        pBitmap->DeleteObject();

        //贴图
        point.x = rtWnd.Width();
        point.y = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME)+20;
        pBitmap->LoadBitmap(IDB_BITMAP1);
        pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
        pDC->BitBlt(0, 0, point.x, point.y, pDisplayMemDC, 0, 0, SRCCOPY);
        pDisplayMemDC->SelectObject(pOldBitmap);
        pBitmap->DeleteObject();
        //拉伸图片
        //pDC->StretchBlt(x,y, nW, nH ,&memDc,0,0,
        //bm.bmWidth,bm.bmHeight,SRCCOPY);
        //重写标题文字
        int nOldMode = pDC->SetBkMode(TRANSPARENT);
        COLORREF clOldText=pDC->SetTextColor(RGB(255, 255, 255));
        pDC->SelectStockObject(SYSTEM_FIXED_FONT);
        rtTitle.left += 2;
        rtTitle.top += GetSystemMetrics(SM_CYSIZE);
        rtTitle.bottom = rtTitle.top + 30;
        CString m_strTitle;
        GetWindowText(m_strTitle);
        pDC->DrawText(m_strTitle, &rtTitle, DT_LEFT);
        pDC->SetBkMode(nOldMode);
        pDC->SetTextColor(clOldText);

        ReleaseDC(pDisplayMemDC);
        delete pDisplayMemDC;
        delete pBitmap;
    }
}

1.2 去除原标题栏
1.去除窗口标题风格
2.添加响应按钮(最大化、最小化等)
3.贴图(可借助众所周知的BitButtonNL类 )处理
4.添加可供窗口拖移消息欺骗:

void CMy2011082302Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
//处理移动
    if (point.y < 26)
        PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));
    CDialog::OnLButtonDown(nFlags, point);
}

2、mfc单/多文档

  2.1  保留原标题栏

    方法同1.1

问题:

1)  禁用cs.style&=~WS_SYSMENU;(为了去除原标题栏按钮) ,但这导致邮件菜单不可用。

2)  不名操作闪烁(个别特殊操作,基本不会)

3)  1.1中的第1步如果单/多文档绘制了菜单,会出现菜单夹中问题。如需菜单建议菜单重绘或bcg界面库工程

  2.2  去除原标题栏
由于2.1中的问题1和2,再加上去除标题栏所导致的非客户区自绘按钮消息无法响应以及窗口无法拖动等情况,我们必须用OnNcHitTest改变新增加空间(1.1中第1步)为HTCAPTION属性。
1.去除标题栏 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){} 添加:ModifyStyle(WS_CAPTION,WS_DLGFRAME,SWP_FRAMECHANGED);
2.同1.1中1.2.3步。1步不可缺省哦
3.   OnNcHitTest返回HTCAPTION:
UINT CMainFrame::OnNcHitTest(CPoint point)
{
    RECT rectWindows, rectClient;
    this->GetWindowRect(&rectWindows);
    this->GetClientRect(&rectClient);
    if (point.y > rectWindows.top && point.y < rectWindows.top + 25)
    {
        return HTCAPTION;//标题栏形式
    }
    else
    {
        return CFrameWnd::OnNcHitTest(point);
    }
}
原文地址:https://www.cnblogs.com/frkang/p/3076765.html