In the past I used a "Finite State Machine" to follow a sequence of keystrokes to completion, but I don't think it's effective and I was wondering how you guys would implement this:

(I have the keyboard & mouse hook lib worked out)

When a sequence of events (keystrokes & a mouse-click) occur I need to do something while the mouse button is held down. When I used the FSM it was complicated and somewhat hard to debug.

Events = ctrl + shift + lmb down ... lmb up

lmb up ends the sequence.

any ideas?

Edited 5 Years Ago by pseudorandom21: n/a

In the past I used a "Finite State Machine" to follow a sequence of keystrokes to completion, but I don't think it's effective and I was wondering how you guys would implement this:

(I have the keyboard & mouse hook lib worked out)

When a sequence of events (keystrokes & a mouse-click) occur I need to do something while the mouse button is held down. When I used the FSM it was complicated and somewhat hard to debug.

Events = ctrl + shift + lmb down ... lmb up

lmb up ends the sequence.

any ideas?

It appears that you're just looking for an unordered combination of keys, i.e., the order of CTRL and SHIFT shouldn't matter, it's only important to know if they were down when the left mouse button was pressed. Is that right?

If so, then I would agree that a state machine isn't the best way to handle this--they're fine for ordered keystrokes, but as soon as order doesn't matter, you end up with a whole mess of states to deal with every possible order the keys could be pressed. Bleah.

I would track the up/down state of CTRL and SHIFT independently, and when handling to the mouse button down event, check to see if they're both pressed. If they are, then we've reached the special "do something" condition. You just need a single bool to track whether you're in the special condition.

If you're doing this in a Windows Forms application, have a look at Control.ModifierKeys; most of the work is done for you already.

Well this isn't really a sequence since it must all be happening at the same time. SOmething like this might work:

private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Shift && e.KeyCode == Keys.ControlKey)
                bKeysDown = true;
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey)
                bKeysDown = false; 
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (bKeysDown)
                DoStuff();
        }

I don't remember exactly how key modifiers work since I haven't used them in a while. Might take some tweaking to get the ctrl+shift combo captured.

Edited 5 Years Ago by skatamatic: n/a

Hm, does this capture key-strokes outside of the application? That's what I'm using a global low-level keyboard hook for (or was). The library I have been using was acting funny from the start, and it just isn't worth the hassle. I think I'm going to re-write the application (it's rather trivial) using C++/CLI because then I don't have to use a buggy library, it will be easy to write a simple C hook procedure and I can still use my WinForms GUI stuff.

Getting a global windows message hook is not very trivial in C#. This is because in order to capture every proc's messages, you must inject into every procs address space. With a native language this wouldnt be so bad, but since .Net languages require a CLI to run, that would also have to be injected into every proc. (The CLI is by no means lightweight).

Here's some links to check out:
Global Hooks In C#
A class to hook other procs winproc's -> Upon further reading, I am not sure if this is global
More global hooks
Hope this helps!

Edited 5 Years Ago by skatamatic: n/a

Getting a global windows message hook is not very trivial in C#. This is because in order to capture every proc's messages, you must inject into every procs address space. With a native language this wouldnt be so bad, but since .Net languages require a CLI to run, that would also have to be injected into every proc. (The CLI is by no means lightweight).

Here's some links to check out:
Global Hooks In C#
A class to hook other procs winproc's -> Upon further reading, I am not sure if this is global
More global hooks
Hope this helps!

I've written them before, more than a couple times actually lol.

I've written them before, more than a couple times actually lol.

You wrote a global hook in a purely .Net platform and are confused as to how to capture a combination of inputs? That seems strange...lol. The former is much more involved than the latter.

You wrote a global hook in a purely .Net platform and are confused as to how to capture a combination of inputs? That seems strange...lol. The former is much more involved than the latter.

Well I was wondering about a better way to do it, the logic gets all confusing using the FSM :(

Well I was wondering about a better way to do it, the logic gets all confusing using the FSM :(

The state machine is definitely overkill. I don't have code for you since you're using a custom keystroke detector, but the general idea still works:

  • Keep track of the SHIFT key up/down state independently of anything else (e.g., in something like bool shiftDown ).
  • Do the same for the CTRL key.
  • When a "left mouse button down" event comes in, check the SHIFT and CTRL state variables. If both are down, you have a CTRL+SHIFT+LMB event; go ahead and set your "do something special" state variable (or whatever you're doing when this happens).
  • When a "left mouse button up" event comes in, clear your "do something special" state variable (or whatever)--normally it shouldn't matter what the shift keys are or whether you are actually in that state when the LMB up event comes in.
This article has been dead for over six months. Start a new discussion instead.