using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApplication1
{
[Flags]
public enum SendMessageTimeoutFlags : uint
{
SMTO_NORMAL = 0x0,
SMTO_BLOCK = 0x1,
SMTO_ABORTIFHUNG = 0x2,
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
}
public partial class Form1 : Form
{
public delegate int HookProc(int code, IntPtr wparam, IntPtr lparam);
static int hHook = 0;
static int mHook = 0;
IntPtr windowHandle;
uint processHandle;
int WH_MOUSE = 7;
int WH_KEYBOARD = 2;
static int HC_ACTION = 0;
static int VK_CONTROL = 11;
//This is the Import for the SetWindowsHookEx function.
//Use this function to install a thread-specific hook.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
//This is the Import for the UnhookWindowsHookEx function.
//Call this function to uninstall the hook.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
//This is the Import for the CallNextHookEx function.
//Use this function to pass the hook information to the next hook procedure in chain.
[DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern short GetAsyncKeyState(int vkey);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int GetLastError();
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr FindWindow(string classname, string windowName);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SendMessage(IntPtr hWnd,uint Msg,IntPtr wParam,IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
UIntPtr wParam,
IntPtr lParam,
SendMessageTimeoutFlags fuFlags,
uint uTimeout,
out UIntPtr lpdwResult);
HookProc MouseHookProcDel;
HookProc KeyBoardHookProcDel;
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
//Declare the wrapper managed MouseHookStruct class.
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
//to marshal to lparam of keyboard hook into a manage type
[StructLayout(LayoutKind.Sequential)]
public class KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public uint dwExtraInfo;
}
public Form1()
{
InitializeComponent();
}
public static int MouseHookProcedure(int code, IntPtr wparam, IntPtr lparam)
{
MouseHookStruct mouse = (MouseHookStruct)Marshal.PtrToStructure(lparam, typeof(MouseHookStruct));
if(code == 0)
{
//Create a string variable that shows the current mouse coordinates.
String strCaption = "x = " +
mouse.pt.x.ToString("d") +
" y = " +
mouse.pt.y.ToString("d");
//You must get the active form because it is a static function.
Form tempForm = Form.ActiveForm;
//Set the caption of the form.
tempForm.Text = strCaption;
return CallNextHookEx(hHook, code, wparam, lparam);
}
else
//calls the next hook with same message and parameters
return CallNextHookEx(hHook, code, wparam, lparam);
}
public static int KeyBoardProcedure(int code, IntPtr wparam, IntPtr lparam)
{
//KBDLLHOOKSTRUCT's structure is copied as it is from msdn to support marshaling
KBDLLHOOKSTRUCT pkbhs = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lparam, typeof(KBDLLHOOKSTRUCT));
int bControlKeyDown = 0 ;
switch (code)
{
//0 refers to HC_ACTION
case 0:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState(VK_CONTROL) >> ((sizeof(short) * 8) - 1);
//write to logic to handle ctrl+esc or alt+tab or any other key here
//then return 1
break;
}
default:
return CallNextHookEx(mHook, code, wparam, lparam);
}
return CallNextHookEx(mHook, code, wparam, lparam);
}
private void button1_Click(object sender, EventArgs e)
{
if (hHook == 0 && mHook==0)
{
// Create an instance of HookProc.
MouseHookProcDel = new HookProc(Form1.MouseHookProcedure);
KeyBoardHookProcDel = new HookProc(Form1.KeyBoardProcedure);
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcDel,
(IntPtr)0,
AppDomain.GetCurrentThreadId());
mHook = SetWindowsHookEx(WH_KEYBOARD,
KeyBoardHookProcDel,
(IntPtr)0,
AppDomain.GetCurrentThreadId());
//If the SetWindowsHookEx function fails.
if (hHook == 0)
{
MessageBox.Show("SetWindowsHookEx Failed" + ":" + GetLastError().ToString());
return;
}
button1.Text = "UnHook Windows Hook";
}
else
{
bool ret = UnhookWindowsHookEx(hHook);
ret = UnhookWindowsHookEx(mHook);
//If the UnhookWindowsHookEx function fails.
if (ret == false)
{
MessageBox.Show("UnhookWindowsHookEx Failed");
return;
}
hHook = 0;
mHook = 0;
button1.Text = "Hook Mouse and Keyboard";
this.Text = "Mouse Hook";
}
}
private void GetActiveWindowTitle()
{
const int nChars = 256;
IntPtr handle = IntPtr.Zero;
StringBuilder Buff = new StringBuilder(nChars);
handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
MessageBox.Show(Buff.ToString());
}
return;
}
private void timer1_Tick(object sender, EventArgs e)
{
//on timer elapsed, we get the active window's title
// uncomment to use it
//GetActiveWindowTitle();
}
private void CheckWhetherProcessIsHung()
{
//easy way of doing this would be to check process.Responding attribute
//C# makes it totally easy with Process class
//edit is the class name here for Notepad
IntPtr hwnd = FindWindow("Edit", null);
UIntPtr let;
//Aborts if the process to which we are sending message fails
IntPtr result = SendMessageTimeout(hwnd, 0, (UIntPtr)0, (IntPtr)0, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 15000, out let);
//there will be error if result = 0, get last error and show it then
if (result == (IntPtr)0)
MessageBox.Show(GetLastError().ToString());
}
private void button2_Click(object sender, EventArgs e)
{
CheckWhetherProcessIsHung();
}
}
}
References:
Pinvoke.net , msdn dev center -desktop and microsoft support pages
No comments:
Post a Comment