# HG changeset patch
# User StephaneLenclud
# Date 1426711626 -3600
# Node ID 9d5867ce966a54ca19ea40ba503fb1e2f57a17fa
# Parent 2e0571e50ab3a7b49a98f43723394358637f8cfb
Looks like we have a solution for our bring to foreground problem.
diff -r 2e0571e50ab3 -r 9d5867ce966a Server/MainForm.Hid.cs
--- a/Server/MainForm.Hid.cs Wed Mar 18 20:38:59 2015 +0100
+++ b/Server/MainForm.Hid.cs Wed Mar 18 21:47:06 2015 +0100
@@ -14,22 +14,26 @@
namespace SharpDisplayManager
{
[System.ComponentModel.DesignerCategory("Code")]
- public class MainFormHid: Form
+ public class MainFormHid : Form
{
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("USER32.DLL")]
- public static extern bool BringWindowToTop(IntPtr hWnd);
+ public static extern IntPtr GetForegroundWindow();
- [DllImport("USER32.DLL")]
- public static extern bool IsIconic(IntPtr hWnd);
+ [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
+ public static extern uint GetWindowThreadProcessId([System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, System.IntPtr lpdwProcessId);
- [DllImport("USER32.DLL")]
- public static extern bool OpenIcon(IntPtr hWnd);
+ [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "GetCurrentThreadId")]
+ public static extern uint GetCurrentThreadId();
+ [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "AttachThreadInput")]
+ [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
+ public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fAttach);
+ //
public delegate void OnHidEventDelegate(object aSender, Hid.Event aHidEvent);
///
@@ -37,6 +41,9 @@
///
private Hid.Handler iHidHandler;
+ ///
+ /// Register HID devices so that we receive corresponding WM_INPUT messages.
+ ///
protected void RegisterHidDevices()
{
// Register the input device to receive the commands from the
@@ -96,6 +103,11 @@
iHidHandler.OnHidEvent += HandleHidEventThreadSafe;
}
+ ///
+ /// Here we receive HID events from our HID library.
+ ///
+ ///
+ ///
public void HandleHidEventThreadSafe(object aSender, SharpLib.Hid.Event aHidEvent)
{
if (aHidEvent.IsStray)
@@ -116,14 +128,13 @@
if (aHidEvent.Usages.Count > 0
&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl
&& aHidEvent.Usages[0] == (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart)
- //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer
- //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
-
+ //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer
+ //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
{
//First check if the process we want to launch already exists
string procName = Path.GetFileNameWithoutExtension(Properties.Settings.Default.StartFileName);
Process[] existingProcesses = Process.GetProcessesByName(procName);
- if (existingProcesses == null || existingProcesses.Length==0)
+ if (existingProcesses == null || existingProcesses.Length == 0)
{
// Process do not exists just try to launch it
ProcessStartInfo start = new ProcessStartInfo();
@@ -136,27 +147,68 @@
start.UseShellExecute = true;
// Run the external process & wait for it to finish
Process proc = Process.Start(start);
-
+
//SL: We could have used that too
//Shell32.Shell shell = new Shell32.Shell();
//shell.ShellExecute(Properties.Settings.Default.StartFileName);
}
else
{
- BringWindowToTop(existingProcesses[0].MainWindowHandle);
- SetForegroundWindow(existingProcesses[0].MainWindowHandle);
- if (IsIconic(existingProcesses[0].MainWindowHandle))
- {
- OpenIcon(existingProcesses[0].MainWindowHandle);
- }
- BringWindowToTop(existingProcesses[0].MainWindowHandle);
- SetForegroundWindow(existingProcesses[0].MainWindowHandle);
- }
+ ForceForegroundWindow(existingProcesses[0].MainWindowHandle);
+ }
}
}
}
-
+
+ ///
+ /// For the Window with the given handle to the foreground no matter what.
+ /// That works around flashing Window issues.
+ /// As seen on http://www.asyncop.com/MTnPDirEnum.aspx?treeviewPath=[o]+Open-Source\WinModules\Infrastructure\SystemAPI.cpp
+ ///
+ ///
+ ///
+ IntPtr ForceForegroundWindow(IntPtr hTo)
+ {
+ if (hTo == IntPtr.Zero)
+ {
+ return IntPtr.Zero;
+ }
+ IntPtr hFrom = GetForegroundWindow();
+
+ if (hFrom != IntPtr.Zero)
+ {
+ SetForegroundWindow(hTo);
+ return IntPtr.Zero;
+ }
+ if (hTo == hFrom)
+ {
+ return IntPtr.Zero;
+ }
+
+ uint pid = GetWindowThreadProcessId(hFrom, IntPtr.Zero);
+ uint tid = GetCurrentThreadId();
+ if (tid == pid)
+ {
+ SetForegroundWindow(hTo);
+ return (hFrom);
+ }
+ if (pid != 0)
+ {
+ if (!AttachThreadInput(tid, pid, true))
+ {
+ return IntPtr.Zero;
+ }
+ SetForegroundWindow(hTo);
+ AttachThreadInput(tid, pid, false);
+ }
+ return (hFrom);
+ }
+
+ ///
+ /// We need to handle WM_INPUT.
+ ///
+ ///
protected override void WndProc(ref Message message)
{
switch (message.Msg)
diff -r 2e0571e50ab3 -r 9d5867ce966a Server/SharpDisplayManager.csproj
--- a/Server/SharpDisplayManager.csproj Wed Mar 18 20:38:59 2015 +0100
+++ b/Server/SharpDisplayManager.csproj Wed Mar 18 21:47:06 2015 +0100
@@ -31,7 +31,7 @@
true
index.htm
false
- 3
+ 4
0.3.2.%2a
false
true