misu – Blame information for rev 5

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.ComponentModel;
3 using System.Drawing;
4 using System.Linq;
5 using System.Threading.Tasks.Dataflow;
6 using System.Windows.Forms;
7 using Configuration;
8 using Gma.System.MouseKeyHook;
9  
10 namespace misu
11 {
3 office 12 public partial class MisuMainForm : Form
1 office 13 {
14 #region Public Enums, Properties and Fields
15  
16 public Settings Settings { get; set; }
17  
18 #endregion
19  
20 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
21  
22 private BufferBlock<KeyEventArgs> PressedKeysBufferBlock { get; }
23  
24 private IKeyboardMouseEvents GlobalHook { get; }
25  
26 private AboutForm AboutForm { get; set; }
27  
28 private BindKeyForm BindKeyForm { get; set; }
29  
30 private volatile bool _lock;
31  
32 #endregion
33  
34 #region Constructors, Destructors and Finalizers
35  
3 office 36 public MisuMainForm()
1 office 37 {
38 InitializeComponent();
39  
40 PressedKeysBufferBlock = new BufferBlock<KeyEventArgs>(new DataflowBlockOptions {EnsureOrdered = true});
41  
42 // Load the settings.
43 var serialization = Serialization.Deserialize(@"Settings.xml");
44 switch (serialization)
45 {
46 case SerializationSuccess<Settings> serializationSuccess:
47 Settings = serializationSuccess.Result;
48 break;
49 case SerializationFailure _:
50 Settings = new Settings();
51 break;
52 }
53  
54 Settings.PropertyChanged += Settings_PropertyChanged;
3 office 55 Settings.Binding.PropertyChanged += Binding_PropertyChanged;
1 office 56  
57 // Hook to global events.
58 GlobalHook = Hook.GlobalEvents();
59  
60 // Bind to receive keyboard presses.
61 GlobalHook.KeyDown += GlobalHook_KeyDown;
62 GlobalHook.KeyUp += GlobalHook_KeyUp;
3 office 63  
64 GlobalHook.MouseUpExt += GlobalHook_BlockMouse;
65 GlobalHook.MouseDragFinishedExt += GlobalHook_BlockMouse;
66 GlobalHook.MouseDragStartedExt += GlobalHook_BlockMouse;
67 GlobalHook.MouseWheelExt += GlobalHook_BlockMouse;
68 GlobalHook.MouseMoveExt += GlobalHook_BlockMouse;
69 GlobalHook.MouseDownExt += GlobalHook_BlockMouse;
70  
71 if (Settings.Binding.Keys.Any())
72 {
5 office 73 Notify("Shortcut is bound.",
3 office 74 $"Press {Settings.Binding} to toggle locking.");
75 }
1 office 76 }
77  
78 #endregion
79  
80 #region Event Handlers
81  
3 office 82 private async void Binding_PropertyChanged(object sender, PropertyChangedEventArgs e)
1 office 83 {
3 office 84 await Settings.Serialize(@"Settings.xml");
85 }
86  
87 private void GlobalHook_BlockMouse(object sender, MouseEventExtArgs e)
88 {
89 // Do not perform any operations while the binding form is visible.
90 if (BindKeyForm != null && BindKeyForm.Visible)
1 office 91 {
3 office 92 return;
1 office 93 }
3 office 94  
95 if (_lock && Settings.Mouse)
96 {
97 e.Handled = true;
98 }
1 office 99 }
100  
101 private async void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
102 {
103 // Serialize the settings to the configuration file on form closing.
104 await Settings.Serialize(@"Settings.xml");
105 }
106  
107 private void GlobalHook_KeyUp(object sender, KeyEventArgs e)
108 {
3 office 109 // Do not perform any operations while the binding form is visible.
110 if (BindKeyForm != null && BindKeyForm.Visible)
1 office 111 {
112 return;
113 }
114  
115 if (!PressedKeysBufferBlock.TryReceiveAll(out var keys))
116 {
117 return;
118 }
119  
3 office 120 if (Settings.Binding == null)
121 {
122 return;
123 }
124  
1 office 125 if (Settings.Binding.Keys.SequenceContains(keys.Select(key => key.KeyCode)))
126 {
127 _lock = !_lock;
128  
3 office 129 // Lock the cursor in position.
130 switch (_lock)
131 {
132 case true:
133 Cursor.Clip = new Rectangle(Cursor.Position, new Size(1, 1));
134 break;
135 default:
136 Cursor.Clip = Screen.PrimaryScreen.Bounds;
137 break;
138 }
1 office 139  
140 // Dismiss the current keypress to avoid typing the key.
141 e.Handled = true;
142 e.SuppressKeyPress = true;
143  
3 office 144 Notify($"Mouse and Keyboard are {(_lock ? "locked" : "unlocked")}.",
145 $"Press {Settings.Binding} to toggle mouse and keyboard locking.");
1 office 146 }
147 }
148  
149 private async void GlobalHook_KeyDown(object sender, KeyEventArgs e)
150 {
3 office 151 // Do not perform any operations while the binding form is visible.
152 if (BindKeyForm != null && BindKeyForm.Visible)
153 {
154 return;
155 }
156  
1 office 157 if (_lock && Settings.Keyboard)
158 {
159 e.SuppressKeyPress = true;
160 e.Handled = true;
161 }
162  
163 await PressedKeysBufferBlock.SendAsync(e);
164 }
165  
166 private void OnContextMenuAboutClick(object sender, EventArgs e)
167 {
168 // Show the about form.
169 AboutForm = new AboutForm();
170 AboutForm.Show();
171 }
172  
173 private void OnContextMenuQuitClick(object sender, EventArgs e)
174 {
175 Application.Exit();
176 }
177  
178 private void OnContextMenuLaunchOnBootChanged(object sender, EventArgs e)
179 {
180 Settings.LaunchOnBoot = ((ToolStripMenuItem) sender).Checked;
181  
182 Utilities.LaunchOnBootSet(Settings.LaunchOnBoot);
183 }
184  
185 private void OnContextMenuBindKeyClick(object sender, EventArgs e)
186 {
187 BindKeyForm = new BindKeyForm(GlobalHook, Settings);
188 BindKeyForm.KeyBound += BindKeyForm_KeyBound;
189 BindKeyForm.Closing += BindKeyForm_Closing;
190 BindKeyForm.Show();
191 }
192  
193 private void BindKeyForm_Closing(object sender, CancelEventArgs e)
194 {
195 BindKeyForm.KeyBound -= BindKeyForm_KeyBound;
196 BindKeyForm.Closing -= BindKeyForm_Closing;
197 }
198  
3 office 199 private async void BindKeyForm_KeyBound(object sender, KeyBoundEventArgs e)
1 office 200 {
3 office 201 Notify("Shortcut key is bound.",
202 $"Press {e.Binding} to toggle between locked and unlocked keyboard and mouse.");
1 office 203  
3 office 204 Settings.Binding.Keys.AddRange(e.Binding.Keys);
205  
206 await Settings.Serialize(@"Settings.xml");
1 office 207 }
208  
209 private void KeyboardToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
210 {
211 var item = (ToolStripMenuItem) sender;
212  
213 Settings.Keyboard = item.Checked;
214 }
215  
216 private void MouseToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
217 {
218 var item = (ToolStripMenuItem) sender;
219  
220 Settings.Mouse = item.Checked;
221 }
222  
223 private void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
224 {
225 // Apply the settings to the menu items.
226 launchOnBootToolStripMenuItem.Checked = Settings.LaunchOnBoot;
227 Utilities.LaunchOnBootSet(Settings.LaunchOnBoot);
228  
229 mouseToolStripMenuItem.Checked = Settings.Mouse;
230 keyboardToolStripMenuItem.Checked = Settings.Keyboard;
231 }
232  
233 #endregion
234  
235 #region Private Methods
236  
237 private void Notify(string title, string message, int timeout = 10000)
238 {
3 office 239 misuNotificationIcon.BalloonTipTitle = title;
240 misuNotificationIcon.BalloonTipText = message;
1 office 241 // the timeout parameter is not used for Windows Vista and up
3 office 242 misuNotificationIcon.ShowBalloonTip(timeout);
1 office 243 }
244  
245 #endregion
246 }
247 }