【问题标题】:Removing Icon from a WPF window从 WPF 窗口中删除图标
【发布时间】:2011-01-21 10:11:21
【问题描述】:

我可以使用 WinApi 从 WPF 窗口中删除窗口图标,但是当我只运行 WPF 项目的可执行文件时,我会在应用程序窗口中再次获得该图标。

如何删除图标?

【问题讨论】:

  • WPF 窗口和应用程序窗口有什么区别。如果您想获得新问题的答案,请接受之前问题的答案。
  • 是的,请先接受之前问题的答案。
  • @LdnCobra,很好的答案,但你没有激励 shraddha 接受旧问题的答案:-)
  • 是的,我不知道如何接受...我无法找到接受答案的直接链接...而是我无法看到以前的答案...
  • 只需单击对您有帮助的答案上的复选框。

标签: wpf user-interface


【解决方案1】:

来自WPFTutorial

如何删除 WPF 窗口的图标

不幸的是,WPF 没有提供任何删除窗口图标的功能。一种解决方案可能是将图标设置为透明图标。但是这样窗口边框和标题之间的额外空间仍然存在。

更好的方法是使用 Win32 API 提供的函数来删除图标。

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        IconHelper.RemoveIcon(this);
    }
}

用于移除图标的辅助类。

public static class IconHelper
{
    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, 
        int x, int y, int width, int height, uint flags);

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hwnd, uint msg, 
        IntPtr wParam, IntPtr lParam);

    const int GWL_EXSTYLE = -20;
    const int WS_EX_DLGMODALFRAME = 0x0001;
    const int SWP_NOSIZE = 0x0001;
    const int SWP_NOMOVE = 0x0002;
    const int SWP_NOZORDER = 0x0004;
    const int SWP_FRAMECHANGED = 0x0020;
    const uint WM_SETICON = 0x0080;

    public static void RemoveIcon(Window window)
    {
        // Get this window's handle
        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);
    }
}

【讨论】:

  • 当我只使用 exe 运行项目时,我使用的相同代码不会从窗口中删除图标....其中 m 不使用 Visual Studio 运行项目
  • @LnDCobra:很好的答案,+1。请注意,您可以轻松地将其实现为附加属性,从而可以在 XAML 中以声明方式删除图标
  • itz 被删除我的问题是它为 exe 文件附加了所有新图标
  • @jmatthias 是的。解决方法是在底部添加这一行:SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);
  • 您可能希望添加SWP_NOACTIVATE(0x0010) 标志以防止窗口被SetWindowPos 函数激活。
【解决方案2】:

只需将此WindowStyle="ToolWindow" 添加到您的窗口属性中即可。

【讨论】:

  • 不错。但这也隐藏了最大化/最小化按钮
  • 哇,我从来不知道这么简单!但它在任务栏中会是什么样子?
  • 这项工作,但使窗口的关闭 X 变成红色!
【解决方案3】:

我已经修改了来自“LnDCobra”的样本,因此它可以用作附加属性(正如“Thomas”所建议的那样:

<Window 
        ...
        xmlns:i="clr-namespace:namespace-to-WindowEx"
        i:WindowEx.ShowIcon = "false"
        ...
>

WindowEx的实现:

public class WindowEx
  {
    private const int GwlExstyle = -20;
    private const int SwpFramechanged = 0x0020;
    private const int SwpNomove = 0x0002;
    private const int SwpNosize = 0x0001;
    private const int SwpNozorder = 0x0004;
    private const int WsExDlgmodalframe = 0x0001;

    public static readonly DependencyProperty ShowIconProperty =
      DependencyProperty.RegisterAttached(
        "ShowIcon",
        typeof (bool),
        typeof (WindowEx),
        new FrameworkPropertyMetadata(true, new PropertyChangedCallback((d, e) => RemoveIcon((Window) d))));


    public static Boolean GetShowIcon(UIElement element)
    {
      return (Boolean) element.GetValue(ShowIconProperty);
    }

    public static void RemoveIcon(Window window)
    {
      window.SourceInitialized += delegate {
        // Get this window's handle
        var hwnd = new WindowInteropHelper(window).Handle;

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

        // Update the window's non-client area to reflect the changes
        SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SwpNomove |
          SwpNosize | SwpNozorder | SwpFramechanged);
      };
    }

    public static void SetShowIcon(UIElement element, Boolean value)
    {
      element.SetValue(ShowIconProperty, value);
    }

    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hwnd, uint msg,
      IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    [DllImport("user32.dll")]
    private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
      int x, int y, int width, int height, uint flags);
  }
}

【讨论】:

  • 对我来说,这在调试模式下工作正常,但如果我在调试环境之外运行它就不行。
  • 接受的答案在 .NET4.5 中不起作用,而您的答案对我有用。谢谢!既可以在调试模式下在 Visual Studio 中工作,也可以通过 Windows 资源管理器运行 exe。
  • 当我将这个答案与这个答案结合起来时,这个答案在 .NET4.5 中对我有用:stackoverflow.com/questions/18580430/…。 XAML 设计人员还抱怨它不能将 WindowsInstance 转换为 Window,所以我不得不稍微重写它并删除直接转换为窗口:PropertyChangedCallback((d, e) =&gt; RemoveIcon((Window) d);
【解决方案4】:

这里有一个简单纯粹的 XAML 解决方案:

<Window x:Class="...">

    <Window.Icon>
        <DrawingImage />
    </Window.Icon>

    ...

</Window>

【讨论】:

  • 这应该是公认的答案。标题当然是由空图标推动的,但这是一个很小的代价。我只是讨厌为了删除图标而弄乱 Windows DLL!
  • 这似乎使任务栏图标空白
【解决方案5】:

我只是使用非常小的透明图像作为 WPF 窗口的图标(1x1 像素)。

【讨论】:

    【解决方案6】:

    创建一个透明的 1 x 1 图标并将其替换为标准图标

    Icon = BitmapSource.Create(1, 1, 0, 0, PixelFormats.Bgra32, null, new byte[4], 4);
    

    【讨论】:

    • 能否请您扩展您的答案?
    猜你喜欢
    • 2011-08-03
    • 2011-09-24
    • 2010-12-12
    • 2013-09-05
    • 2011-03-06
    • 2016-08-14
    • 2016-10-26
    • 1970-01-01
    • 2016-01-04
    相关资源
    最近更新 更多