0

I have implemented a keyboard hook as presented in this answer. Everything works fine except for one case. If I want to hold a key pressed for some time, thus technically remaning in the method which I'm calling, two thing happen:

  1. I remain in the method (which is good)
  2. the application records the key being held down, as independent keystrokes which are then captured by the hook.

Hook:

private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {

        const int WM_HOTKEY = 0x0312;
            switch (msg)
            {
                case WM_HOTKEY:
                    if (battleBotStatus == 0)
                    {
                        switch (wParam.ToInt32())
                        {

                            case HOTKEY_ID:
                                OnHotKeyPressed();
                                handled = true;
                                break;

                            case HOTKEY_ID9:
                                enableBattleBotKeys();
                                battleBotStatus = 1;
                                //performCombo();
                                handled = true;
                                break;
                        }
                    }
                    else
                    {
                        switch (wParam.ToInt32())
                        {

                            case BattleKey1:
                                performCombo(1);
                                handled = true;                                    
                                buttonIsPressed = false;
                                break;
                        }
                    }
                    break;
            }
        return IntPtr.Zero;
    }

PerformCombo code

private void performCombo(int n)
        {
            string simpleAction;
            Sleep(cmbDelay);
            Key k = new Key();
            switch (n) 
            {
                case 1:
                    k = Key.D1;
                    break;
                case 2:
                    k = Key.D2;
                    break;
                case 3:
                    k = Key.D3;
                    break;
                case 4:
                    k = Key.D4;
                    break;
                case 5:
                    k = Key.D5;
                    break;
                case 6:
                    k = Key.D6;
                    break;
            }
        if ((Keyboard.GetKeyStates(k) & KeyStates.Down) > 0)
            Sleep(1000);
        do
        {
            if (comboList[n - 1].Count > 0)
            {
                foreach (string action in comboList[n - 1])
                {
                    simpleAction = action.Split('~')[0];
                    if (simpleAction.Length == 1)
                    {
                        dkeyinput(simpleAction, gamePid, 500);
                        Sleep(cmbDelay);
                    }
                    else
                    {
                        if (simpleAction == "LeftClick")
                        {
                            dmouseclick("left", 300);
                            Sleep(cmbDelay);
                        }
                        else if (simpleAction == "RightClick")
                        {
                            dmouseclick("right", 300);
                            Sleep(cmbDelay);
                        }
                        else if (simpleAction == "Space")
                        {
                            dkeyinput("\"{SPACE}\"", gamePid);
                            Sleep(cmbDelay);
                        }
                        else if (simpleAction.Contains("&"))
                        {
                            dkeyinput2(simpleAction, cmbDelay);
                            Sleep(cmbDelay);
                        }
                    }
                }
            }
        }
        while ((Keyboard.GetKeyStates(k) & KeyStates.Down) > 0);


    }  

I have tried to use flags, but they didn't seem to work either. When inspecting the using the debugger, I've noticed that it constantly goes onto the handler and continously perfoms the action for the BattleKey1 case, even after releasing the key.

Community
  • 1
  • 1
Bogdan Molinger
  • 251
  • 1
  • 6
  • 19
  • I don't know why you using sleep... but that's the case. Usually if you want to combine some input events (multiple key/mouse clicks) you need to store a value and start time, and check em and compare with a new one based on current time. This will help you to combine few events to an "event stream" (combo). – Shakra Feb 27 '17 at 12:26
  • @Shakra I don't know how to apply event streams on this kind of problem. The sleeps are there only to create a delay between actions. If I take them out, only very operations are processed – Bogdan Molinger Feb 27 '17 at 12:40

1 Answers1

0

As a fast workaround, if you know Maximum combo time: Add new DateTime variable befor do-while:

var comboStart = DateTime.Now;
do{...}while

Add time check at do-while:

while ((Keyboard.GetKeyStates(k) & KeyStates.Down) > 0 ||
(DateTime.Now - comboStart).TotalSeconds > maxComboTimeInSeconds);

This wouldn't delete application freezes (you need to run in Async this methods to do so), but will make a solid case for do-while to break it, if you press some key for a long time.

Shakra
  • 501
  • 2
  • 8