views:

56

answers:

3

I'd like to retrieve the state of the Ctrl keys in a place where I don't have a form.

Normally to get a key state I'd use Control_KeyDown / KeyUp events. However, the code that needs to know whether Ctrl is pressed is outside any form. There is a form displayed, but the code is supposed not to depend on that form but finding the key state on its own.

Surely there is a way to do that, only I don't succeed to find it on google.

Note that although the code doesn't "have" a form available, its still a WinForms application, so maybe the framework provides some class/object for me to achieve that goal.

Background:

During the application startup phase, I want one step to behave differntly if the Ctrl key is being pressed in that moment. The startup phase displays a splash screen, but the code for the startup isn't aware of that. Instead it reports progress to a callback, and that callback updates the splash screen.

If I use the splash screen for fetching the KeyDown event, I make the startup code depend on that splash screen, which introduces a circular dependency. I want to keep the freedom to remove the splash screen and replace by something different.

+2  A: 

I've done exactly that just recently:

    static class NativeMethods
    {
        public static bool IsControlKeyDown()
        {
            return (GetKeyState(VK_CONTROL) & KEY_PRESSED) != 0;
        }
        private const int KEY_PRESSED = 0x8000;
        private const int VK_CONTROL = 0x11;
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern short GetKeyState(int key);
    }

To test the code, create a new Console Application and use the following main method:

    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine(NativeMethods.IsControlKeyDown());
            System.Threading.Thread.Sleep(100);
        }
    }
testalino
Thanks, looks good. Is there a non-native way as well?
chiccodoro
I couldn't find any non-native solutions a couple of days ago.
testalino
@testalino: I've copied and pasted your code, and added a call to IsControlKeyDown(), but it returned false even if I press both Ctrl keys.
chiccodoro
@chiccodoro I've created a test application and it works here, I'll edit my answer with the test code.
testalino
@testalino: That's probably my fault! The event loop only starts after the initialization, what's not recommended and probably why I don't get the event...
chiccodoro
My code is not event based - it is poll based. You need to check whether the key is pressed. If you need events, you must create a keyboard hook.
testalino
@testalino: Then I don't know why it doesn't work for me...
chiccodoro
@chiccodoro so you created an empty console application in Visual Studio with the test code i provided and when you press ctrl while the code runs you don't see the value changing to true? I can assure you that this code works.
testalino
@testalino: No, I haven't tried this, I only tried it in my application. I believe you that it'll work in a empty console application, but that doesn't help me. That's why I say I don't understand why it doesn't work for me.
chiccodoro
A: 

Can't you just catch the Ctrl being pressed on the form that is displayed, since it seems that this form is also a part of the appication, and relay the click to the "formless" part of the code using an event that the form can invoke?

I might misunderstand what you are after here, but it seems like an option at least.

Øyvind Bråthen
Yes, I'm thinking about this approach too. However in my case it introduces a dependency which I'd rather prevent (see update on my question).
chiccodoro
+3  A: 

You could use the static method on Control called ModifierKeys

Control.ModifierKeys on MSDN

eg:

if (Control.ModifierKeys == Keys.Control)
{
    //...
}
Pondidum
I tried this a couple of days ago and it didn't work, because at this stage (initialization with splash screen) the event loop wasn't running yet. (See also comment to testalino). Now the splash screen runs in a message loop, and the solution works.
chiccodoro