Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Wednesday, October 27 2021 @ 09:29 PM CEST

Dynamic Hotkey Support

   

CodingLevel : beginner

OS : windows
Language : C

Written by: Daniel S. Millington (guyonasm@hotmail.com)

Introduction

This article will introduce the concept of dynamic hotkeys within a program.
A Hotkey is a combination of one or more keys simultaneously pressed in which
then causes an action to occur. For example, pressing alt+f4 terminates an
application.



Where dynamic comes into play is how the key combinations are
"figured out", so to speak. The key combinations are stored within an INI file
and from there read into the program. The advantages to this and the method
that will soon be introduced are:

  • Dynamic. Hotkeys are not hardcoded into the program.
  • Hooking the keyboard is now obsolete. We simply check the state of the keys.
  • Hotkeys can be of any combination. Any length (i.e. alt+1+2+f+h+s, if we want).
  • Very easy to understand, and small amount of code to add.

The Concept

Now obviously, we will need an expandable data structure to store information
that we need. More specifically the combination of keys that make up our
hotkeys. It must be dynamic, meaning we can alter its size and state at will.
To cover this we will use a linked-list data structure as so:
struct Key
{
	int vKey;
	struct Key *nKey;
};
vKey stores the virtual keycode of the key, and nKey links us to the next key
(if there is one). We fill this list by parsing the string representation of the
hotkey stored within the INI file. Here is a simple function that parses the
string and creates the list that will makeup our hotkey combination list.
void parseHotkey (char *s, struct Key *k)
{
	struct Key *front;
	
	k->vKey = 0;
	k->nKey = 0;
	
	front = k;
	
	if (strtok (s, "+") == 0)
	{
		k->vKey = getKeyCode (s);
		return;
	}
		k->vKey = getKeyCode (s);
	
	while (s = strtok (0, "+"))
	{
		k->nKey = (struct Key *)malloc (sizeof (struct Key));
		k = k->nKey;
		k->vKey = getKeyCode (s);
		k->nKey = 0;
	}
		k = front;
}
The first parameter of the function takes the string representation of our
hotkey, and the second is a pointer to our linked-list data structure. All should
be self explanatory. It splits the string at "+", therefore there should be no
spaces in the string. Something not explained is of course, getKeyCode. This
function takes the string representation of our key, and returns the virtual
keycode of it. A standard keyboard has about 101 keys, and others have more.
It would be pointless to code in all of the virtual keys, so for this example
we will only use 3 different keys, if you want more you can look them up.
int getKeyCode (char *s)
{
	if (s == 0)
		return -1;
		
	if (!strcmp (s, "alt") || !strcmp (s, "ALT"))
		return VK_MENU;

	else if (!strcmp (s, "1"))
		return 0x31;
		
	else if (!strcmp (s, "2"))
		return 0x32;
	else
		return -1;
}
Okay, that is pretty straight forward. Now although most current systems
will do this for you, it is good to clean up after yourselves. So here is a function
to free the memory allocated for each list:
void cleanKey (struct Key *k)
{
	struct Key *temp;
	while (k != 0)
	{
		temp = k;
		k = k->nKey;
		free (temp);
	}
}
Now, to walk through and see if a key combination is pressed, we simply check
each link in the list, and if it is true (meaning the key is pressed), then we
move onto the next key in the combination. If all the keys are pressed then
the hotkey has been triggered, and we can execute whatever action was
assigned to it. Here is an example. There are many ways to go about this:

int checkKeys (struct Key *k)
{
	struct Key *temp;
	
	temp = k;
	while (k)
	{
		if (GetAsyncKeyState (k->vKey) < 0)
                {
                        if (k->nKey == 0)
			{
				// we made it here, hotkey triggered
				k = temp;
				return 1;
			}
		}
		else
			break;
		
		k = k->nKey;
	}
	k = temp;
	return 0;
}
If the hotkey is triggered 1 is returned, otherwise its 0.

An Implementation

So, now that we've covered all of the important things, and pretty much the
goal of the article. An example of using this, although rather useless would be
to create a program with 2 hotkeys. It sits in the background and waits for
either of them to be pressed. The first creates a MessageBox with a message.
The other exits the program, and pops up a MessageBox stating so. Here is
the code for this simple implementation:

// We are assuming everything else needed has been defined
// you, just can't see it. This program will not compile as is
// you are missing the necessary declarations of all of the functions
// Listed above.

// Also the hotkeys are hardcoded. We do not read in from any
// External Source. This was just to make the code shorter.
// You read in the string from an external source, and then pass
// it as the first parameter to parseHotkey.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

struct Key *mkey=0, *exitkey=0;

int working = 1;

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)
{				mkey = (struct Key *)malloc (sizeof (struct Key));
	exitkey = (struct Key *)malloc (sizeof (struct Key));
			
	parseHotkey ("alt+1", mkey);
	parseHotkey ("alt+2", exitkey);
			
	while (working)
	{
		if (checkKeys (mkey))
			MessageBox (0, "Hotkey #1 triggered!", "Notice.", 0);
		else if (checkKeys (exitkey))
		{
			MessageBox (0, "Hotkey #2 triggered! Exiting Program.", "Notice.", 0);
			working = 0;
		}
		Sleep (10);
	}
				cleanKey (mkey);
	cleanKey (exitkey);
	
	return 0;
}
And that is it. It is hoped that at least one person found this useful. If not, it
was still rather enjoyable writing it.




What's Related

Story Options

Dynamic Hotkey Support | 6 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
very nice article
Authored by: kino on Thursday, August 18 2005 @ 08:49 PM CEST
Hi there.
Very cool article . keep up the good work.

kino
Dynamic Hotkey Support
Authored by: stingduk on Friday, August 19 2005 @ 04:23 PM CEST
nice article there guyonasm
btw
why dont you use #include <stdio.h>

it should make the article as well as code readbale and compilable

#include and lt semicolon stdio.h and gt semicolon
and = &
lt = lessthan symbol
gt = greater than symbol
semicolon = ;

:)
Dynamic Hotkey Support
Authored by: guyonasm on Friday, August 19 2005 @ 06:04 PM CEST
I wasn't responsible for that. I did use those tags, when i submitted the article. Seems they were removed again. Detten is fixing the problem though.
 Copyright © 2021 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.83 seconds