如何在运行时删除WPF窗口图标

问题描述 投票:0回答:1

我想知道是否有一种简单的方法可以在运行时添加和删除 WPF 窗口的图标。这不是重复的问题;请仔细阅读。我需要一种方法来在程序运行且窗口初始化时隐藏 WPF 窗口的图标。我所有的搜索都会路由到此代码示例(来自 Stack Overflow):

IntPtr hwnd = new WindowInteropHelper(window).Handle;

// Change the extended window style to not show a window icon
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);

// Update the window's non-client area to reflect the changes
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

...这不起作用。我已经进行了广泛的尝试,可以确认在 64 位 Windows 10 版本 1607 上它根本不起作用。我得到的另一个代码示例是这个(也来自 Stack Overflow):

const int ICON_SMALL = 0;
const int ICON_BIG = 1;

IntPtr hWnd = new WindowInteropHelper(this).Handle;
int currentStyle = (int)GetWindowLong(hWnd, GWL_EXSTYLE);

SetWindowLong(hWnd, GWL_EXSTYLE, (uint)currentStyle | WS_EX_DLGMODALFRAME);

SendMessage(hWnd, WM_SETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
SendMessage(hWnd, WM_SETICON, (IntPtr)ICON_BIG, IntPtr.Zero);

SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

...这也不起作用。这两个选项在整个网站的各种改编中都可以看到,但我似乎无法让它们中的任何一个工作,即使在 Visual Studio 之外也是如此。现在有一些仅适用于 Windows 10 的新方法吗?看来不起作用的部分是帧重绘。据我所知,它不会重绘任何东西。还有其他选择吗?感谢所有帮助。

c# wpf user-interface window interop
1个回答
0
投票

我通过使用 https://stackoverflow.com/a/2341385/410083 提供的代码来实现此功能,但将其转换为使用 64 位函数。我还必须使用

SendMessageW
消息添加对
WM_SETICON
的几次调用,以从窗口中删除大图标和小图标。

这是帮助程序类(我使用的是.NET 7,所以我将其更改为使用

LibraryImport
而不是
DllImport
):

public static partial class IconHelper
{
    [LibraryImport("user32.dll")]
    private static partial int GetWindowLongPtrW(IntPtr hWnd, int nIndex);

    [LibraryImport("user32.dll")]
    private static partial int SetWindowLongPtrW(IntPtr hWnd, int nIndex, int dwNewLong);

    [LibraryImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static partial bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

    [LibraryImport("user32.dll")]
    private static partial IntPtr SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    private const int GwlExStyle = -20;
    private const int WsExDlgModalFrame = 0x0001;
    private const int SwpNoSize = 0x0001;
    private const int SwpNoMove = 0x0002;
    private const int SwpNoZOrder = 0x0004;
    private const int SwpFrameChanged = 0x0020;
    private const uint WmSetIcon = 0x0080;

    public static void RemoveIcon(this Window window)
    {
        // Get this window's handle
        var hwnd = new WindowInteropHelper(window).Handle;
        // Change the extended window style to not show a window icon
        var extendedStyle = IconHelper.GetWindowLongPtrW(hwnd, IconHelper.GwlExStyle);
        _ = IconHelper.SetWindowLongPtrW(hwnd, IconHelper.GwlExStyle, extendedStyle | IconHelper.WsExDlgModalFrame);
        // Update the window's non-client area to reflect the changes
        _ = IconHelper.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0,
            IconHelper.SwpNoMove | IconHelper.SwpNoSize | IconHelper.SwpNoZOrder | IconHelper.SwpFrameChanged);
        // Send a couple messages to the window to remove the large and small icons
        _ = IconHelper.SendMessageW(hwnd, IconHelper.WmSetIcon, IntPtr.Zero, IntPtr.Zero);
        _ = IconHelper.SendMessageW(hwnd, IconHelper.WmSetIcon, 1, IntPtr.Zero);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.