当用户点击show desktop按钮时,如何防止WPF窗口最小化?
答案 0 :(得分:2)
此链接可以帮助您:Get the minimize box click of a WPF window
你需要抓住事件并自己处理。
编辑:一旦状态发生变化,此方法将提醒您,因此它可能不是“最佳”解决方案,但它可以正常工作。
答案 1 :(得分:1)
发布“显示桌面”时,Windows不会最小化。相反,“WorkerW”和“桌面”窗口被带到前台。
我最终开发了自己的解决方案。 我在互联网上搜索了几个星期,试图找到答案,所以我为这一点感到自豪。
所以我们要做的是使用pinvoke为EVENT_SYSTEM_FOREGROUND窗口事件创建一个钩子。 只要前景窗口发生变化,就会触发此事件。
现在我注意到当发出“Show Desktop”命令时,WorkerW窗口类变为前景。
请注意,此WorkerW窗口不是桌面,我确认此WorkerW窗口的hwnd不是Desktop hwnd。
所以我们所做的就是当WorkerW窗口成为前景时,我们将“WPF Gadget Window”设置为最顶层!
每当WorkerW窗口的其他窗口成为前景时,我们从“WPF Gadget Window”中删除最顶层的窗口。
如果你想更进一步,你可以取消注释我检查新前景窗口是否也是“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; }
}
}
答案 2 :(得分:-2)
您可以将窗口的父级更改为不受Show Desktop的影响。 (如此处所述: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);
}
}