diff --git a/KVMControl.Designer.cs b/KVMControl.Designer.cs index 07e2537..6473a54 100644 --- a/KVMControl.Designer.cs +++ b/KVMControl.Designer.cs @@ -38,9 +38,6 @@ this.Name = "KVMControl"; this.Size = new System.Drawing.Size(585, 364); this.Paint += new System.Windows.Forms.PaintEventHandler(this.KVMControl_Paint); - this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.KVMControl_KeyDown); - this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.KVMControl_KeyPress); - this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.KVMControl_KeyUp); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.KVMControl_MouseDown); this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.KVMControl_MouseMove); this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.KVMControl_MouseUp); diff --git a/KVMControl.cs b/KVMControl.cs index 044ef36..c42d0fc 100644 --- a/KVMControl.cs +++ b/KVMControl.cs @@ -46,6 +46,9 @@ namespace MeshCentralRouter public double DpiX = 96; public double DpiY = 96; public KVMViewer parent = null; + private readonly KVMControlHook.KVMCallback KeyboardCallback; + private bool keyboardIsAttached; + private enum KvmCommands { @@ -121,6 +124,25 @@ namespace MeshCentralRouter this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.MouseWheel += new System.Windows.Forms.MouseEventHandler(KVMControl_MouseWheel); + KeyboardCallback = SendKey; + } + + public void AttachKeyboard() + { + if (!keyboardIsAttached) + { + Program.controlHook.AttachCallback(KeyboardCallback); + keyboardIsAttached = true; + } + } + + public void DetacheKeyboard() + { + if (keyboardIsAttached) + { + Program.controlHook.DetachCallback(); + keyboardIsAttached = false; + } } public int ProcessData(byte[] buffer, int off, int len) @@ -543,24 +565,6 @@ namespace MeshCentralRouter SendMouse(e, 0); } - private void KVMControl_KeyDown(object sender, KeyEventArgs e) - { - if ((e.KeyCode == Keys.LWin) || (e.KeyCode == Keys.RWin)) return; // Don't process the Windows key - SendKey(e, 0); - e.Handled = true; - } - - private void KVMControl_KeyUp(object sender, KeyEventArgs e) - { - SendKey(e, 1); - e.Handled = true; - } - - private void KVMControl_KeyPress(object sender, KeyPressEventArgs e) - { - e.Handled = true; - } - private void KVMControl_MouseEnter(object sender, EventArgs e) { this.Focus(); @@ -575,28 +579,6 @@ namespace MeshCentralRouter Send(bw); } - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - const int WM_KEYDOWN = 0x100; - const int WM_SYSKEYDOWN = 0x104; - - // Tab keys - if (msg.Msg == WM_KEYDOWN && msg.WParam.ToInt32() == 9) - { - SendKey((byte)msg.WParam.ToInt32(), 0); - return true; - } - - // Handle arrow keys - if (((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) && msg.WParam.ToInt32() >= 37 && msg.WParam.ToInt32() <= 40) - { - SendKey((byte)msg.WParam.ToInt32(), 0); - return true; - } - - return false; - } - public void GetDisplayNumbers() { //if (state != ConnectState.Connected) return; @@ -618,12 +600,6 @@ namespace MeshCentralRouter Send(bw); } - public void SendWindowsKey() - { - SendKey(0x5B, 4); // Windows key down - SendKey(0x5B, 3); // Windows key up - } - public void SendCharmsKey() { SendKey(0x5B, 4); // Windows key down diff --git a/KVMControlHook.cs b/KVMControlHook.cs new file mode 100644 index 0000000..809fa0b --- /dev/null +++ b/KVMControlHook.cs @@ -0,0 +1,98 @@ + +using System; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace MeshCentralRouter +{ + public class KVMControlHook + { + public delegate void KVMCallback(byte keyCodes, byte lParam); + private KVMCallback _callback; + private KVMKeyboardHook.LowLevelKeyboardProc _proc; + private static IntPtr _hook = IntPtr.Zero; + protected static KVMControl _control; + internal KVMControlHook() + { + _proc = HookCallback; + AttachKeyboardHook(); + } + + private void AttachKeyboardHook() + { + try + { + _hook = KVMKeyboardHook.SetHook(_proc); + } + catch + { + DetachKeyboardHook(); + throw new System.InvalidOperationException("Could not set hook."); + } + } + + internal void AttachCallback(KVMCallback callback) + { + _callback = callback; + } + + internal void DetachCallback() + { + _callback = null; + } + + internal static void DetachKeyboardHook() + { + if (_hook != IntPtr.Zero) + KVMKeyboardHook.UnhookWindowsHookEx(_hook); + } + + public IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) + { + if (nCode >= 0) + { + bool alt = (Control.ModifierKeys & Keys.Alt) != 0; + bool control = (Control.ModifierKeys & Keys.Control) != 0; + + Keys key = (Keys)Marshal.ReadInt32(lParam); + + const int WM_KEYDOWN = 0x100; + const int WM_KEYUP = 0x101; + const int WM_SYSKEYDOWN = 0x104; + const int WM_SYSKEYUP = 0x105; + + byte bkey = (byte)key; + byte keyStatus; + switch ((int)wParam) + { + case WM_KEYDOWN: + keyStatus = 0; + break; + case WM_KEYUP: + keyStatus = 1; + break; + case WM_SYSKEYDOWN: + keyStatus = 4; + break; + case WM_SYSKEYUP: + keyStatus = 5; + break; + default: + return KVMKeyboardHook.CallNextHookEx(_hook, nCode, wParam, lParam); + } + + try + { + if (_callback != null) + { + _callback(bkey,keyStatus); + return (IntPtr)1; + } + } + catch { } + } + return KVMKeyboardHook.CallNextHookEx(_hook, nCode, wParam, lParam); + } + } +} + diff --git a/KVMKeyboardHook.cs b/KVMKeyboardHook.cs new file mode 100644 index 0000000..52f4b8d --- /dev/null +++ b/KVMKeyboardHook.cs @@ -0,0 +1,57 @@ +/* + +credit to https://github.com/shanselman/babysmash + +Copyright (c) 2015 Scott Hanselman +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace MeshCentralRouter +{ + internal class KVMKeyboardHook + { + #region Delegates + + public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); + + #endregion + + private const int WH_KEYBOARD_LL = 13; + private const int WM_KEYDOWN = 0x0100; + + public static IntPtr SetHook(LowLevelKeyboardProc proc) + { + using (Process curProcess = Process.GetCurrentProcess()) + using (ProcessModule curModule = curProcess.MainModule) + { + return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); + } + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool UnhookWindowsHookEx(IntPtr hhk); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr GetModuleHandle(string lpModuleName); + } +} \ No newline at end of file diff --git a/KVMViewer.Designer.cs b/KVMViewer.Designer.cs index e7bb83e..e48d4d4 100644 --- a/KVMViewer.Designer.cs +++ b/KVMViewer.Designer.cs @@ -200,6 +200,8 @@ namespace MeshCentralRouter this.resizeKvmControl.ZoomToFit = false; this.resizeKvmControl.StateChanged += new System.EventHandler(this.kvmControl_StateChanged); this.resizeKvmControl.DisplaysReceived += new System.EventHandler(this.resizeKvmControl_DisplaysReceived); + this.resizeKvmControl.Enter += new System.EventHandler(this.resizeKvmControl_Enter); + this.resizeKvmControl.Leave += new System.EventHandler(this.resizeKvmControl_Leave); // // KVMViewer // @@ -211,6 +213,8 @@ namespace MeshCentralRouter this.Controls.Add(this.topPanel); this.Controls.Add(this.mainStatusStrip); this.Name = "KVMViewer"; + this.Activated += new System.EventHandler(this.KVMViewer_Activated); + this.Deactivate += new System.EventHandler(this.KVMViewer_Deactivate); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Main_FormClosing); this.Load += new System.EventHandler(this.MainForm_Load); this.Resize += new System.EventHandler(this.MainForm_Resize); diff --git a/KVMViewer.cs b/KVMViewer.cs index 1a18435..280bcc7 100644 --- a/KVMViewer.cs +++ b/KVMViewer.cs @@ -36,7 +36,6 @@ namespace MeshCentralRouter private bool sessionIsRecorded = false; public webSocketClient wc = null; public Dictionary userSessions = null; - // Stats public long bytesIn = 0; public long bytesInCompressed = 0; @@ -122,6 +121,7 @@ namespace MeshCentralRouter state = 0; wc.Dispose(); wc = null; + kvmControl.DetacheKeyboard(); break; } case webSocketClient.ConnectionStates.Connecting: @@ -224,6 +224,7 @@ namespace MeshCentralRouter { // Connect MenuItemConnect_Click(null, null); + kvmControl.AttachKeyboard(); } displayMessage(null); } @@ -405,7 +406,7 @@ namespace MeshCentralRouter private void winButton_Click(object sender, EventArgs e) { - kvmControl.SendWindowsKey(); + //kvmControl.SendWindowsKey(); } private void charmButton_Click(object sender, EventArgs e) @@ -480,5 +481,25 @@ namespace MeshCentralRouter server.sendCommand("{\"action\":\"msg\",\"type\":\"setclip\",\"nodeid\":\"" + node.nodeid + "\",\"data\":\"" + textData + "\"}"); } } + + private void resizeKvmControl_Enter(object sender, EventArgs e) + { + kvmControl.AttachKeyboard(); + } + + private void resizeKvmControl_Leave(object sender, EventArgs e) + { + kvmControl.DetacheKeyboard(); + } + + private void KVMViewer_Deactivate(object sender, EventArgs e) + { + kvmControl.DetacheKeyboard(); + } + + private void KVMViewer_Activated(object sender, EventArgs e) + { + kvmControl.AttachKeyboard(); + } } } diff --git a/KVMViewer.resx b/KVMViewer.resx index 415ebd3..f919ebd 100644 --- a/KVMViewer.resx +++ b/KVMViewer.resx @@ -121,31 +121,13 @@ 127, 17 - - 1029, 17 - - - --- - - - MiddleLeft - - - 13, 17 - - - v - - - - False - - 0, 772 + 0, 727 1044, 22 + 9 @@ -164,6 +146,24 @@ 3 + + 1029, 17 + + + --- + + + MiddleLeft + + + 13, 17 + + + v + + + False + 264, 17 @@ -583,7 +583,7 @@ 0, 32 - 1044, 740 + 1044, 695 10 @@ -592,7 +592,7 @@ resizeKvmControl - MeshCentralRouter.KVMResizeControl, MeshCentralRouter, Version=1.0.7565.29854, Culture=neutral, PublicKeyToken=null + MeshCentralRouter.KVMResizeControl, MeshCentralRouter, Version=1.0.7568.41332, Culture=neutral, PublicKeyToken=null $this @@ -607,7 +607,7 @@ 6, 13 - 1044, 794 + 1044, 749 diff --git a/MainForm.cs b/MainForm.cs index 65a3ed5..6341ce1 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -143,7 +143,7 @@ namespace MeshCentralRouter } public string getRegValue(string name, string value) { - try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router", name, value).ToString(); } catch (Exception) { return value; } + try {return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router", name, value).ToString(); } catch (Exception) { return value; } } public MainForm(string[] args) diff --git a/MeshCentralRouter.csproj b/MeshCentralRouter.csproj index 5b04242..9482c68 100644 --- a/MeshCentralRouter.csproj +++ b/MeshCentralRouter.csproj @@ -130,6 +130,8 @@ InstallForm.cs + + UserControl diff --git a/Program.cs b/Program.cs index c4a3f65..0d90126 100644 --- a/Program.cs +++ b/Program.cs @@ -21,6 +21,7 @@ namespace MeshCentralRouter { static class Program { + public static KVMControlHook controlHook = new KVMControlHook(); /// /// The main entry point for the application. ///