努力在键盘钩中使用秒表

本文关键字:键盘 努力 | 更新日期: 2023-09-27 18:31:32

我整天都在这里度过,但几乎从不问任何问题;你们太好了,我觉得不值得(:

有一段时间前制作的这个应用程序,我最近又开始工作了。它记录了一个鼠标单击宏并重播它,它非常适合我的使用,但我开始觉得也需要添加键盘笔划。

所以今天我添加了这个记录键盘笔划的功能,我可以捕捉笔画并显示它们,但我的问题是我想运行一个从按键开始并在按键释放时结束的秒表。此外,我应该确保我按下的键和我释放的键是相同的,我希望这实际上可以做到。

我尝试了很多不同的方法来运行秒表,但是关于这段代码的所有内容都让我感到不舒服。键的侦听器应该将键控和键降分开,但我如何使用计时器呢?

无论如何,请全力以赴。


问题是,我尝试全局实例化秒表(Form1 范围),它应该:

  1. 运行方法1次,进入键下条件,启动定时器,
  2. 然后运行另一个时间,转到 Keyup 并停止计时器。

我认为这应该有效,但我想我有范围问题,因为计时器从未给出准确的值。(按 3 秒得到 1,之后按下并快速松开得到 3)我检查了计时器是否在正确的时间启动和停止,我认为确实如此。

之后,我尝试在钩子方法中实例化它,但由于它必须运行两次才能很好地记录上下,因此计时器被重置。(这样写,我想也许我应该检查它是否正在运行,如果它正在运行,则不要实例化它)

我并不着急,真的不是在寻找解决此问题的快速方法,而是寻找实现此功能的最佳方法,并尝试使该程序更整洁。我有一种感觉,这很离谱,我应该使用 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类文档

默认情况下,秒表实例的已用时间值等于所有测量时间间隔的总和。对"开始"屏幕的每个调用都从累计运行时间开始计数;每次调用 Stop 都会结束当前间隔测量并冻结累计已用时间值。使用 Reset 方法清除现有秒表实例中的累计运行时间。

如您所见,您使用它的方式,您的Stopwatch正在积累总时间。如果要测量两个事件之间的时间,请使用重新启动方法而不是Start