misu – Blame information for rev 1

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 {
12 public partial class Form1 : Form
13 {
14 #region Public Enums, Properties and Fields
15  
16 public Settings Settings { get; set; }
17  
18 public Point LockedCursorPosition { get; set; }
19  
20 #endregion
21  
22 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
23  
24 private BufferBlock<KeyEventArgs> PressedKeysBufferBlock { get; }
25  
26 private IKeyboardMouseEvents GlobalHook { get; }
27  
28 private AboutForm AboutForm { get; set; }
29  
30 private BindKeyForm BindKeyForm { get; set; }
31  
32 private volatile bool _lock;
33  
34 #endregion
35  
36 #region Constructors, Destructors and Finalizers
37  
38 public Form1()
39 {
40 InitializeComponent();
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;
57  
58 // Hook to global events.
59 GlobalHook = Hook.GlobalEvents();
60  
61 // Bind to receive keyboard presses.
62 GlobalHook.KeyDown += GlobalHook_KeyDown;
63 GlobalHook.KeyUp += GlobalHook_KeyUp;
64 GlobalHook.MouseMove += GlobalHook_MouseMove;
65 }
66  
67 #endregion
68  
69 #region Event Handlers
70  
71 private void GlobalHook_MouseMove(object sender, MouseEventArgs e)
72 {
73 if (Settings.Mouse)
74 {
75 switch (_lock)
76 {
77 case true:
78 Cursor.Clip = new Rectangle(LockedCursorPosition, new Size(1, 1));
79 break;
80 default:
81 Cursor.Clip = Screen.PrimaryScreen.Bounds;
82 break;
83 }
84 }
85 }
86  
87 private async void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
88 {
89 // Serialize the settings to the configuration file on form closing.
90 await Settings.Serialize(@"Settings.xml");
91 }
92  
93 private void GlobalHook_KeyUp(object sender, KeyEventArgs e)
94 {
95 if (Settings.Binding == null)
96 {
97 return;
98 }
99  
100 if (!PressedKeysBufferBlock.TryReceiveAll(out var keys))
101 {
102 return;
103 }
104  
105 if (Settings.Binding.Keys.SequenceContains(keys.Select(key => key.KeyCode)))
106 {
107 _lock = !_lock;
108  
109 // Save the cursor position in order to lock the mouse.
110 LockedCursorPosition = Cursor.Position;
111  
112 // Dismiss the current keypress to avoid typing the key.
113 e.Handled = true;
114 e.SuppressKeyPress = true;
115  
116 Notify($"Input is {(_lock ? "locked" : "unlocked")}", "Press the keyboard shortcut to toggle locking.");
117 }
118 }
119  
120 private async void GlobalHook_KeyDown(object sender, KeyEventArgs e)
121 {
122 if (_lock && Settings.Keyboard)
123 {
124 e.SuppressKeyPress = true;
125 e.Handled = true;
126 }
127  
128 await PressedKeysBufferBlock.SendAsync(e);
129 }
130  
131 private void OnContextMenuAboutClick(object sender, EventArgs e)
132 {
133 // Show the about form.
134 AboutForm = new AboutForm();
135 AboutForm.Show();
136 }
137  
138 private void OnContextMenuQuitClick(object sender, EventArgs e)
139 {
140 Application.Exit();
141 }
142  
143 private void OnContextMenuLaunchOnBootChanged(object sender, EventArgs e)
144 {
145 Settings.LaunchOnBoot = ((ToolStripMenuItem) sender).Checked;
146  
147 Utilities.LaunchOnBootSet(Settings.LaunchOnBoot);
148 }
149  
150 private void OnContextMenuBindKeyClick(object sender, EventArgs e)
151 {
152 BindKeyForm = new BindKeyForm(GlobalHook, Settings);
153 BindKeyForm.KeyBound += BindKeyForm_KeyBound;
154 BindKeyForm.Closing += BindKeyForm_Closing;
155 BindKeyForm.Show();
156 }
157  
158 private void BindKeyForm_Closing(object sender, CancelEventArgs e)
159 {
160 BindKeyForm.KeyBound -= BindKeyForm_KeyBound;
161 BindKeyForm.Closing -= BindKeyForm_Closing;
162 }
163  
164 private void BindKeyForm_KeyBound(object sender, KeyBoundEventArgs e)
165 {
166 Notify("Keys bound", "Press to toggle between locked and unlocked states.");
167  
168 Settings.Binding = e.Binding;
169 }
170  
171 private void KeyboardToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
172 {
173 var item = (ToolStripMenuItem) sender;
174  
175 Settings.Keyboard = item.Checked;
176 }
177  
178 private void MouseToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
179 {
180 var item = (ToolStripMenuItem) sender;
181  
182 Settings.Mouse = item.Checked;
183 }
184  
185 private void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
186 {
187 // Apply the settings to the menu items.
188 launchOnBootToolStripMenuItem.Checked = Settings.LaunchOnBoot;
189 Utilities.LaunchOnBootSet(Settings.LaunchOnBoot);
190  
191 mouseToolStripMenuItem.Checked = Settings.Mouse;
192 keyboardToolStripMenuItem.Checked = Settings.Keyboard;
193 }
194  
195 #endregion
196  
197 #region Private Methods
198  
199 private void Notify(string title, string message, int timeout = 10000)
200 {
201 notifyIcon1.BalloonTipTitle = title;
202 notifyIcon1.BalloonTipText = message;
203 // the timeout parameter is not used for Windows Vista and up
204 notifyIcon1.ShowBalloonTip(timeout);
205 }
206  
207 #endregion
208 }
209 }