newgoldenman
سه شنبه 01 بهمن 1387, 16:54 عصر
سلام به همگي دوستان
راستش خيلي گشتم كه بتونم براي برنامم، يدونه ShortCut بسازم، كه از هر جايي توي ويندوز اون كليد زده شد، برنامه ي من برام يه كاري انجام بده.
در نهايت فهميدم كه بايد Keybord رو Hook كنم! پس از گشت و گذارهايي طولاني، يه نمونه پيدا كردم كه كار ميكرد خودش، ولي توي برنامه ي من اين error رو ميده:
A callback was made on a garbage collected delegate of type 'PersianDate!GlobalHookKeyBoard.globalKeyboardHook +keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
اين از كلاس Hook كردن كه من استفاده كردم:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace GlobalHookKeyBoard
{
/// <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
}
}
اين هم روشي كه من ازش استفاده كردم توي كلاس فرم برنامم،عيناً همون كارهايي كه توي اون مثال codeproject ديدم.
namespace PersianDate
{
public partial class Form1 : Form
{
globalKeyboardHook myHookKeyBoard = new globalKeyboardHook();
public Form1()
{
InitializeComponent();
}
private void GlobalHookKeyBoard_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("F12 Pressed");
e.Handled = true;
}
private void Form1_Load(object sender, EventArgs e)
{
myHookKeyBoard.HookedKeys.Add(Keys.F12);
myHookKeyBoard.KeyDown += new KeyEventHandler(GlobalHookKeyBoard_KeyDown);
}
}
اين نمونه رو از توي codeproject (http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx) پيدا كردم. نمونه ي خودش كار ميكنه، ولي وقتي عيناً كارهاي اونو، توي برنامم اعمال كردم(كه نوشتم براتون) براي من اون error رو ميده.
آيا كسي ميتونه كمكم كنه در اين زمينه؟ خدايي خيلي توي Google گشتم. از اين مدل خطا، خيلي ها داشتن، روش حل هم به روش "تئوري" گفتن همه جا! ولي هيچ جا كسي يك خط كد يا يك تغيير كوچيك كه اين مشكل رو برطرف كنه، نداده...
شرمنده ميكنيد اگه مشكل منو حل كنيد دوستان.يا اينكه يه روشي يا كلاس Hook كردني كه خودتون تاحالا استفاده كرده و كار كرده براتون، به من هم معرفي كنيد.
خيلي خيلي ازتون ممنونم.
اينم لينك نمونه اي كه توي CodeProject ازش حرف زدم:
http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx
راستش خيلي گشتم كه بتونم براي برنامم، يدونه ShortCut بسازم، كه از هر جايي توي ويندوز اون كليد زده شد، برنامه ي من برام يه كاري انجام بده.
در نهايت فهميدم كه بايد Keybord رو Hook كنم! پس از گشت و گذارهايي طولاني، يه نمونه پيدا كردم كه كار ميكرد خودش، ولي توي برنامه ي من اين error رو ميده:
A callback was made on a garbage collected delegate of type 'PersianDate!GlobalHookKeyBoard.globalKeyboardHook +keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
اين از كلاس Hook كردن كه من استفاده كردم:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace GlobalHookKeyBoard
{
/// <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
}
}
اين هم روشي كه من ازش استفاده كردم توي كلاس فرم برنامم،عيناً همون كارهايي كه توي اون مثال codeproject ديدم.
namespace PersianDate
{
public partial class Form1 : Form
{
globalKeyboardHook myHookKeyBoard = new globalKeyboardHook();
public Form1()
{
InitializeComponent();
}
private void GlobalHookKeyBoard_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("F12 Pressed");
e.Handled = true;
}
private void Form1_Load(object sender, EventArgs e)
{
myHookKeyBoard.HookedKeys.Add(Keys.F12);
myHookKeyBoard.KeyDown += new KeyEventHandler(GlobalHookKeyBoard_KeyDown);
}
}
اين نمونه رو از توي codeproject (http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx) پيدا كردم. نمونه ي خودش كار ميكنه، ولي وقتي عيناً كارهاي اونو، توي برنامم اعمال كردم(كه نوشتم براتون) براي من اون error رو ميده.
آيا كسي ميتونه كمكم كنه در اين زمينه؟ خدايي خيلي توي Google گشتم. از اين مدل خطا، خيلي ها داشتن، روش حل هم به روش "تئوري" گفتن همه جا! ولي هيچ جا كسي يك خط كد يا يك تغيير كوچيك كه اين مشكل رو برطرف كنه، نداده...
شرمنده ميكنيد اگه مشكل منو حل كنيد دوستان.يا اينكه يه روشي يا كلاس Hook كردني كه خودتون تاحالا استفاده كرده و كار كرده براتون، به من هم معرفي كنيد.
خيلي خيلي ازتون ممنونم.
اينم لينك نمونه اي كه توي CodeProject ازش حرف زدم:
http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx