代码改变世界

自绘标题栏

2022-05-31 10:09  bgbing  阅读(169)  评论(0)    收藏  举报

//步骤如下
//
//1.去除边框标题栏
//
//2.重新设置标题栏、边框大小(OnNcCalcSize)
//
//3.设定标题栏响应区域(OnNcHitTest)
//
//4.重绘(多个地方需要重绘,但是可以调用统一绘制方法WM_MOVE、WM_PAINT、WM_NCPAINT、WM_NCACTIVATE、WM_NOTIFY)

// 设置标题栏、边框大小
void CTestDrawTitleDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
    // TODO: Add your message handler code here and/or call default
    //建议使用成员变量的方式存储各个属性
    int nTitleHeight = 40;
    int nFrameBorerL = 1;
    int nFrameBorerR = 1;
    int nFrameBorerB = 1;
    lpncsp->rgrc[0].top += nTitleHeight;
    lpncsp->rgrc[0].left += nFrameBorerL;
    lpncsp->rgrc[0].right -= nFrameBorerR;
    lpncsp->rgrc[0].bottom -= nFrameBorerB;

    CDialogEx::OnNcCalcSize(bCalcValidRects, lpncsp);
}


// 设置标题栏响应区域
LRESULT CTestDrawTitleDlg::OnNcHitTest(CPoint point)
{
    // TODO: Add your message handler code here and/or call default

    RECT rectWindows, rectClient;
    this->GetWindowRect(&rectWindows);
    this->GetClientRect(&rectClient);

    if (point.y > rectWindows.top && point.y < rectWindows.top + 40)
    {
        return HTCAPTION;//标题栏形式  
    }
    else
    {
        return CDialogEx::OnNcHitTest(point);
    }
}


LRESULT CTestDrawTitleDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class
    //以下消息可能使标题栏发生重绘,所以重新绘制,也可以响应标题栏处的鼠标移动、点击事件,
    if (message == WM_MOVE || message == WM_PAINT || message == WM_NCPAINT || message == WM_NCACTIVATE || message == WM_NOTIFY)
    {
        CDC* pWinDC = GetWindowDC();
        if (pWinDC)
            DrawTitleBar(pWinDC);
        ReleaseDC(pWinDC);
    }

    return CDialogEx::WindowProc(message, wParam, lParam);
}


void CTestDrawTitleDlg::DrawTitleBar(CDC* pDC)
{
    if (m_hWnd)
    {
        CBrush Brush(RGB(0xff, 0x63, 0x21));
        CBrush* pOldBrush = pDC->SelectObject(&Brush);

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

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

        pDC->SelectObject(pOldBrush);

        //重写标题文字
        int nOldMode = pDC->SetBkMode(TRANSPARENT);
        COLORREF clOldText = pDC->SetTextColor(RGB(255, 255, 255));
        pDC->SelectStockObject(SYSTEM_FIXED_FONT);

        CBrush b(RGB(0xd8, 0xd8, 0xd8));
        pDC->FillRect(&rtTitle, &b);

        CString m_strTitle=_T("这是一个自绘的标题栏");
        GetWindowText(m_strTitle);
        pDC->SetTextColor(clOldText);
        pDC->DrawText(m_strTitle, &rtTitle, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        pDC->SetBkMode(nOldMode);
    }
}

转载于:(19条消息) MFC自绘标题栏和边框_youyudexiaowangzi的博客-CSDN博客_mfc自绘边框