我试图在表单不是当前活动应用程序时检测
Print Screen
按钮的按下。如何实现这一点,如果可能的话?如果您遇到了系统钩子的问题,这里有一个现成的解决方案(基于http://www.dreamincode.net/forums/topic/180436-global-hotkeys/):
在您的项目中定义静态类:
public static class Constants
{
//windows message id for hotkey
public const int WM_HOTKEY_MSG_ID = 0x0312;
}
在您的项目中定义类:
public class KeyHandler
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private int key;
private IntPtr hWnd;
private int id;
public KeyHandler(Keys key, Form form)
{
this.key = (int)key;
this.hWnd = form.Handle;
id = this.GetHashCode();
}
public override int GetHashCode()
{
return key ^ hWnd.ToInt32();
}
public bool Register()
{
return RegisterHotKey(hWnd, id, 0, key);
}
public bool Unregiser()
{
return UnregisterHotKey(hWnd, id);
}
}
添加 using:
using System.Windows.Forms;
using System.Runtime.InteropServices;
现在,在您的表单中添加字段:
private KeyHandler ghk;
并且在 Form 构造函数中:
ghk = new KeyHandler(Keys.PrintScreen, this);
ghk.Register();
将这两种方法添加到你的表单中:
private void HandleHotkey()
{
// Do stuff...
}
protected override void WndProc(ref Message m)
{
if (m.Msg == Constants.WM_HOTKEY_MSG_ID)
HandleHotkey();
base.WndProc(ref m);
}
HandleHotkey是您的按钮按下处理程序。您可以通过在此处传递不同的参数来更改按钮:ghk = new KeyHandler(Keys.PrintScreen, this);
现在,即使没有焦点,您的程序也会对按钮输入作出反应。
GetAsyncKeyState()
可以作为设置 Windows Hook 的完全可接受的替代方式。GetAsyncKeyState
的简单演示:
[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(int vKey);
private static readonly int VK_SNAPSHOT = 0x2C; //This is the print-screen key.
//Assume the timer is setup with Interval = 16 (corresponds to ~60FPS).
private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
private void timer1_Tick(object sender, EventArgs e)
{
short keyState = GetAsyncKeyState(VK_SNAPSHOT);
//Check if the MSB is set. If so, then the key is pressed.
bool prntScrnIsPressed = ((keyState >> 15) & 0x0001) == 0x0001;
//Check if the LSB is set. If so, then the key was pressed since
//the last call to GetAsyncKeyState
bool unprocessedPress = ((keyState >> 0) & 0x0001) == 0x0001;
if (prntScrnIsPressed)
{
//TODO Execute client code...
}
if (unprocessedPress)
{
//TODO Execute client code...
}
}