Hey,

I currently have a program that runs a loop with some mouse clicks in an internet browser to do some menial tasks I do not want to do. But I have to specify the number I want it to do before hand, and since the mouse clicks are too fast, I cant stop debugging either or any other form of stopping it.

My question is, how do I stop the program with the keyboard while the form is not selected? If you could provide some code or just a good explanation, that would be great.

~Pengwin

If you want to catch keyboard events without your app having focus i think you will need to use a global keyboard hook. Check out this link to get you started.

if all you need is 1 key, then a simple hotkey would serve very nicely.

First Import the native methods you need.

//API Imports
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(
            IntPtr hWnd, // handle to window    
            int id, // hot key identifier    
            KeyModifiers fsModifiers, // key-modifier options    
            Keys vk    // virtual-key code    
            );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(
            IntPtr hWnd, // handle to window    
            int id      // hot key identifier    
            );

Create a enum to easily understand what key modifiers are used and a constant to hold the ID of the hotkey.

//const int HOTKEY_ID = 31197;    //any number to be used as an id within this app
        const int WM_HOTKEY = 0x0312;

        public enum KeyModifiers        //enum to call 3rd parameter of RegisterHotKey easily
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
            Windows = 8
        }

so we just create the hotkey bind on load, or whatever you need.

RegisterHotKey(this.Handle, HID, KeyModifiers.None, Keys.F11)

note, the hotkey ID is just just used to unregister the hot key

UnregisterHotKey(this.Handle, HID);

now we just check the WndProc to listen for our hotkey call!

const int WM_HOTKEY = 0x0312;//windows hotkey constant
        protected override void WndProc(ref Message message)
        {
           if (message.Msg == WM_HOTKEY)
            {
                   //there is your event, do whatever you like here.
            }
            base.WndProc(ref message);
        }

This is a simple hotkey, That's it, nothing else, nothing complicated. Now, you can make it complicated, if you wished. but if all you want to do is stop your app when you push a key regardless of focused application, this is the way to go.

This is a simple hotkey, That's it, nothing else, nothing complicated. Now, you can make it complicated, if you wished. but if all you want to do is stop your app when you push a key regardless of focused application, this is the way to go.

OK, so I have it working when the form is selected, but when it is not, the hotkey does not register. Is this normal?

(It is used for clicking an internet browser, so that is whats selected.


~Thanks in advance
MasterPengwin

Edited 6 Years Ago by MasterPengwin: n/a

The hot key should work at any time regardless of selected window. Please post your code and I will help you.

So right now I have this:

public partial class Form1 : Form
    {

         //API Imports

        
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(

            IntPtr hWnd, // handle to window    
            int id, // hot key identifier    
            KeyModifiers fsModifiers, // key-modifier options    
            Keys vk    // virtual-key code    
            );
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(
            IntPtr hWnd, // handle to window    
            int id);     //

             const int WM_HOTKEY = 0x0312;
             protected override void WndProc(ref Message message)
             {
                 if (message.Msg == WM_HOTKEY)
                 {
                     Close();
                 }
                 base.WndProc(ref message);
             }

 
        public enum KeyModifiers        //enum to call 3rd parameter of RegisterHotKey easily
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
            Windows = 8
        }

        public Form1()
        {
            InitializeComponent();
        }
        
    

        private void button1_Click(object sender, EventArgs e)
        {
//I have non-relevant code here
       }
        private void button2_Click(object sender, EventArgs e)
        {
            //I run a loop here, it clicks certain spots on the browser
        }
        
        private void button3_Click(object sender, EventArgs e)
       {
//I have non-relevant code here
        }
        private void button4_Click(object sender, EventArgs e)
        {
           //I have non-relevant code here
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            RegisterHotKey(this.Handle, WM_HOTKEY, KeyModifiers.None, Keys.Q);
        
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnregisterHotKey(this.Handle, WM_HOTKEY);
        }
       
    }
}

The Q key currently closes the form when it is selected, but when my program simulates clicking on the internet browser, nothing happens, the key stroke is just applied to the browser window. I think the problem is the loop I am running, it does not want to break the loop to close the program

Edited 6 Years Ago by MasterPengwin: n/a

I created a new project and pasted this code in, tied up the load and closing events and it works just fine.

so here is the possibilities.
1) you have a code loop going that keeps your form from processing windows messages, using a separate thread or calling Application.DoEvents(); could fix that.

2) Another program on your system is suppressing the Q key. Not likely but entirely possible. simple solution there is to just try another hotkey. just plain "Q" is a bad hotkey, what if you had to type a few words? a better choice would be like F9

3)IDK, but certainly other possible problems. HotKeys are very simple though, I have never had trouble with them. I have written a slew of little apps that run all the time hidden and show them selves on a hotkey press. (my personal favorite is alt + an arrow key)

I do use Thread.Sleep() to make my program wait for a certain amount of time. Could this be the problem? If so, how do I either, make it wait another way, or still make the hotkey work.

if you are sleeping the thread it WILL NOT process messages so the hot key will not work during a sleep.

you could put that work method into a separate thread and it should work find then.

if you are sleeping the thread it WILL NOT process messages so the hot key will not work during a sleep.

you could put that work method into a separate thread and it should work find then.

Im not sure I get what you mean. Could you explain or post some code?

Ok, A "Form" is that familiar window of the application that has the close button in the corner, windows communicates with a program via a message system where it sends codes to all apps as numbers, these numbers tell the form that things are happening. for example, a key is pressed, the mouse has entered the form, the form has moved, or a usb device has been plugged in. when you create a hotkey you tell windows that you want a message to be sent to your program when that key is pressed, simple enough.

a thread can be considered a "task". a thread is created when your program runs. This thread is a single concurrent run through the code that always follows in line. A program runs in a loop processing the windows messages and checking each event to see if it has fired. if during a method your "sleep" the thread. you tell the thread to do nothing for a period of time. in which it will not process events or windows messages. So when you sleep the thread you stop your hot key from getting processed. but windows does send it to your app, but your app misses it.

If you create a second thread (probably using the Background worker control would be easiest) and perform your work there, it should solve everything.

This article has been dead for over six months. Start a new discussion instead.