【问题标题】:How to hide a WPF Window icon and use ResizeMode=NoResize?如何隐藏 WPF 窗口图标并使用 ResizeMode=NoResize?
【发布时间】:2017-03-03 18:30:53
【问题描述】:

我最近实现了来自this question 的解决方案来隐藏 WPF 窗口的图标。我发现当该解决方案与 ResizeMode=NoResize 结合使用时,应用程序的标题栏上下文菜单无法禁用 Min/Max/Resize 选项。

奇怪的是上下文菜单并没有错误地启用某些选项,它只是保留了图标隐藏之前的上下文菜单状态。我使用一个简单的测试应用程序发现了这一点,该应用程序可以进行必要的调用来隐藏图标,并且可以即时更新窗口的ResizeMode

图标显示,ResizeMode=CanResize

标题栏按钮和上下文菜单正确。

图标隐藏,ResizeMode=CanResize

还是正确的

图标隐藏,ResizeMode=NoResize

标题栏按钮已正确隐藏,但上下文菜单保留其先前状态。如果我切换到CanMinimize,然后切换到NoResize,上下文菜单只会启用“最小化”。

当一个可调整大小的 WPF 窗口启动另一个设置为 NoResize 的窗口时(并且您正在隐藏图标),这将成为一个问题。

问题

是否有其他 Windows API 函数可以强制上下文菜单重新评估其状态? NoResize 选项可能会导致这种奇怪的行为吗?由于这只影响 NoResize 选项,是否有 WPF 级别的解决方法?

编辑 - 我的目标是避免使用 WindowStyle=ToolWindowWS_EX_TOOLWINDOW 扩展窗口样式。过去我发现该窗口样式存在一些问题,其中一个是 on this question。我使用整个方法的一个目标是模拟ToolWindow 的外观,而无需实际使用它。

【问题讨论】:

  • 您采用了哪种解决方案? o-tool-kit 还是 Sheridan 的?
  • 一个组合。我做SetWindowLong...SendMessage...SendMessage...SetWindowPos。只使用其中一个似乎不起作用。

标签: c# wpf


【解决方案1】:

使用 .NET 4.0 和 Windows 8.1 Enterprise(我不知道它是否适用于其他 .NET 版本或不同的操作系统),您只需要使用 WS_EX_TOOLWINDOW 扩展样式而不是 WS_EX_DLGMODALFRAME 一个。

所以代码是:

public partial class MainWindow : Window
{
    [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);

    private const int GWL_EXSTYLE = -20;
    private const int WS_EX_DLGMODALFRAME = 0x0001;
    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_SETICON = 0x0080;
    private const int WS_EX_TOOLWINDOW = 0x00000080;

    public MainWindow()
    {
        InitializeComponent();
        ResizeMode = System.Windows.ResizeMode.NoResize;
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        IntPtr hwnd = new WindowInteropHelper(this).Handle;

        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
        SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TOOLWINDOW);

        SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero);
        SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);

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

希望对你有帮助。

【讨论】:

  • 我认为这是一个有效的答案,但我试图避免使用ToolWindow。如on this question 所述,ToolWindow 有一些不良副作用。我会相应地更新我的问题。
  • 如果你想使用SetWindowLong,恐怕没有别的办法@Michael。您是否考虑过创建一个空图标并将其用于您的窗口?
  • 这可能是我们暂时要走的路。当窗口设置为使用NoResize 时,只显示一个存根透明图标而不是隐藏它。不理想,但你可能是目前最好的。
猜你喜欢
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
相关资源
最近更新 更多