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

如何隐藏其他应用窗口的关闭、最大化、最小化按钮?SetWindowLongPtr失效

如何让移除Windows应用标题栏的代码对所有应用生效?

我有一段C#代码可以移除Windows应用中包含关闭、最小化、最大化按钮的整个标题栏区域,代码如下:

private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_FRAMECHANGED = 0x0020;
private const int GWL_STYLE = -16;
private const int WS_SYSMENU = 0x80000;
private const int WS_CAPTION = 0xC00000;

[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);

[DllImport("user32.dll", SetLastError = true)]
private static extern int SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

public void RemoveMenuAndTitle(IntPtr hwnd)
{
    if (hwnd != IntPtr.Zero)
    {
        IntPtr stylePtr;

        if (IntPtr.Size == 4) // 32-bit system
        {
            stylePtr = new IntPtr(GetWindowLongPtr(hwnd, GWL_STYLE).ToInt32());
        }
        else // 64-bit system
        {
            stylePtr = GetWindowLongPtr(hwnd, GWL_STYLE);
        }

        long style = stylePtr.ToInt64();

        style &= ~(WS_SYSMENU | WS_CAPTION);

        // Set the modified style back to the window
        IntPtr result = (IntPtr)SetWindowLongPtr(hwnd, GWL_STYLE, new IntPtr(style));

        if (result == IntPtr.Zero)
        {
            int error = Marshal.GetLastWin32Error();
            Console.WriteLine("SetWindowLongPtr failed with error code: {0}", error);
        }
        else
        {
            // Force a redraw of the window
            SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
        }
    }
}

这段代码在记事本、VLC等应用上可正常工作,但在Windows计算器、Chrome等应用上无响应且未抛出异常。我期望这段代码能对所有应用生效,请问该如何解决?


问题原因分析

  1. UWP应用(如Windows计算器):这类应用依赖Desktop Window Manager(DWM)提供的自定义框架,传统的WS_CAPTION等窗口样式不直接控制标题栏外观,应用会自行维护界面框架,修改系统样式后会被重置或忽略。
  2. 自定义窗口框架的应用(如Chrome):Chrome等应用不依赖系统默认标题栏,而是自行绘制标题栏区域。修改系统窗口样式后,应用的内部逻辑会重新检测并绘制自定义标题栏,覆盖你的修改。
  3. 权限限制:如果目标应用以管理员权限运行,你的程序若没有同等权限,将无法修改其窗口属性。
  4. 样式重置时机:部分应用在启动、窗口状态变化(如最大化/还原)时会重新设置窗口样式,你的修改会被覆盖。

解决方案

1. 针对UWP应用的处理

UWP应用依赖DWM框架,需通过DwmSetWindowAttribute修改DWM属性来隐藏标题栏:

private const int DWMWA_NO_NONCLIENT_PIXELATION = 22;
private const int DWMWA_NCAPTION_BUTTON_BOUNDS = 3;

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[DllImport("dwmapi.dll", SetLastError = true)]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, ref int pvAttribute, int cbAttribute);

[DllImport("dwmapi.dll", SetLastError = true)]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, ref RECT pvAttribute, int cbAttribute);

// 在RemoveMenuAndTitle方法中添加以下逻辑
int disableNonClient = 1;
DwmSetWindowAttribute(hwnd, DWMWA_NO_NONCLIENT_PIXELATION, ref disableNonClient, sizeof(int));

// 设置空的标题栏按钮区域以隐藏按钮
RECT emptyRect = new RECT();
DwmSetWindowAttribute(hwnd, DWMWA_NCAPTION_BUTTON_BOUNDS, ref emptyRect, Marshal.SizeOf(typeof(RECT)));

2. 针对自定义框架应用的处理

对于Chrome这类自行绘制标题栏的应用,可通过查找并隐藏其自定义标题栏控件:

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

private const int SW_HIDE = 0;

// 在RemoveMenuAndTitle中添加
IntPtr chromeTitleBar = FindWindowEx(hwnd, IntPtr.Zero, "Chrome_WidgetWin_1", null);
if (chromeTitleBar != IntPtr.Zero)
{
    ShowWindow(chromeTitleBar, SW_HIDE);
}

注:Chrome的控件类名可能随版本更新变化,需自行验证最新类名。

3. 提升程序权限

在程序的app.manifest中添加管理员权限要求,确保能修改高权限进程的窗口:

<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>

4. 防止样式被重置

设置定时器定期检查窗口样式,若发现标题栏样式被恢复则重新应用修改:

private Timer _styleCheckTimer;

public void StartStyleMonitoring(IntPtr hwnd)
{
    _styleCheckTimer = new Timer(CheckAndApplyStyle, hwnd, 0, 1000);
}

private void CheckAndApplyStyle(object state)
{
    IntPtr hwnd = (IntPtr)state;
    IntPtr stylePtr = GetWindowLongPtr(hwnd, GWL_STYLE);
    long style = stylePtr.ToInt64();
    if ((style & (WS_SYSMENU | WS_CAPTION)) != 0)
    {
        RemoveMenuAndTitle(hwnd);
    }
}

5. 扩展窗口样式修改范围

移除更多与标题栏相关的窗口样式,确保彻底清除系统标题栏相关属性:

private const int WS_THICKFRAME = 0x00040000;
private const int WS_MINIMIZEBOX = 0x00020000;
private const int WS_MAXIMIZEBOX = 0x00010000;

// 修改样式代码
style &= ~(WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:40:57