I'd want to make an extra panel of options for another application.
I succeeded making my window borderless and placing it constantly on top of the other window, but there's a few problems in this method: 1) it looks out of place 2) it covers some of "host" applications ui.
Better way seems to be making the other window take place in my window as a child. To my surprise, it worked like charm on Win 7! But on windows 10 there seems to be 2 problems: 1) the other window doesn't go borderless 2) parenting doesn't work.
Parenting isn't absolutely necessary as I can just place the other window on my window, but it simply works better when embedded window is a child (having it move perfectly with main window and no z-order trickery needed). The main problem here is those borders... but if setting parent is possible on Win 10 it's a great bonus :)
So I need help either getting this thing fixed or another perspective how to accomplish original goal...
What I have tried:
This example program launches notepad and embeds it on top of
childPlaceholder
control. On window resize the child window is adjusted accordingly.
Here's the code which works on Windows 7:
WPF XAML:
<Window x:Class="EmbedWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Embedded window example" Height="350" Width="525" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
<DockPanel>
<Grid Name="myContent" DockPanel.Dock="Right">
<TextBlock Margin="10">Some extra content here...</TextBlock>
</Grid>
<Border Name="childPlaceholder" BorderBrush="DarkGray" BorderThickness="2" >
<TextBlock Margin="10">Here should be the embedded window...</TextBlock>
</Border>
</DockPanel>
</Window>
Code behind (C#):
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
namespace EmbedWindow
{
public partial class MainWindow : Window
{
IntPtr otherWindow = IntPtr.Zero, thisWindow = IntPtr.Zero;
public MainWindow()
{
InitializeComponent();
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
thisWindow = new WindowInteropHelper(this).Handle;
Process proc = new Process();
proc.StartInfo = new ProcessStartInfo("Notepad.exe");
proc.Start();
await Task.Delay(500);
otherWindow = proc.MainWindowHandle;
WinHelper.SetWindowLong(otherWindow, WinHelper.GWL_STYLE, WinHelper.winStyle.WS_VISIBLE);
WinHelper.SetParent(otherWindow, thisWindow);
ArrangeWindows();
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
ArrangeWindows();
}
private void ArrangeWindows()
{
Point topLeft = childPlaceholder.TransformToAncestor(this).Transform(new Point(0, 0));
Point bottomRight = childPlaceholder.TransformToAncestor(this).Transform(new Point(childPlaceholder.ActualWidth, childPlaceholder.ActualHeight));
WinHelper.MoveWindow(otherWindow, (int)topLeft.X, (int)topLeft.Y, (int)bottomRight.X - (int)topLeft.X, (int)bottomRight.Y - (int)topLeft.Y, true);
}
static class WinHelper
{
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, winStyle dwNewLong);
public static int GWL_STYLE = -16;
[Flags]
public enum winStyle : int
{
WS_VISIBLE = 0x10000000,
WS_CHILD = 0x40000000,
WS_BORDER = 0x00800000,
WS_DLGFRAME = 0x00400000,
WS_CAPTION = WS_BORDER | WS_DLGFRAME
}
}
}
}