Looks like we have a solution for our bring to foreground problem.
1.1 --- a/Server/MainForm.Hid.cs Wed Mar 18 20:38:59 2015 +0100
1.2 +++ b/Server/MainForm.Hid.cs Wed Mar 18 21:47:06 2015 +0100
1.3 @@ -14,22 +14,26 @@
1.4 namespace SharpDisplayManager
1.5 {
1.6 [System.ComponentModel.DesignerCategory("Code")]
1.7 - public class MainFormHid: Form
1.8 + public class MainFormHid : Form
1.9 {
1.10
1.11 [DllImport("USER32.DLL")]
1.12 public static extern bool SetForegroundWindow(IntPtr hWnd);
1.13
1.14 [DllImport("USER32.DLL")]
1.15 - public static extern bool BringWindowToTop(IntPtr hWnd);
1.16 + public static extern IntPtr GetForegroundWindow();
1.17
1.18 - [DllImport("USER32.DLL")]
1.19 - public static extern bool IsIconic(IntPtr hWnd);
1.20 + [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
1.21 + public static extern uint GetWindowThreadProcessId([System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, System.IntPtr lpdwProcessId);
1.22
1.23 - [DllImport("USER32.DLL")]
1.24 - public static extern bool OpenIcon(IntPtr hWnd);
1.25 + [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "GetCurrentThreadId")]
1.26 + public static extern uint GetCurrentThreadId();
1.27
1.28 + [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "AttachThreadInput")]
1.29 + [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
1.30 + public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fAttach);
1.31
1.32 + //
1.33 public delegate void OnHidEventDelegate(object aSender, Hid.Event aHidEvent);
1.34
1.35 /// <summary>
1.36 @@ -37,6 +41,9 @@
1.37 /// </summary>
1.38 private Hid.Handler iHidHandler;
1.39
1.40 + /// <summary>
1.41 + /// Register HID devices so that we receive corresponding WM_INPUT messages.
1.42 + /// </summary>
1.43 protected void RegisterHidDevices()
1.44 {
1.45 // Register the input device to receive the commands from the
1.46 @@ -96,6 +103,11 @@
1.47 iHidHandler.OnHidEvent += HandleHidEventThreadSafe;
1.48 }
1.49
1.50 + /// <summary>
1.51 + /// Here we receive HID events from our HID library.
1.52 + /// </summary>
1.53 + /// <param name="aSender"></param>
1.54 + /// <param name="aHidEvent"></param>
1.55 public void HandleHidEventThreadSafe(object aSender, SharpLib.Hid.Event aHidEvent)
1.56 {
1.57 if (aHidEvent.IsStray)
1.58 @@ -116,14 +128,13 @@
1.59 if (aHidEvent.Usages.Count > 0
1.60 && aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl
1.61 && aHidEvent.Usages[0] == (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart)
1.62 - //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer
1.63 - //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
1.64 -
1.65 + //&& aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer
1.66 + //&& aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
1.67 {
1.68 //First check if the process we want to launch already exists
1.69 string procName = Path.GetFileNameWithoutExtension(Properties.Settings.Default.StartFileName);
1.70 Process[] existingProcesses = Process.GetProcessesByName(procName);
1.71 - if (existingProcesses == null || existingProcesses.Length==0)
1.72 + if (existingProcesses == null || existingProcesses.Length == 0)
1.73 {
1.74 // Process do not exists just try to launch it
1.75 ProcessStartInfo start = new ProcessStartInfo();
1.76 @@ -136,27 +147,68 @@
1.77 start.UseShellExecute = true;
1.78 // Run the external process & wait for it to finish
1.79 Process proc = Process.Start(start);
1.80 -
1.81 +
1.82 //SL: We could have used that too
1.83 //Shell32.Shell shell = new Shell32.Shell();
1.84 //shell.ShellExecute(Properties.Settings.Default.StartFileName);
1.85 }
1.86 else
1.87 {
1.88 - BringWindowToTop(existingProcesses[0].MainWindowHandle);
1.89 - SetForegroundWindow(existingProcesses[0].MainWindowHandle);
1.90 - if (IsIconic(existingProcesses[0].MainWindowHandle))
1.91 - {
1.92 - OpenIcon(existingProcesses[0].MainWindowHandle);
1.93 - }
1.94 - BringWindowToTop(existingProcesses[0].MainWindowHandle);
1.95 - SetForegroundWindow(existingProcesses[0].MainWindowHandle);
1.96 - }
1.97 + ForceForegroundWindow(existingProcesses[0].MainWindowHandle);
1.98 + }
1.99 }
1.100 }
1.101 }
1.102
1.103 -
1.104 +
1.105 + /// <summary>
1.106 + /// For the Window with the given handle to the foreground no matter what.
1.107 + /// That works around flashing Window issues.
1.108 + /// As seen on http://www.asyncop.com/MTnPDirEnum.aspx?treeviewPath=[o]+Open-Source\WinModules\Infrastructure\SystemAPI.cpp
1.109 + /// </summary>
1.110 + /// <param name="hTo"></param>
1.111 + /// <returns></returns>
1.112 + IntPtr ForceForegroundWindow(IntPtr hTo)
1.113 + {
1.114 + if (hTo == IntPtr.Zero)
1.115 + {
1.116 + return IntPtr.Zero;
1.117 + }
1.118 + IntPtr hFrom = GetForegroundWindow();
1.119 +
1.120 + if (hFrom != IntPtr.Zero)
1.121 + {
1.122 + SetForegroundWindow(hTo);
1.123 + return IntPtr.Zero;
1.124 + }
1.125 + if (hTo == hFrom)
1.126 + {
1.127 + return IntPtr.Zero;
1.128 + }
1.129 +
1.130 + uint pid = GetWindowThreadProcessId(hFrom, IntPtr.Zero);
1.131 + uint tid = GetCurrentThreadId();
1.132 + if (tid == pid)
1.133 + {
1.134 + SetForegroundWindow(hTo);
1.135 + return (hFrom);
1.136 + }
1.137 + if (pid != 0)
1.138 + {
1.139 + if (!AttachThreadInput(tid, pid, true))
1.140 + {
1.141 + return IntPtr.Zero;
1.142 + }
1.143 + SetForegroundWindow(hTo);
1.144 + AttachThreadInput(tid, pid, false);
1.145 + }
1.146 + return (hFrom);
1.147 + }
1.148 +
1.149 + /// <summary>
1.150 + /// We need to handle WM_INPUT.
1.151 + /// </summary>
1.152 + /// <param name="message"></param>
1.153 protected override void WndProc(ref Message message)
1.154 {
1.155 switch (message.Msg)
2.1 --- a/Server/SharpDisplayManager.csproj Wed Mar 18 20:38:59 2015 +0100
2.2 +++ b/Server/SharpDisplayManager.csproj Wed Mar 18 21:47:06 2015 +0100
2.3 @@ -31,7 +31,7 @@
2.4 <CreateWebPageOnPublish>true</CreateWebPageOnPublish>
2.5 <WebPage>index.htm</WebPage>
2.6 <OpenBrowserOnPublish>false</OpenBrowserOnPublish>
2.7 - <ApplicationRevision>3</ApplicationRevision>
2.8 + <ApplicationRevision>4</ApplicationRevision>
2.9 <ApplicationVersion>0.3.2.%2a</ApplicationVersion>
2.10 <UseApplicationTrust>false</UseApplicationTrust>
2.11 <CreateDesktopShortcut>true</CreateDesktopShortcut>