【问题标题】:Is it possible to display a wpf window without an icon in the title bar?是否可以在标题栏中显示没有图标的 wpf 窗口?
【发布时间】:2010-12-05 22:32:34
【问题描述】:

众所周知,如果 wpf 窗口的图标未定义,则显示默认图标。我想在标题栏中显示一个没有任何图标的窗口。我意识到我可以使用空白图像,但这会导致标题栏中的文本向右偏移。

有谁知道完全删除图标的方法吗?

(我尝试搜索类似的问题,但找不到任何内容。)

【问题讨论】:

    标签: wpf xaml dialog titlebar application-icon


    【解决方案1】:

    简单,将此代码添加到您的窗口中:

    [DllImport("user32.dll")]
    static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
    
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    
    private const int GWL_STYLE = -16;
    
    private const uint WS_SYSMENU = 0x80000;
    
    protected override void OnSourceInitialized(EventArgs e)
    {
        IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
        SetWindowLong(hwnd, GWL_STYLE,
            GetWindowLong(hwnd, GWL_STYLE) & (0xFFFFFFFF ^ WS_SYSMENU));
    
        base.OnSourceInitialized(e);
    }
    

    【讨论】:

    • 必须根据“如何在 wpf 窗口中隐藏关闭按钮?”中的代码进行一些修改,但这确实有效!
    • 这似乎也摆脱了并非总是需要的“关闭”按钮。
    • @MichaelArnell 你是怎么把关闭按钮放回去的?
    • @Frustrated 我不需要关闭按钮,所以不用担心。您必须查看 SetWindowLong 的 Win32 API 文档(请参阅msdn.microsoft.com/en-gb/library/windows/desktop/…)以确定您需要哪些值用于 GWL_STYLE(请参阅msdn.microsoft.com/en-gb/library/windows/desktop/…)。
    • 但这对我不起作用..还有什么我需要做的吗? @尼尔
    【解决方案2】:

    虽然不是完全正确的解决方案,但您可以尝试以下方法之一:

    1. 将 WindowStyle-Property 设置为 ToolWindow 会使图标消失,但标题栏(显然)会变小。

    2. 为整个窗口编写一个 ControlTemplate。根据窗口是否必须看起来像“真实”窗口,尝试在模板中重新创建默认样式会付出很多努力。

    【讨论】:

    • 我认为表达式套件的 WPF 部分可能会自己绘制所有内容(包括标题栏)以允许此类事情。尽管如此,对于用户来说,原生的外观和行为是一件非常好的事情,恕我直言。
    • +1 “ToolWindow” WindowStyle 正是我想要的!
    【解决方案3】:

    我知道这已得到解答,但是 Dan Rigsby's blog 有一篇文章展示了如何在不隐藏最小化/最大化框的情况下做到这一点。

    我发现这让我很沮丧,因为我正在使用文章(herehere,但是当隐藏 sysmenu 时它一直隐藏所有按钮,以帮助我创建了这个助手,如上所示,在 @987654324 中调用@。

    public static class WpfWindowHelper {
    
        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hwnd, int index);
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
    
        public const int GWL_EXSTYLE = -20;
        public const int WS_EX_DLGMODALFRAME = 0x0001;
        public const int SWP_NOSIZE = 0x0001;
        public const int SWP_NOMOVE = 0x0002;
        public const int SWP_NOZORDER = 0x0004;
        public const int SWP_FRAMECHANGED = 0x0020;
        public const int GWL_STYLE = -16;
        public const int WS_MAXIMIZEBOX = 0x00010000;
        public const int WS_MINIMIZEBOX = 0x00020000;
        public const int WS_SYSMENU = 0x00080000;
    
        public static void HideSysMenu(this Window w) {
            IntPtr hwnd = new WindowInteropHelper(w).Handle;
            int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
            SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
            SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
        }
    
        public static void HideMinimizeBox(this Window w) {
            IntPtr hwnd = new WindowInteropHelper(w).Handle;
            SetWindowLong(hwnd, GWL_STYLE,
                GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MINIMIZEBOX));
        }
    
        public static void HideMaximizeBox(this Window w) {
            IntPtr hwnd = new WindowInteropHelper(w).Handle;
            SetWindowLong(hwnd, GWL_STYLE,
                GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MAXIMIZEBOX));
        }
    
        public static void HideMinimizeAndMaximizeBoxes(this Window w) {
            IntPtr hwnd = new WindowInteropHelper(w).Handle;
            SetWindowLong(hwnd, GWL_STYLE,
                GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
        }
    
    }
    

    【讨论】:

    • HideSysMenu (WS_EX_DLGMODALFRAME) 做的事情!隐藏图标,但保持关闭按钮不变。
    • 对不起,它没有任何作用。图标和关闭按钮仍然存在。根据 Microsoft 自己的对话窗口 UI 指南,我只想让图标消失。
    • 它不起作用,因为您缺少两个语句(需要您的代码加上以下内容): SendMessage(hwnd, WM_SETICON, ICON_SMALL, IntPtr.Zero); SendMessage(hwnd, WM_SETICON, ICON_BIG, IntPtr.Zero);
    【解决方案4】:

    不,这似乎是不可能的。引用Icon property 的文档(强调我的):

    一个WPF窗口总是显示一个图标。当没有通过设置Icon提供时,WPF根据以下规则选择一个图标显示:

    1. 如果指定,请使用程序集图标。
    2. 如果未指定程序集图标,请使用默认的 Microsoft Windows 图标。

    如果使用 Icon 指定自定义窗口图标,可以通过将 Icon 设置为 null 来恢复默认应用程序图标。

    因此,显然完全透明的图标似乎是您最好的选择。或者也许通过使用 Windows API 函数在窗口上设置适当的样式来解决所有这些问题。但这可能会干扰 WPF 的窗口管理。

    【讨论】:

      【解决方案5】:

      您可以使用一个空的 png 图片并将其转换为图标并将其设置为您的窗口的图标!!!

      【讨论】:

      • 这是最简单最好的解决方案。 +1
      • 图片仍然占用窗口标题空间
      • 如果您的窗口有标题,您就会明白为什么这不是一个好的解决方案。
      【解决方案6】:

      将以下代码添加到Window 的主类中,以删除最大化和最小化按钮,并隐藏图标。

      private const uint WS_MINIMIZEBOX = 0x00020000;
      private const uint WS_MAXIMIZEBOX = 0x00010000;
      private const int GWL_STYLE = -16;
      private const int GWL_EXSTYLE = -20;
      private const int SWP_NOSIZE = 0x0001;
      private const int SWP_NOMOVE = 0x0002;
      private const int SWP_NOZORDER = 0x0004;
      private const int SWP_FRAMECHANGED = 0x0020;
      private const int WM_SYSCOMMAND = 0x0112;
      private const int WM_SETICON = 0x0080;
      private const int WS_EX_DLGMODALFRAME = 0x0001;
      
      [DllImport("user32.dll")]
      public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
      
      [DllImport("user32.dll")]
      private static extern uint GetWindowLong(IntPtr hwnd, int index);
      
      [DllImport("user32.dll")]
      private static extern int SetWindowLong(IntPtr hwnd, int index, uint newStyle);
      
      [DllImport("user32.dll")]
      private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
      
      protected override void OnSourceInitialized(EventArgs e)
      {
          base.OnSourceInitialized(e);
          
          IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
          uint styles = GetWindowLong(hwnd, GWL_STYLE);
      
          // Remove the maximize and minimize buttons
          styles &= 0xFFFFFFFF ^ (WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
          SetWindowLong(hwnd, GWL_STYLE, styles);
          
          // Change to dialog modal - necessary for the final step to work!
          styles = GetWindowLong(hwnd, GWL_EXSTYLE);
          styles |= WS_EX_DLGMODALFRAME;
          SetWindowLong(hwnd, GWL_EXSTYLE, styles);
      
          SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
          ((HwndSource)PresentationSource.FromVisual(this)).AddHook(HelpButtonHook);
      
          // Remove the icon
          SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero);
          SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);
      }
      

      【讨论】:

        【解决方案7】:

        我的第一个建议是不要这样做。在 WinForms 中,您可以使用 formborderstyles 类型来创建一个没有图标的对话框,但这仅仅是因为这是 Windows 标准。只有具有这些特定边框类型的表单才应该没有图标;这是用户的期望。

        【讨论】:

        • Windows 窗体也有一个ShowIcon 属性。
        • 不幸的是,WPF 中的窗口和对话框之间似乎没有真正的区别。
        • design guidelines for Windows error dialogs 另有说明:“模态错误消息对话框没有标题栏图标
        猜你喜欢
        • 2012-10-20
        • 2019-08-30
        • 2020-01-09
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        • 2013-03-04
        • 2011-07-03
        • 2015-09-30
        相关资源
        最近更新 更多