using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
#region " Instructions "
// Go to page:
// Project > Properties > Debug
//
// Then uncheck the option:
// "Enable the Visual Studio Hosting Process"
#endregion
#region " Imports "
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
#region " MouseHook "
/// <summary>
/// A low level mouse hook that processes mouse input events.
/// </summary>
internal sealed class MouseHook : IDisposable
{
#region " P/Invoke "
protected sealed class NativeMethods
{
#region " Methods "
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowsHookEx(HookType idHook, LowLevelMouseProcDelegate lpfn, IntPtr hInstance, uint threadId);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern bool UnhookWindowsHookEx(IntPtr idHook);
#endregion
#region " Enumerations "
public enum WindowsMessages : uint
{
WMlButtonDown = 0x201u
}
public enum HookType : uint
{
WHMouseLL = 14u
}
[Flags()]
public enum MsllHookStructFlags : int
{
LlmhfInjected = 1,
LlmhfLowerILInjected = 2
}
#endregion
#region " Delegates "
public delegate int LowLevelMouseProcDelegate(int nCode, NativeMethods.WindowsMessages wParam, IntPtr lParam);
#endregion
}
#endregion
#region " Properties "
/// <summary>
/// Handle to the hook procedure.
/// </summary>
private IntPtr MouseHook { get; set; }
/// <summary>
/// The mouse hook delegate.
/// </summary>
private NativeMethods.LowLevelMouseProcDelegate MouseHookDelegate { get; set; }
#endregion
#region " Events "
/// <summary>
/// Occurs when the mouse left button is pressed.
/// </summary>
public event MouseLeftDownEventHandler MouseLeftDown;
public delegate void MouseLeftDownEventHandler(object sender);
#endregion
#region " Constructors "
/// <summary>
/// Initializes a new instance of the <see cref="MouseHook"/> class.
/// </summary>
/// <param name="Install">
/// If set to <c>true</c>, the Hook starts initialized for this <see cref="MouseHook"/> instance.
/// </param>
public MouseHook(bool install = false)
{
if (install) {
this.Install();
}
}
#endregion
#region " Public Methods "
/// <summary>
/// Installs the Mouse Hook, then start processing messages to fire events.
/// </summary>
public void Install()
{
if (this.IsVisualStudioHostingProcessEnabled()) {
throw new Exception
("Visual Studio Hosting Process should be deactivated."); return;
}
this.MouseHookDelegate = new NativeMethods
.LowLevelMouseProcDelegate(LowLevelMouseProc
);
try {
this.MouseHook = NativeMethods
.SetWindowsHookEx(NativeMethods
.HookType.WHMouseLL,
this.MouseHookDelegate,
new IntPtr
(Marshal
.GetHINSTANCE(Assembly
.GetExecutingAssembly.GetModules()(0)).ToInt32),
0);
} catch (Exception ex) {
throw;
}
}
/// <summary>
/// Uninstalls the Mouse Hook and free all resources, then stop processing messages to fire events.
/// </summary>
public void Uninstall()
{
this.Finalize();
}
#endregion
#region " Private Methods "
private bool IsVisualStudioHostingProcessEnabled()
{
return AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe", StringComparison.OrdinalIgnoreCase);
}
private int LowLevelMouseProc(int nCode, NativeMethods.WindowsMessages wParam, IntPtr lParam)
{
if (nCode == 0) {
switch (wParam) {
case NativeMethods.WindowsMessages.WMlButtonDown:
if (MouseLeftDown != null) {
MouseLeftDown(this);
}
break;
default:
// Do Nothing
break; // TODO: might not be correct. Was : Exit Select
break;
}
return Convert
.ToInt32(NativeMethods
.CallNextHookEx(MouseHook, nCode,
new IntPtr
(wParam
), lParam
));
} else if (nCode < 0) {
return Convert
.ToInt32(NativeMethods
.CallNextHookEx(MouseHook, nCode,
new IntPtr
(wParam
), lParam
));
// nCode > 0
} else {
return Convert
.ToInt32(NativeMethods
.CallNextHookEx(MouseHook, nCode,
new IntPtr
(wParam
), lParam
));
}
}
#endregion
#region "IDisposable Support"
/// <summary>
/// Flag to detect redundant calls at <see cref="Dispose"/> method.
/// </summary>
private bool disposedValue;
protected void Dispose(bool disposing)
{
if (!this.disposedValue) {
// Dispose managed state (managed objects).
if (disposing) {
// Free unmanaged resources (unmanaged objects).
} else {
NativeMethods.UnhookWindowsHookEx(this.MouseHook);
}
}
this.disposedValue = true;
}
protected override void Finalize()
{
// Do not change this code. Put cleanup code in method: Dispose(ByVal disposing As Boolean)
this.Dispose(disposing: false);
base.Finalize();
}
private void Dispose()
{
// Do not change this code. Put cleanup code in method: Dispose(ByVal disposing As Boolean)
this.Dispose(disposing: true);
GC.SuppressFinalize(obj: this);
}
#endregion
}
#endregion
//=======================================================
//Service provided by Telerik (www.telerik.com)
//Conversion powered by NRefactory.
//Twitter: @telerik
//Facebook: facebook.com/telerik
//=======================================================