misu – Blame information for rev 6

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