You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅绘制窗口标题栏?使用WM_NCPAINT出现异常如何解决?

问题根因

  • WM_NCPAINT绘制API使用错误:BeginPaint/EndPaint是专门用于处理WM_PAINT消息、仅返回客户区绘制上下文的API,你用这个获取到的DC本身只对应客户区,自然会绘制到客户区上,非客户区绘制应该调用GetWindowDC获取整个窗口的DC,绘制完成后调用ReleaseDC释放。
  • 没有调用基类的OnNcPaint实现:你重写了OnNcPaint但完全跳过了MFC基类默认的非客户区绘制逻辑,系统默认的标题栏、边框绘制逻辑都没有执行,所以启动时标题栏直接消失。
  • Win10风格标题栏回退到Win7风格的原因:Win10及以上系统的默认现代化标题栏是由DWM(桌面窗口管理器)负责绘制的,自定义处理WM_NCPAINT且没有兼容DWM绘制逻辑时,系统会自动禁用当前窗口的DWM非客户区渲染,回退到Win7时代的GDI绘制风格。

修复方案

你可以参考以下修改后的代码实现自定义非客户区绘制:

class CMainFrame : public CFrameWnd
{
public:
    CMainFrame()
    {
        Create(
            NULL, 
            _T("Hello World!"), 
            WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, 
            CRect(CPoint(100, 100), CSize(640, 360)));
    }
protected:
    afx_msg void OnNcPaint();
    DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_WM_NCPAINT()
END_MESSAGE_MAP()

void CMainFrame::OnNcPaint()
{
    // 先调用基类实现完成默认非客户区绘制,若要完全自定义标题栏可删除此行自行实现全部绘制逻辑
    CFrameWnd::OnNcPaint();

    // 获取包含非客户区的全窗口DC
    CDC* pDC = GetWindowDC();
    CBrush brush;
    brush.CreateSolidBrush(RGB(0, 0, 255));
    
    // 计算标题栏区域范围,避免绘制到客户区
    CRect ncRect;
    GetWindowRect(&ncRect);
    ncRect.OffsetRect(-ncRect.left, -ncRect.top); // 转换为窗口DC对应的相对坐标
    ncRect.bottom = ncRect.top + GetSystemMetrics(SM_CYCAPTION); // 仅保留标题栏高度的区域
    
    pDC->FillRect(&ncRect, &brush);

    // 释放DC资源
    ReleaseDC(pDC);
}

class CApplication : public CWinApp {
    BOOL InitInstance() override {
        CMainFrame* mainWnd = new CMainFrame();
        m_pMainWnd = mainWnd;

        mainWnd->ShowWindow(SW_NORMAL);
        mainWnd->UpdateWindow();
        
        return TRUE;
    }
};
  • 如果你要完全自定义标题栏、不需要系统默认绘制,可以删除基类调用,同时需要自行处理所有非客户区元素的绘制(标题文字、最小化/关闭按钮、边框等),并且需要处理WM_NCCALCSIZE消息调整客户区范围,避免自定义的标题栏和客户区内容重叠。
  • 如果需要保留Win10/Win11的现代化标题栏风格,建议不要直接重写WM_NCPAINT,改为使用DWM相关API扩展自定义标题栏内容。

内容的提问来源于stack exchange,提问作者lynx pravoka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 17:15:07