WPF单击任务栏最小化

10

我有一个WPF应用程序,按照利益相关者的要求,必须具有WindowStyle="None"、ResizeMode="NoResize"和AllowTransparency="True"。我知道通过不使用Windows chrome,您必须重新实现许多操作系统窗口处理功能。我已经能够创建一个工作的自定义最小化按钮,但是我无法重新实现Windows在单击屏幕底部的任务栏图标时最小化应用程序的功能。

用户要求应用程序在单击任务栏图标时最小化,并在再次单击时恢复。后者从未停止工作,但我无法实现前者。这里是我正在使用的代码:

    public ShellView(ShellViewModel viewModel)
    {
        InitializeComponent();

        // Set the ViewModel as this View's data context.
        this.DataContext = viewModel;

        this.Loaded += new RoutedEventHandler(ShellView_Loaded);
    }

    private void ShellView_Loaded(object sender, RoutedEventArgs e)
    {
        var m_hWnd = new WindowInteropHelper(this).Handle;
        HwndSource.FromHwnd(m_hWnd).AddHook(WindowProc);
    }

    private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == NativeMethods.CS_DBLCLKS)
        {
            this.WindowState = WindowState.Minimized;
            // handled = true
        }

        return IntPtr.Zero;
    }

    /// <summary>
    /// http://msdn.microsoft.com/en-us/library/ms646360(v=vs.85).aspx
    /// </summary>
    internal class NativeMethods
    {
        public const int SC_RESTORE = 0xF120;
        public const int SC_MINIMIZE = 0xF020;
        public const int SC_CLOSE = 0xF060;
        public const int WM_SYSCOMMAND = 0x0112;
        public const int WS_SYSMENU = 0x80000;
        public const int WS_MINIMIZEBOX = 0x20000;
        public const int CS_DBLCLKS = 0x8;
        NativeMethods() { }
    }

我差点忘了,在发帖之前我已经搜索了StackOverflow,但是没有找到适用于WPF的可接受解决方案。我看到了WinForms的解决方案。 - sidney.andrews
你不应该使用本地方法来最小化和从任务栏还原。我的几乎所有应用程序都是这样运行的,我没有遇到过这种情况... WindowState = WindowState.Minimized 不起作用吗? - FlyingStreudel
@FlyingStreudel 问题在于没有一种受控的方法来检测用户何时单击任务栏。在所有其他情况下,我可以很好地最小化和最大化,但我没有办法让应用程序响应其任务栏图标的单击事件。要求在单击任务栏按钮时最小化。 - sidney.andrews
我想我有点困惑,即使设置了WindowStyle=None和AllowsTransparency=True,窗口仍应该响应任务栏上的点击。还有其他什么原因导致它不能响应吗? - FlyingStreudel
@FlyingStreudel 这个链接是关于WinForms的,但同样的道理也适用于WPF。https://dev59.com/TFTTa4cB1Zd3GeqPwdwQ我刚刚打开了Expression Blend,并创建了一个没有任何更改的新应用程序,只有WindowStyle="None",AllowsTransparency="True"。如果ResizeMode="NoResize",它不起作用,但如果我不改变ResizeMode,它突然之间就可以工作了。非常奇怪。 - sidney.andrews
显示剩余2条评论
3个回答

17

使用ResizeMode="CanMinimize"。这样可以允许您最小化到任务栏。


非常感谢,浪费了很多时间,我会处理这个问题。在我的代码中,调整大小模式没有重新调整大小。 - Rakibul

3

我曾经使用过这段代码,通过WPF的WindowStyle=None最小化/最大化Windows。

private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Minimized;
}

private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
    AdjustWindowSize();
}

private void AdjustWindowSize()
{
    if (this.WindowState == WindowState.Maximized)
    {
        this.WindowState = WindowState.Normal;
    }
    else
    {
        this.WindowState = WindowState.Maximized;
    }
}

private void FakeTitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ChangedButton == MouseButton.Left)
    {
        if (e.ClickCount == 2)
        {
            AdjustWindowSize();
        }
        else
        {
            Application.Current.MainWindow.DragMove();
        }
    }
 }

1
不幸的是,这无法处理任务栏图标被左键单击的情况。 - sidney.andrews
@masenkablast - 抱歉,刚刚注意到您提到的是任务栏行为,而不是托盘图标行为。任务栏行为不是属于应用程序的一部分吗?它不是属于 Windows 的一部分吗? - Rachel
然而,如果您在问题中设置了这三个属性,则会禁用Windows行为。 - sidney.andrews

1
我刚刚意识到,如果ResizeMode=NoResize,那么会发生这种情况,如果它等于CanResize,那么您不会禁用通过任务栏图标单击最小化的操作系统功能。我投票关闭此问题。

一个替代禁用调整大小的方法是将窗口的 MinHeight/MaxHeightMinWidth/MaxWidth 设置为相同。 - Rachel
@Joel B Fant,这对我来说似乎有些不可靠。 - sidney.andrews
@Rachel 听起来是个好主意。禁用调整大小的主要原因是,如果您有一个无边框窗口并最大化窗口,如果启用了调整大小,则操作系统会在您的窗口上裁剪像素,而它期望的是一个调整大小的手柄。 - sidney.andrews
2
这是非常正常的,因为这样做的目的是如果其他人遇到类似的问题并找到了你的提问,他们也能找到解决方案。 - Joel B Fant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接