// Intercept keyboard messages for Ctrl-F4 and Ctrl-Tab handling private IntPtr KBHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { int vkCode = Marshal.ReadInt32(lParam); Keys keys = (Keys)vkCode; // track key state globally for control/alt/shift is up/down bool isKeyDown = (wParam == (IntPtr)NativeMethods.WM_KEYDOWN || wParam == (IntPtr)NativeMethods.WM_SYSKEYDOWN); if (keys == Keys.LControlKey || keys == Keys.RControlKey) { isControlDown = isKeyDown; } if (keys == Keys.LShiftKey || keys == Keys.RShiftKey) { isShiftDown = isKeyDown; } if (keys == Keys.LMenu || keys == Keys.RMenu) { isAltDown = isKeyDown; } if (Log.Logger.IsEnabledFor(Level.Trace)) { Log.DebugFormat("### KBHook: nCode={0}, wParam={1}, lParam={2} ({4,-4} - {3}) [{5}{6}{7}]", nCode, wParam, vkCode, keys, isKeyDown ? "Down" : "Up", (isControlDown ? "Ctrl" : ""), (isAltDown ? "Alt" : ""), (isAltDown ? "Shift" : "")); } if (IsForegroundWindow(this)) { // SuperPuTTY or Putty is the window in front... if (keys == Keys.LControlKey || keys == Keys.RControlKey) { // If Ctrl-Tab has been pressed to move to an older panel then // make it current panel when Ctrl key is finally released. if (SuperPuTTY.Settings.EnableControlTabSwitching && !isControlDown && !isShiftDown) { this.tabSwitcher.CurrentDocument = (ToolWindow)this.DockPanel.ActiveDocument; } } if (keys == Keys.LShiftKey || keys == Keys.RShiftKey) { // If Ctrl-Shift-Tab has been pressed to move to an older panel then // make it current panel when both keys are finally released. if (SuperPuTTY.Settings.EnableControlTabSwitching && !isControlDown && !isShiftDown) { this.tabSwitcher.CurrentDocument = (ToolWindow)this.DockPanel.ActiveDocument; } } if (SuperPuTTY.Settings.EnableControlTabSwitching && isControlDown && !isShiftDown && keys == Keys.Tab) { // Operator has pressed Ctrl-Tab, make next PuTTY panel active if (isKeyDown && this.DockPanel.ActiveDocument is ToolWindowDocument) { if (this.tabSwitcher.MoveToNextDocument()) { // Eat the keystroke return (IntPtr)1; } } } if (SuperPuTTY.Settings.EnableControlTabSwitching && isControlDown && isShiftDown && keys == Keys.Tab) { // Operator has pressed Ctrl-Shift-Tab, make previous PuTTY panel active if (isKeyDown && this.DockPanel.ActiveDocument is ToolWindowDocument) { if (this.tabSwitcher.MoveToPrevDocument()) { // Eat the keystroke return (IntPtr)1; } } } if (isControlDown && !isShiftDown && keys == Keys.V) { if (this.DockPanel.ActiveDocument is ctlPuttyPanel) { ctlPuttyPanel puttyPanel = (ctlPuttyPanel)this.DockPanel.ActiveDocument; string commandText = Clipboard.GetText(); CommandData commandData = new CommandData(commandText); int handle = puttyPanel.AppPanel.AppWindowHandle.ToInt32(); Log.InfoFormat("SendCommand: session={0}, command=[{1}], handle={2}", puttyPanel.Session.SessionName, commandText, handle); try { commandData.SendToTerminal(handle); return (IntPtr)1; } catch (Exception e) { Log.ErrorFormat("Send command failed : {0}", e.Message); } } } // misc action handling (eat keyup and down) if (SuperPuTTY.Settings.EnableKeyboadShortcuts && isKeyDown && keys != Keys.LControlKey && keys != Keys.RControlKey && keys != Keys.LMenu && keys != Keys.RMenu && keys != Keys.LShiftKey && keys != Keys.RShiftKey) { if (isControlDown) keys |= Keys.Control; if (isShiftDown) keys |= Keys.Shift; if (isAltDown) keys |= Keys.Alt; if (Log.Logger.IsEnabledFor(Level.Trace)) { Log.DebugFormat("#### TryExecute shortcut: keys={0}", keys); } SuperPuTTYAction action; if (this.shortcuts.TryGetValue(keys, out action)) { // post action to avoid getting errant keystrokes (e.g. allow current to be eaten) this.BeginInvoke(new Action(() => { ExecuteSuperPuTTYAction(action); })); return (IntPtr)1; } } } } return NativeMethods.CallNextHookEx(kbHookID, nCode, wParam, lParam); }
int TrySendCommandsFromToolbar(CommandData command, bool saveHistory) { int sent = 0; //String command = this.tsSendCommandCombo.Text; //this.tbTextCommand.Text; if (this.DockPanel.DocumentsCount > 0) { foreach (DockContent content in this.DockPanel.Documents) { ctlPuttyPanel puttyPanel = content as ctlPuttyPanel; if (puttyPanel != null && this.sendCommandsDocumentSelector.IsDocumentSelected(puttyPanel)) { int handle = puttyPanel.AppPanel.AppWindowHandle.ToInt32(); Log.InfoFormat("SendCommand: session={0}, command=[{1}], handle={2}", puttyPanel.Session.SessionName, command, handle); command.SendToTerminal(handle); /* foreach (Char c in command.Chars) { NativeMethods.SendMessage(handle, NativeMethods.WM_CHAR, (int)c, 0); } NativeMethods.SendMessage(handle, NativeMethods.WM_CHAR, (int)Keys.Enter, 0);*/ //NativeMethods.SendMessage(handle, NativeMethods.WM_KEYUP, (int)Keys.Enter, 0); sent++; } } if (sent > 0) { // success...clear text and save in mru this.tsSendCommandCombo.Text = string.Empty; if (this.tsSendCommandCombo.Items.Count >= SuperPuTTY.Settings.MaxCommandHistory) { this.tsSendCommandCombo.Items.RemoveAt(this.tsSendCommandCombo.Items.Count - 1); } if (command != null && !string.IsNullOrEmpty(command.Command) && saveHistory) { this.tsSendCommandCombo.Items.Insert(0, command.ToString()); } } } return sent; }