【问题标题】:How to prevent a window from minimizing?如何防止窗口最小化?
【发布时间】:2011-09-14 19:39:53
【问题描述】:

当用户点击显示桌面按钮时,如何防止 WPF 窗口最小化?

【问题讨论】:

  • 为什么要阻止用户看到他们的桌面?
  • 我正在开发一个桌面日历,所以它就像窗口的背景
  • Window "on desktop"的可能重复
  • 也许可以成为侧边栏/小工具应用程序的候选人?拒绝让路的标准窗口本质上会破坏用户的计算机。如果他们需要访问桌面图标怎么办?
  • 我得到了 2 个答案! 1-你没有。 2-你关闭它,它不会最小化!

标签: c# wpf minimize


【解决方案1】:

此链接将对您有所帮助:Get the minimize box click of a WPF window

你需要自己捕捉事件并处理它。

编辑:一旦状态改变,此方法会提醒您,因此它可能不是“最佳”解决方案,但它可以工作。

【讨论】:

  • 我尝试使用计时器来获取状态,但它可以工作,但它认为这不是一个好主意。
【解决方案2】:

发出“显示桌面”时,Windows 不会最小化。而是将“WorkerW”和“Desktop”窗口置于前台。

我最终开发了自己的解决方案。 我在互联网上搜索了数周试图找到答案,所以我为这个感到自豪。

所以我们要做的是使用 pinvoke 为 EVENT_SYSTEM_FOREGROUND 窗口事件创建一个钩子。 每当前台窗口发生变化时都会触发此事件。

现在我注意到当“显示桌面”命令发出时,WorkerW 窗口类变成了前台。

注意这个 WorkerW 窗口不是桌面,我确认这个 WorkerW 窗口的 hwnd 不是桌面 hwnd。

所以我们所做的就是每当 WorkerW 窗口成为前台时,我们将“WPF Gadget Window”设置为最顶层!

当 WorkerW 窗口以外的窗口成为前景时,我们会从“WPF 小工具窗口”中移除最顶层。

如果你想更进一步,你可以取消注释我检查新前景窗口是否也是“PROGMAN”的部分,即桌面窗口。

但是,如果用户在不同的显示器上单击其桌面,这将导致您的窗口变为最顶部。就我而言,我不希望这种行为,但我想你们中的一些人可能会。

确认可以在 Windows 10 中运行。应该可以在旧版本的 Windows 中运行。

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;

namespace YourNamespace
{
    internal static class NativeMethods
    {
        [DllImport("user32.dll")]
        internal static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, ShowDesktop.WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        [DllImport("user32.dll")]
        internal static extern bool UnhookWinEvent(IntPtr hWinEventHook);

        [DllImport("user32.dll")]
        internal static extern int GetClassName(IntPtr hwnd, StringBuilder name, int count);
    }

    public static class ShowDesktop
    {
        private const uint WINEVENT_OUTOFCONTEXT = 0u;
        private const uint EVENT_SYSTEM_FOREGROUND = 3u;

        private const string WORKERW = "WorkerW";
        private const string PROGMAN = "Progman";

        public static void AddHook(Window window)
        {
            if (IsHooked)
            {
                return;
            }

            IsHooked = true;

            _delegate = new WinEventDelegate(WinEventHook);
            _hookIntPtr = NativeMethods.SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _delegate, 0, 0, WINEVENT_OUTOFCONTEXT);
            _window = window;
        }

        public static void RemoveHook()
        {
            if (!IsHooked)
            {
                return;
            }

            IsHooked = false;

            NativeMethods.UnhookWinEvent(_hookIntPtr.Value);

            _delegate = null;
            _hookIntPtr = null;
            _window = null;
        }

        private static string GetWindowClass(IntPtr hwnd)
        {
            StringBuilder _sb = new StringBuilder(32);
            NativeMethods.GetClassName(hwnd, _sb, _sb.Capacity);
            return _sb.ToString();
        }

        internal delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        private static void WinEventHook(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            if (eventType == EVENT_SYSTEM_FOREGROUND)
            {
                string _class = GetWindowClass(hwnd);

                if (string.Equals(_class, WORKERW, StringComparison.Ordinal) /*|| string.Equals(_class, PROGMAN, StringComparison.Ordinal)*/ )
                {
                    _window.Topmost = true;
                }
                else
                {
                    _window.Topmost = false;
                }
            }
        }

        public static bool IsHooked { get; private set; } = false;

        private static IntPtr? _hookIntPtr { get; set; }

        private static WinEventDelegate _delegate { get; set; }

        private static Window _window { get; set; }
    }
}

【讨论】:

    【解决方案3】:

    您可以将窗口的父级更改为不受“显示桌面”的影响。 (如此处所述:Window "on desktop"

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindowLoaded;
        }
    
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
        private void MainWindowLoaded(object sender, RoutedEventArgs e)
        {
            var hwnd = new WindowInteropHelper(this).Handle;
            var ProgmanHwnd = FindWindowEx(FindWindowEx(FindWindow("Progman", "Program Manager"), IntPtr.Zero, "SHELLDLL_DefView",""), IntPtr.Zero,"SysListView32", "FolderView");
            SetParent(hwnd, ProgmanHwnd);
        }
    
    }
    

    【讨论】:

    • 不正确。从任务栏中使用“显示桌面”将覆盖任何非焦点应用程序使窗口可见的尝试。这是设计使然。
    猜你喜欢
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多