努力在键盘挂钩内使用秒表
Struggling to use stopwatch within keyboard hook
我在这里待了一整天,但几乎不问任何问题;你们太好了我觉得不值得(:
我有一段时间前制作的这个应用程序,最近我又开始工作了。
它记录了一个鼠标点击宏并重播它,它非常适合我使用它,但我开始觉得也需要添加键盘笔画。
所以今天我添加了这个记录键盘笔划的功能,我可以捕捉笔划并显示它们,但我的问题是我想要 运行 一个秒表,它从按键开始到结束键释放。
此外,我应该确保我按下的键和我释放的键是相同的我希望这真的能做到。
我尝试了很多不同的方法来 运行 那里的秒表但是关于这段代码的一切都让我不舒服。按键的侦听器应该将 keyup 和 keydown 分开,但是我该如何使用计时器呢?
一定要全力以赴
问题是,我尝试全局实例化秒表(Form1 范围)应该:
- 运行方法1次,进入keydown状态,启动定时器,
- 然后 运行 再一次,转到 keyup 并停止计时器。
我认为这应该可行,但我想我有范围问题,考虑到计时器永远不会给出准确的值。 (按 3 秒给出 1,然后快速按下和释放给出 3)我检查了定时器是否在正确的时间启动和停止,我认为是这样。
之后我尝试在 hook 方法中实例化它,但由于它必须 运行 两次才能很好地记录上下,计时器被重置。 (这样写我想也许我应该检查它是否是 运行ning 而不是实例化它)
我并不着急,真的不是在寻找解决此问题的快速方法,而是在寻找实现此功能的最佳方法并尝试使此程序更整洁。我觉得这已经很遥远了,我应该使用 lParam,这样会更容易。
我在那里存储了按键信息,尽管我认为 lParam 实际上可以更有效地执行此操作,但无法理解它是如何工作的
public class KeyPressHelper
{
public Keys currentPressedKeyCode;
public Keys currentReleasedKeyCode;
public Keys previousPressedKeyCode;
public KeyPressHelper()
{
currentPressedKeyCode = new Keys();
currentReleasedKeyCode = new Keys();
previousPressedKeyCode = new Keys();
}
}
这是钩子函数,大部分只是msdn提供的示例代码,我添加了keyup的条件,但我真的不确定这是正确的方法。
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
keyStrokeTimer.Start(); // global Stopwatch
//keypresshelper kph1
kph1.previousPressedKeyCode = 0;
kph1.currentReleasedKeyCode = 0;
int vkCode = Marshal.ReadInt32(lParam);
kph1.currentPressedKeyCode = (Keys)vkCode;
kphList.Add(kph1);
}
if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
//assign kph2.previousPressedkey to kph1.currentPressedKey
kph2.previousPressedKeyCode
= kphList.Find(k => k.Equals(kph1)).currentPressedKeyCode;
kph2.currentPressedKeyCode = 0;
int vkCode = Marshal.ReadInt32(lParam);
kph2.currentReleasedKeyCode = (Keys)vkCode;
//if they're identical well this is nice.
if (kph2.previousPressedKeyCode == kph2.currentReleasedKeyCode)
{
keyStrokeTimer.Stop();
MessageBox.Show("" + keyStrokeTimer.ElapsedMilliseconds) //goal.
}
else
{
keyStrokeTimer.Stop();
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
来看看Stopwatch
classdocumentation
By default, the elapsed time value of a Stopwatch instance equals the total of all measured time intervals. Each call to Start begins counting at the cumulative elapsed time; each call to Stop ends the current interval measurement and freezes the cumulative elapsed time value. Use the Reset method to clear the cumulative elapsed time in an existing Stopwatch instance.
如您所见,您使用它的方式,您的 Stopwatch
正在累积总时间。如果要测量两个事件之间的时间,请使用 Restart 方法而不是 Start
.
我在这里待了一整天,但几乎不问任何问题;你们太好了我觉得不值得(:
我有一段时间前制作的这个应用程序,最近我又开始工作了。 它记录了一个鼠标点击宏并重播它,它非常适合我使用它,但我开始觉得也需要添加键盘笔画。
所以今天我添加了这个记录键盘笔划的功能,我可以捕捉笔划并显示它们,但我的问题是我想要 运行 一个秒表,它从按键开始到结束键释放。 此外,我应该确保我按下的键和我释放的键是相同的我希望这真的能做到。
我尝试了很多不同的方法来 运行 那里的秒表但是关于这段代码的一切都让我不舒服。按键的侦听器应该将 keyup 和 keydown 分开,但是我该如何使用计时器呢?
一定要全力以赴
问题是,我尝试全局实例化秒表(Form1 范围)应该:
- 运行方法1次,进入keydown状态,启动定时器,
- 然后 运行 再一次,转到 keyup 并停止计时器。
我认为这应该可行,但我想我有范围问题,考虑到计时器永远不会给出准确的值。 (按 3 秒给出 1,然后快速按下和释放给出 3)我检查了定时器是否在正确的时间启动和停止,我认为是这样。
之后我尝试在 hook 方法中实例化它,但由于它必须 运行 两次才能很好地记录上下,计时器被重置。 (这样写我想也许我应该检查它是否是 运行ning 而不是实例化它)
我并不着急,真的不是在寻找解决此问题的快速方法,而是在寻找实现此功能的最佳方法并尝试使此程序更整洁。我觉得这已经很遥远了,我应该使用 lParam,这样会更容易。
我在那里存储了按键信息,尽管我认为 lParam 实际上可以更有效地执行此操作,但无法理解它是如何工作的
public class KeyPressHelper
{
public Keys currentPressedKeyCode;
public Keys currentReleasedKeyCode;
public Keys previousPressedKeyCode;
public KeyPressHelper()
{
currentPressedKeyCode = new Keys();
currentReleasedKeyCode = new Keys();
previousPressedKeyCode = new Keys();
}
}
这是钩子函数,大部分只是msdn提供的示例代码,我添加了keyup的条件,但我真的不确定这是正确的方法。
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
keyStrokeTimer.Start(); // global Stopwatch
//keypresshelper kph1
kph1.previousPressedKeyCode = 0;
kph1.currentReleasedKeyCode = 0;
int vkCode = Marshal.ReadInt32(lParam);
kph1.currentPressedKeyCode = (Keys)vkCode;
kphList.Add(kph1);
}
if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
//assign kph2.previousPressedkey to kph1.currentPressedKey
kph2.previousPressedKeyCode
= kphList.Find(k => k.Equals(kph1)).currentPressedKeyCode;
kph2.currentPressedKeyCode = 0;
int vkCode = Marshal.ReadInt32(lParam);
kph2.currentReleasedKeyCode = (Keys)vkCode;
//if they're identical well this is nice.
if (kph2.previousPressedKeyCode == kph2.currentReleasedKeyCode)
{
keyStrokeTimer.Stop();
MessageBox.Show("" + keyStrokeTimer.ElapsedMilliseconds) //goal.
}
else
{
keyStrokeTimer.Stop();
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
来看看Stopwatch
classdocumentation
By default, the elapsed time value of a Stopwatch instance equals the total of all measured time intervals. Each call to Start begins counting at the cumulative elapsed time; each call to Stop ends the current interval measurement and freezes the cumulative elapsed time value. Use the Reset method to clear the cumulative elapsed time in an existing Stopwatch instance.
如您所见,您使用它的方式,您的 Stopwatch
正在累积总时间。如果要测量两个事件之间的时间,请使用 Restart 方法而不是 Start
.