misu – Rev 8
?pathlinks?
using System;
using System.ComponentModel;
using System.Configuration;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks.Dataflow;
using System.Windows.Forms;
using AutoUpdaterDotNET;
using Gma.System.MouseKeyHook;
using misu.Properties;
namespace misu
{
public partial class MisuMainForm : Form
{
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
private BufferBlock<KeyEventArgs> PressedKeysBufferBlock { get; }
private IKeyboardMouseEvents GlobalHook { get; }
private AboutForm AboutForm { get; set; }
private BindKeyForm BindKeyForm { get; set; }
private volatile bool _lock;
#endregion
#region Constructors, Destructors and Finalizers
public MisuMainForm()
{
InitializeComponent();
AutoUpdater.Start("http://misu.grimore.org/update/update.xml");
// Upgrade settings if required.
if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
{
Settings.Default.Upgrade();
}
// Bind to settings changed event.
Settings.Default.SettingsLoaded += Default_SettingsLoaded;
Settings.Default.SettingsSaving += Default_SettingsSaving;
Settings.Default.PropertyChanged += Default_PropertyChanged;
PressedKeysBufferBlock = new BufferBlock<KeyEventArgs>(new DataflowBlockOptions {EnsureOrdered = true});
// Hook to global events.
GlobalHook = Hook.GlobalEvents();
// Bind to receive keyboard presses.
GlobalHook.KeyDown += GlobalHook_KeyDown;
GlobalHook.KeyUp += GlobalHook_KeyUp;
GlobalHook.MouseUpExt += GlobalHook_BlockMouse;
GlobalHook.MouseDragFinishedExt += GlobalHook_BlockMouse;
GlobalHook.MouseDragStartedExt += GlobalHook_BlockMouse;
GlobalHook.MouseWheelExt += GlobalHook_BlockMouse;
GlobalHook.MouseMoveExt += GlobalHook_BlockMouse;
GlobalHook.MouseDownExt += GlobalHook_BlockMouse;
if (Settings.Default.Keys != null)
{
Notify("Shortcut is bound.",
$"Press {string.Join(" ", Settings.Default.Keys.OfType<string>())} to toggle locking.");
}
}
#endregion
#region Event Handlers
private static void Default_SettingsSaving(object sender, CancelEventArgs e)
{
}
private static void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Settings.Default.Save();
}
private static void Default_SettingsLoaded(object sender, SettingsLoadedEventArgs e)
{
}
private void GlobalHook_BlockMouse(object sender, MouseEventExtArgs e)
{
// Do not perform any operations while the binding form is visible.
if (BindKeyForm != null && BindKeyForm.Visible)
{
return;
}
if (_lock && Settings.Default.Mouse)
{
e.Handled = true;
}
}
private void GlobalHook_KeyUp(object sender, KeyEventArgs e)
{
// Do not perform any operations while the binding form is visible.
if (BindKeyForm != null && BindKeyForm.Visible)
{
return;
}
if (!PressedKeysBufferBlock.TryReceiveAll(out var keys))
{
return;
}
if (Settings.Default.Keys == null)
{
return;
}
if (!Settings.Default.Keys.OfType<string>().SequenceEqual(keys.Select(key => key.KeyCode.ToString())))
{
return;
}
_lock = !_lock;
// Lock the cursor in position.
switch (_lock)
{
case true:
Cursor.Clip = new Rectangle(Cursor.Position, new Size(1, 1));
break;
default:
Cursor.Clip = Screen.PrimaryScreen.Bounds;
break;
}
// Dismiss the current keypress to avoid typing the key.
e.Handled = true;
e.SuppressKeyPress = true;
Notify($"Mouse and Keyboard are {(_lock ? "locked" : "unlocked")}.",
$"Press {string.Join(" ", Settings.Default.Keys.OfType<string>())} to toggle mouse and keyboard locking.");
}
private async void GlobalHook_KeyDown(object sender, KeyEventArgs e)
{
// Do not perform any operations while the binding form is visible.
if (BindKeyForm != null && BindKeyForm.Visible)
{
return;
}
if (_lock && Settings.Default.Keyboard)
{
e.SuppressKeyPress = true;
e.Handled = true;
}
await PressedKeysBufferBlock.SendAsync(e);
}
private void OnContextMenuAboutClick(object sender, EventArgs e)
{
// Show the about form.
AboutForm = new AboutForm();
AboutForm.Show();
}
private void OnContextMenuQuitClick(object sender, EventArgs e)
{
Close();
Environment.Exit(0);
}
private void OnContextMenuLaunchOnBootChanged(object sender, EventArgs e)
{
Settings.Default.LaunchOnBoot = ((ToolStripMenuItem) sender).Checked;
Utilities.LaunchOnBootSet(Settings.Default.LaunchOnBoot);
}
private void OnContextMenuBindKeyClick(object sender, EventArgs e)
{
BindKeyForm = new BindKeyForm(GlobalHook);
BindKeyForm.KeyBound += BindKeyForm_KeyBound;
BindKeyForm.Closing += BindKeyForm_Closing;
BindKeyForm.Show();
}
private void BindKeyForm_Closing(object sender, CancelEventArgs e)
{
BindKeyForm.KeyBound -= BindKeyForm_KeyBound;
BindKeyForm.Closing -= BindKeyForm_Closing;
}
private async void BindKeyForm_KeyBound(object sender, KeyBoundEventArgs e)
{
Notify("Shortcut key is bound.",
$"Press {string.Join(" ", Settings.Default.Keys.OfType<string>())} to toggle between locked and unlocked keyboard and mouse.");
}
private void KeyboardToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var item = (ToolStripMenuItem) sender;
Settings.Default.Keyboard = item.Checked;
}
private void MouseToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var item = (ToolStripMenuItem) sender;
Settings.Default.Mouse = item.Checked;
}
private void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
// Apply the settings to the menu items.
launchOnBootToolStripMenuItem.Checked = Settings.Default.LaunchOnBoot;
Utilities.LaunchOnBootSet(Settings.Default.LaunchOnBoot);
mouseToolStripMenuItem.Checked = Settings.Default.Mouse;
keyboardToolStripMenuItem.Checked = Settings.Default.Keyboard;
}
#endregion
#region Private Methods
private void Notify(string title, string message, int timeout = 10000)
{
misuNotificationIcon.BalloonTipTitle = title;
misuNotificationIcon.BalloonTipText = message;
// the timeout parameter is not used for Windows Vista and up
misuNotificationIcon.ShowBalloonTip(timeout);
}
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.