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

如何移除窗口标题栏同时保留最小化/最大化动画?

解决无标题栏窗口最小化/还原动画丢失问题

核心原因

直接使用WS_POPUP样式创建的窗口,系统默认不会为其提供最小化/还原的标准动画——这类样式通常用于特殊窗口(如自定义弹窗、悬浮面板),不在系统标准窗口动画的适配范围内。而带标题栏的WS_OVERLAPPEDWINDOW窗口,系统会自动启用动画逻辑。

最优解决方案:保留标准窗口类型,隐藏标题栏

通过使用WS_OVERLAPPEDWINDOW作为基础样式,再通过修改窗口非客户区来隐藏标题栏,既保留系统动画支持,又实现无标题栏效果。

步骤1:修改窗口创建代码

将原本的WS_POPUP替换为WS_OVERLAPPEDWINDOW,保留所需的控制样式:

WNDCLASSEX wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)), nullptr, nullptr, nullptr, window::class_name, nullptr };
::RegisterClassEx(&wc);
// 用WS_OVERLAPPEDWINDOW替代WS_POPUP
g_hWnd = ::CreateWindowExA(0, wc.lpszClassName, window::window_name, WS_OVERLAPPEDWINDOW | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU, x, y, window::g_Width, window::g_Height, nullptr, nullptr, wc.hInstance, nullptr);

步骤2:在窗口过程中处理WM_NCCALCSIZE消息,隐藏标题栏

在WndProc中添加对WM_NCCALCSIZE的处理,移除标题栏和边框,让客户区占满整个窗口:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_NCCALCSIZE:
            if (wParam == TRUE)
            {
                NCCALCSIZE_PARAMS* pParams = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
                // 调整客户区范围,覆盖标题栏和边框
                pParams->rgrc[0].top += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
                pParams->rgrc[0].left += GetSystemMetrics(SM_CXFRAME);
                pParams->rgrc[0].right -= GetSystemMetrics(SM_CXFRAME);
                pParams->rgrc[0].bottom -= GetSystemMetrics(SM_CYFRAME);
                return 0; // 告诉系统我们已修改了客户区大小
            }
            break;

        // 其他消息处理...
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

备选方案:手动触发动画(不推荐)

如果坚持使用WS_POPUP样式,需要手动监听任务栏点击事件(通过WM_SYSCOMMAND消息中的SC_MINIMIZE/SC_RESTORE命令),调用AnimateWindow函数实现动画:

case WM_SYSCOMMAND:
    if (wParam == SC_MINIMIZE)
    {
        AnimateWindow(hWnd, 200, AW_HIDE | AW_SLIDE | AW_VER_POSITIVE);
        ShowWindow(hWnd, SW_MINIMIZE);
        return 0;
    }
    else if (wParam == SC_RESTORE)
    {
        ShowWindow(hWnd, SW_RESTORE);
        AnimateWindow(hWnd, 200, AW_ACTIVATE | AW_SLIDE | AW_VER_NEGATIVE);
        return 0;
    }
    break;

这种方法需要自己维护窗口状态,且动画效果可能和系统默认不一致,不如第一种方案稳定可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:44:57