1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections;
6
using System.Collections.Generic;
7
using System.ComponentModel;
8
using System.ComponentModel.Design;
9
using System.Reflection;
10
using System.Windows.Forms;
11
using System.Windows.Forms.Design;
13
using ICSharpCode.Core;
14
using ICSharpCode.SharpDevelop.Gui;
16
namespace ICSharpCode.FormsDesigner
18
public sealed class FormKeyHandler : IMessageFilter
20
const int keyPressedMessage = 0x100;
21
const int leftMouseButtonDownMessage = 0x0202;
23
readonly Dictionary<Keys, CommandWrapper> keyTable = new Dictionary<Keys, CommandWrapper>();
24
public static bool inserted = false;
25
public static void Insert()
28
Application.AddMessageFilter(new FormKeyHandler());
31
public FormKeyHandler()
34
keyTable[Keys.Left] = new CommandWrapper(MenuCommands.KeyMoveLeft);
35
keyTable[Keys.Right] = new CommandWrapper(MenuCommands.KeyMoveRight);
36
keyTable[Keys.Up] = new CommandWrapper(MenuCommands.KeyMoveUp);
37
keyTable[Keys.Down] = new CommandWrapper(MenuCommands.KeyMoveDown);
38
keyTable[Keys.Tab] = new CommandWrapper(MenuCommands.KeySelectNext);
39
keyTable[Keys.Delete] = new CommandWrapper(MenuCommands.Delete);
40
keyTable[Keys.Back] = new CommandWrapper(MenuCommands.Delete);
42
// shift modified keys
43
keyTable[Keys.Left | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeWidthDecrease);
44
keyTable[Keys.Right | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeWidthIncrease);
45
keyTable[Keys.Up | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeHeightDecrease);
46
keyTable[Keys.Down | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeHeightIncrease);
47
keyTable[Keys.Tab | Keys.Shift] = new CommandWrapper(MenuCommands.KeySelectPrevious);
48
keyTable[Keys.Delete| Keys.Shift] = new CommandWrapper(MenuCommands.Delete);
49
keyTable[Keys.Back| Keys.Shift] = new CommandWrapper(MenuCommands.Delete);
52
keyTable[Keys.Left | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeLeft);
53
keyTable[Keys.Right | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeRight);
54
keyTable[Keys.Up | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeUp);
55
keyTable[Keys.Down | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeDown);
57
// ctrl + shift modified keys
58
keyTable[Keys.Left | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeWidthDecrease);
59
keyTable[Keys.Right | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeWidthIncrease);
60
keyTable[Keys.Up | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeHeightDecrease);
61
keyTable[Keys.Down | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeHeightIncrease);
64
public bool PreFilterMessage(ref Message m)
66
if (m.Msg != keyPressedMessage /*&& m.Msg != leftMouseButtonDownMessage*/) {
70
FormsDesignerViewContent formDesigner = WorkbenchSingleton.Workbench.ActiveContent as FormsDesignerViewContent;
72
if (formDesigner == null || formDesigner.Host == null) {
75
if (formDesigner.UserContent != null && !((Control)formDesigner.UserContent).ContainsFocus) {
79
Control originControl = Control.FromChildHandle(m.HWnd);
80
if (originControl != null && formDesigner.UserContent != null && !(formDesigner.UserContent == originControl || formDesigner.UserContent.Contains(originControl))) {
81
// Ignore if message origin not in forms designer
82
// (e.g. navigating the main menu)
86
Keys keyPressed = (Keys)m.WParam.ToInt32() | Control.ModifierKeys;
88
if (keyPressed == Keys.Escape) {
89
if (formDesigner.IsTabOrderMode) {
90
formDesigner.HideTabOrder();
95
CommandWrapper commandWrapper;
96
if (keyTable.TryGetValue(keyPressed, out commandWrapper)) {
97
if (commandWrapper.CommandID == MenuCommands.Delete) {
98
// Check Delete menu is enabled.
99
if (!formDesigner.EnableDelete) {
103
LoggingService.Debug("Run menu command: " + commandWrapper.CommandID);
105
IMenuCommandService menuCommandService = (IMenuCommandService)formDesigner.Host.GetService(typeof(IMenuCommandService));
106
ISelectionService selectionService = (ISelectionService)formDesigner.Host.GetService(typeof(ISelectionService));
107
ICollection components = selectionService.GetSelectedComponents();
108
if (components.Count == 1) {
109
foreach (IComponent component in components) {
110
if (HandleMenuCommand(formDesigner, component, keyPressed))
115
menuCommandService.GlobalInvoke(commandWrapper.CommandID);
117
if (commandWrapper.RestoreSelection) {
118
selectionService.SetSelectedComponents(components);
126
bool HandleMenuCommand(FormsDesignerViewContent formDesigner, IComponent activeComponent, Keys keyPressed)
128
Assembly asm = typeof(WindowsFormsDesignerOptionService).Assembly;
129
// Microsoft made ToolStripKeyboardHandlingService internal, so we need Reflection
130
Type keyboardType = asm.GetType("System.Windows.Forms.Design.ToolStripKeyboardHandlingService");
131
object keyboardService = formDesigner.Host.GetService(keyboardType);
132
if (keyboardService == null) {
133
LoggingService.Debug("no ToolStripKeyboardHandlingService found");
134
return false; // handle command normally
136
if (activeComponent is ToolStripItem) {
137
if (keyPressed == Keys.Up) {
138
keyboardType.InvokeMember("ProcessUpDown",
139
BindingFlags.Instance
140
| BindingFlags.Public
141
| BindingFlags.InvokeMethod,
142
null, keyboardService, new object[] { false });
143
return true; // command was handled specially
144
} else if (keyPressed == Keys.Down) {
145
keyboardType.InvokeMember("ProcessUpDown",
146
BindingFlags.Instance
147
| BindingFlags.Public
148
| BindingFlags.InvokeMethod,
149
null, keyboardService, new object[] { true });
150
return true; // command was handled specially
153
bool active = (bool)keyboardType.InvokeMember("TemplateNodeActive",
154
BindingFlags.Instance
155
| BindingFlags.NonPublic
156
| BindingFlags.GetProperty,
157
null, keyboardService, null);
159
return true; // command will handled specially by the text box, don't invoke the CommandID
161
return false; // invoke the CommandID
164
sealed class CommandWrapper
167
bool restoreSelection;
169
public CommandID CommandID {
175
public bool RestoreSelection {
177
return restoreSelection;
181
public CommandWrapper(CommandID commandID) : this(commandID, false)
184
public CommandWrapper(CommandID commandID, bool restoreSelection)
186
this.commandID = commandID;
187
this.restoreSelection = restoreSelection;