窗口“在桌面上”

我一直在使用Rainlendar一段时间,我注意到它有一个选项,把窗口“在桌面上”。 这就像一个bottomMost窗口(顶层)。

我怎么能在WPF应用程序上做到这一点?

谢谢

我的答案是在Win32 API,而不是特定于WPF(可能需要从C#中的P / Invoke):

Rainlendar有两个选项:

  • “在桌面上”,它成为资源pipe理器桌面窗口(“程序pipe理器”)的子项。 你可以通过SetParent API来实现。
  • “底部”就是你所描述的 – 它的窗户停留在Z-order的底部,就在桌面前面。 很容易把它们放在那里(参见SetWindowPos ) – 诀窍是阻止它们在点击时到达前面。 我会build议处理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); } 

警告接受的答案build议您调用SetParent创build桌面的子项。 如果你这样做,你会导致Win32窗口pipe理器将桌面的input队列同步到你的子窗口,这是一件坏事 – Raymond Chen解释了为什么。 基本上,如果你的窗口挂起或阻塞(用MessageBox说)你会locking你的桌面。

Im使用的OnDesktop版本:

 [DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); public static void SetOnDesktop(Window window) { IntPtr hWnd = new WindowInteropHelper(window).Handle; IntPtr hWndProgMan = FindWindow("Progman", "Program Manager"); SetParent(hWnd, hWndProgMan); } 

我在寻找程序pipe理器窗口时遇到了一些麻烦,但是Rainlendar的创build者Kimmo给了我一个代码的链接:

http://www.ipi.fi/~rainy/legacy.html

如果有人需要更多的细节,只需在library / rainwindow.cpp中查看SetWindowZPos函数。

我正在尝试做同样的事情…我已经使用了很多想法,但我能够做到这一点,并防止闪烁。

我设法覆盖WndProc,使用一个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)); } 

@HrejWaltz的附加属性版本的答案是:

更新(12/28/2016)

 public class WindowSinker { #region Properties 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; const int WM_WINDOWPOSCHANGING = 0x0046; static readonly IntPtr HWND_BOTTOM = new IntPtr(1); Window Window = null; #endregion #region WindowSinker public WindowSinker(Window Window) { this.Window = Window; } #endregion #region Methods [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); void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) { var Handle = (new WindowInteropHelper(Window)).Handle; var Source = HwndSource.FromHwnd(Handle); Source.RemoveHook(new HwndSourceHook(WndProc)); } void OnLoaded(object sender, RoutedEventArgs e) { var Hwnd = new WindowInteropHelper(Window).Handle; SetWindowPos(Hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); var Handle = (new WindowInteropHelper(Window)).Handle; var Source = HwndSource.FromHwnd(Handle); Source.AddHook(new HwndSourceHook(WndProc)); } IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_SETFOCUS) { hWnd = new WindowInteropHelper(Window).Handle; SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); handled = true; } return IntPtr.Zero; } public void Sink() { Window.Loaded += OnLoaded; Window.Closing += OnClosing; } public void Unsink() { Window.Loaded -= OnLoaded; Window.Closing -= OnClosing; } #endregion } public static class WindowExtensions { #region Always On Bottom public static readonly DependencyProperty SinkerProperty = DependencyProperty.RegisterAttached("Sinker", typeof(WindowSinker), typeof(WindowExtensions), new UIPropertyMetadata(null)); public static WindowSinker GetSinker(DependencyObject obj) { return (WindowSinker)obj.GetValue(SinkerProperty); } public static void SetSinker(DependencyObject obj, WindowSinker value) { obj.SetValue(SinkerProperty, value); } public static readonly DependencyProperty AlwaysOnBottomProperty = DependencyProperty.RegisterAttached("AlwaysOnBottom", typeof(bool), typeof(WindowExtensions), new UIPropertyMetadata(false, OnAlwaysOnBottomChanged)); public static bool GetAlwaysOnBottom(DependencyObject obj) { return (bool)obj.GetValue(AlwaysOnBottomProperty); } public static void SetAlwaysOnBottom(DependencyObject obj, bool value) { obj.SetValue(AlwaysOnBottomProperty, value); } static void OnAlwaysOnBottomChanged(object sender, DependencyPropertyChangedEventArgs e) { var Window = sender as Window; if (Window != null) { if ((bool)e.NewValue) { var Sinker = new WindowSinker(Window); Sinker.Sink(); SetSinker(Window, Sinker); } else { var Sinker = GetSinker(Window); Sinker.Unsink(); SetSinker(Window, null); } } } #endregion }