We have a .net 4.6.1 C# WPF app that takes up whole screen. We want to be able to turn on/off having a different smaller app's window on top of our main app (so they can chat to our support people). There are several third party tools that do it so I know it is possible:
http://www.makeuseof.com/tag/5-simple-ways-selected-windows-top-windows/
We have tried many things, I can get it to come to the front, but as soon as we touch our app (which takes up whole screen) the one we want to stay on top goes to the back... Saw a few solutions that would force the other app to stay on top, but it would freeze main app... but that is not ideal because we still want to be able to use our app while the other app is open on top of ours...
Any ideas? Thanks
public static void SearchForRunningProcessByWindow(string windowCaption, ShowWindowState windowState = ShowWindowState.SW_SHOWNORMAL)
{
IntPtr hWnd = FindWindowByCaption(0, windowCaption);
if (hWnd != IntPtr.Zero)
{
ShowWindow(hWnd, (int)ShowWindowState.SW_SHOWNORMAL);
SetForegroundWindow(hWnd);
// this is supposed to make it stay on top... ?
SetWindowPos(hWnd, new IntPtr(-1), 0, 0, 0, 0, 0x4000 | 0x0002 | 0x0001);
return true;
}
}
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
EDIT: did attempt a brute force way w/ timer but makes our main app unusable:
private static Timer _timer;
static void ForceOnTop(string windowCaption)
{
var timeout = 250;
_timer = new Timer(TimerCallback, new Tuple<long, string>(timeout, windowCaption), timeout, Timeout.Infinite);
}
private static void TimerCallback(object state)
{
var @tuple = (Tuple<long, string>) state;
SearchForRunningProcessByWindow(@tuple.Item2);
_timer.Change(@tuple.Item1, Timeout.Infinite);
}