我一直在使用Rainlendar,我注意到它可以选择将窗口"放在桌面上".它就像一个bottomMost窗口(与最顶层相对).
我怎么能在WPF应用程序上这样做?
谢谢
我的答案是Win32 API,不是特定于WPF(可能需要来自C#的P/Invoke):
Rainlendar有两种选择:
"在桌面上",它成为Explorer桌面窗口("程序管理器")的子项.您可以使用SetParent API 实现此目的.
"On Bottom"就是你所描述的 - 它的窗口停留在Z-order的底部,就在桌面前面.将它们放在那里很容易(参见SetWindowPos) - 诀窍是在点击时阻止它们到达前面.我建议处理WM_WINDOWPOSCHANGING消息.
这是我使用的,所以窗口总是"在底部":
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop;
...
[DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); const UInt32 SWP_NOSIZE = 0x0001; const UInt32 SWP_NOMOVE = 0x0002; const UInt32 SWP_NOACTIVATE = 0x0010; static readonly IntPtr HWND_BOTTOM = new IntPtr(1); public static void SetBottom(Window window) { IntPtr hWnd = new WindowInteropHelper(window).Handle; SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); }
警告接受的答案表明您调用SetParent来创建桌面的子项.如果你这样做,你会让Win32窗口管理器将桌面的输入队列同步到你的子窗口,这是一件坏事 - 雷蒙德陈解释了原因.基本上,如果您的窗口挂起或阻塞(例如使用MessageBox),您将锁定桌面.
我试图做同样的事情……我使用了很多想法,但是我能够做到这一点并防止闪烁。
我设法覆盖了WndProc,在将setwindowpos放在后台之前使用了一个setwindowpos,并使用了另一个setwindowpos来防止它获得焦点...
const UInt32 SWP_NOSIZE = 0x0001; const UInt32 SWP_NOMOVE = 0x0002; const UInt32 SWP_NOACTIVATE = 0x0010; const UInt32 SWP_NOZORDER = 0x0004; const int WM_ACTIVATEAPP = 0x001C; const int WM_ACTIVATE = 0x0006; const int WM_SETFOCUS = 0x0007; static readonly IntPtr HWND_BOTTOM = new IntPtr(1); const int WM_WINDOWPOSCHANGING = 0x0046; [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] static extern IntPtr DeferWindowPos(IntPtr hWinPosInfo, IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] static extern IntPtr BeginDeferWindowPos(int nNumWindows); [DllImport("user32.dll")] static extern bool EndDeferWindowPos(IntPtr hWinPosInfo); private void Window_Loaded(object sender, RoutedEventArgs e) { IntPtr hWnd = new WindowInteropHelper(this).Handle; SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); IntPtr windowHandle = (new WindowInteropHelper(this)).Handle; HwndSource src = HwndSource.FromHwnd(windowHandle); src.AddHook(new HwndSourceHook(WndProc)); } private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_SETFOCUS) { IntPtr hWnd = new WindowInteropHelper(this).Handle; SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); handled = true; } return IntPtr.Zero; } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { IntPtr windowHandle = (new WindowInteropHelper(this)).Handle; HwndSource src = HwndSource.FromHwnd(windowHandle); src.RemoveHook(new HwndSourceHook(this.WndProc)); }