解決されたようですが、閲覧者向けにまとめておきます。
まずProgram Managerの子ウィンドウにするような手法は、あまりよろしくないようです。
c# - Window "on desktop" - Stack Overflow
一応動きはしましたが、Vistaのような残念な見た目になってしまいましたw(何か手はあるのかもしれませんが深堀しません)
SetWindowPos
するのがいいようですが、タイミングによって効かなかったりチラついたりしました。
安定したのは参考リンクの一番下の(一番新しい)回答でした。
c# - Window "on desktop" - Stack Overflow
下記を使用しました(「プレリリースを含める」をチェックしないと出ないので注意)
NuGet Gallery | Microsoft.Windows.CsWin32 0.1.691-beta
xml
1<Window
2 x:Class="Q05wtn9uoflyayp.MainWindow"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 Width="800"
6 Height="450"
7 Closing="Window_Closing"
8 SourceInitialized="Window_SourceInitialized">
9 <Window.Resources>
10 <Style BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type RadioButton}">
11 <Setter Property="Margin" Value="10" />
12 </Style>
13 </Window.Resources>
14 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
15 <RadioButton Content="None" />
16 <RadioButton
17 Checked="SetParent_Checked"
18 Content="SetParent"
19 Unchecked="SetParent_Unchecked" />
20 <RadioButton
21 x:Name="SetWindowPos_RadioButton"
22 Content="SetWindowPos"
23 IsChecked="True" />
24 </StackPanel>
25</Window>
cs
1using System;
2using System.Runtime.InteropServices;
3using System.Windows;
4using System.Windows.Interop;
5using Windows.Win32.Foundation;
6using Windows.Win32.UI.WindowsAndMessaging;
7using static Windows.Win32.PInvoke;
8using static Windows.Win32.UI.WindowsAndMessaging.SET_WINDOW_POS_FLAGS;
9
10namespace Q05wtn9uoflyayp
11{
12 public partial class MainWindow : Window
13 {
14 public MainWindow() => InitializeComponent();
15
16 private void Window_SourceInitialized(object sender, EventArgs e)
17 {
18 var hWnd = new WindowInteropHelper(this).Handle;
19 SetWindowPos((HWND)hWnd, HWND.HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
20 HwndSource.FromHwnd(hWnd).AddHook(new HwndSourceHook(WndProc));
21 }
22
23 private void SetParent_Checked(object sender, RoutedEventArgs e)
24 {
25 var hWnd = new WindowInteropHelper(this).Handle;
26 var hWndProgMan = FindWindow("Progman", "Program Manager");
27 SetParent((HWND)hWnd, hWndProgMan);
28 }
29 private void SetParent_Unchecked(object sender, RoutedEventArgs e)
30 {
31 var hWnd = new WindowInteropHelper(this).Handle;
32 SetParent((HWND)hWnd, (HWND)IntPtr.Zero);
33 }
34
35 private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
36 {
37 if (SetWindowPos_RadioButton.IsChecked != true) return IntPtr.Zero;
38
39 if (msg == WM_WINDOWPOSCHANGING)
40 {
41 var windowPos = Marshal.PtrToStructure<WINDOWPOS>(lParam);
42 windowPos.flags |= SWP_NOZORDER;
43 // こうするほうがいいような気もするけど、同じことしているウィンドウがあると取り合いになるか?
44 //windowPos.hwndInsertAfter = HWND.HWND_BOTTOM;
45 Marshal.StructureToPtr(windowPos, lParam, false);
46 }
47
48 return IntPtr.Zero;
49 }
50
51 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
52 {
53 var hWnd = new WindowInteropHelper(this).Handle;
54 HwndSource.FromHwnd(hWnd).RemoveHook(new HwndSourceHook(WndProc));
55 }
56 }
57}
txt:NativeMethods.txt
1FindWindow
2SetParent
3SetWindowPos
4WINDOWPOS
5SWP_NOSIZE
6SWP_NOMOVE
7SWP_NOACTIVATE
8SWP_NOZORDER
9HWND_BOTTOM
10WM_WINDOWPOSCHANGING