WPF 在任务栏上最小化单击

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

我有一个 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() { }
    }
c# wpf winapi minimize
4个回答
18
投票

使用

ResizeMode="CanMinimize"
。这将使您最小化到任务栏。


3
投票

我过去曾使用此代码使用 WPF 来最小化/最大化 Windows

WindowStyle=None

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
投票

我刚刚意识到,如果 ResizeMode=NoResize 会发生这种情况,如果它等于 CanResize,则不要禁用操作系统功能以通过任务栏图标单击最小化。 我投票结束这个问题。


0
投票

如果您使用 WindowStyle="None",这是无需设置 ResizeMode 的正确解决方案。我花了很长时间才弄清楚。关键是了解 Windows 如何处理任务栏图标单击。它首先发送一个最小化事件,然后连续发送一个恢复事件,因此一旦窗口最小化,它就会在下一个事件中恢复。在我的解决方案中,我按调用最小化事件的日期时间过滤事件,因此它不会立即恢复。

注意:我没有使用 SC_MINIMIZE,因为如果 ResizeMode="None",它永远不会被调用,但 CS_DBLCLKS 是。

public const int SC_RESTORE = 0xF120;
public const int SC_MINIMIZE = 0xF020; // No effect if ResizeMode="None"
public const int WM_SYSCOMMAND = 0x0112;
public const int CS_DBLCLKS = 0x8;
private DateTime lastMinimized = DateTime.Now;

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // Works Perfectly without needing to set ResizeMode="CanResize" and thus,
    // doesn't show the resize grip border on the Window

    if (msg == WM_SYSCOMMAND && wParam.ToInt32() == SC_RESTORE && this.WindowState == WindowState.Minimized)
    {
        double elapsedTime = (DateTime.Now - lastMinimized).TotalSeconds;
        if (elapsedTime > 1.0D) // Adjust time to your liking
        {
            //Debug.WriteLine($"Restore.... Elapsed: {elapsedTime.ToString()}ms");
            this.WindowState = WindowState.Normal;
        }                
        handled = true;
    }
    else if (msg == CS_DBLCLKS && wParam.ToInt32() == 0 && this.WindowState == WindowState.Normal)
    {
        //Debug.WriteLine($"Minimized.... wParam: 0x{wParam.ToInt32().ToString("X")}");
        lastMinimized = DateTime.Now;
        this.WindowState = WindowState.Minimized;
        handled = true;
    }
    return IntPtr.Zero;
}
© www.soinside.com 2019 - 2024. All rights reserved.