home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


That completes our work with journal hooks. Next, we turn to hooks specifically made to handle keyboard events: keyboard hooks.

Keyboard Hooks

In our next hook example, we support a keyboard hook, which is specifically designed to work with the keyboard. In this case, we let the user press a key combination—^C—to open the Windows calculator. The keyboard hook code has to be in a DLL, and we call our DLL LaunchDLL.dll. When we link that DLL into a program, Launch, we call a function in that DLL, InstallLauncher(), to install our hook. Until you end the Launch program, every time the user presses ^C in any program, the Windows calculator appears.

We start by creating a new MFC DLL as we did in the last chapter.

Creating LaunchDLL.dll

Use AppWizard(dll) to create a new, standard DLL project named LaunchDLL. We need two functions in this DLL: a function to install the keyboard hook, InstallLauncher(), and a hook procedure, LauncherHook(). The following example shows how we declare those in LauncherDLL.h:

// LaunchDLL.h : main header file for the LAUNCHDLL DLL
//

#if !defined(AFX_LAUNCHDLL_H__6433B666_A86C_11D1_887F_D
42B07C10710__INCLUDED_)
#define AFX_LAUNCHDLL_H__6433B666_A86C_11D1_887F_D
42B07C10710__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
    #error include ‘stdafx.h’ before including this file for PCH
#endif

#include “resource.h”        // main symbols

#define DllExport    __declspec( dllexport )                             ⇐
DllExport void WINAPI InstallLauncher();                                 ⇐
LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam );   ⇐
    .
    .
    .

The code in InstallLauncher() installs our hook, and writing that code will be our first task.

Installing the Hook

Add the InstallLauncher() function to the end of the LaunchDLL.cpp file, after the declaration of the actual MFC DLL object itself, theApp.

CLaunchDLLApp theApp;

DllExport void WINAPI InstallLauncher()        ⇐
{                                              ⇐

}                                              ⇐

To install a keyboard hook, we pass SetWindowsHookEx() the constant WH_KEYBOARD, a pointer to a hook procedure (which will be our LauncherHook() function), the instance handle of the DLL, and the thread ID of the process to hook. Making that ID 0 means we hook all running threads.

One problem here is how to get the instance handle of the DLL, especially because the InstallLauncher() procedure is not part of the CLaunchDLL class. The solution is simple. As we just saw, the actual DLL object in MFC DLLs is named theApp, and that object has a special member named m_hInstance, which is just what we want. We set the hook this way:

CLaunchDLLApp theApp;

DllExport void WINAPI InstallLauncher()
{
    Hook = (HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)LauncherHook,
theApp.m_hInstance, 0);               ⇐
}

That installs the hook. All we need to do now is write the hook procedure, LauncherHook().

The Hook Procedure

We start the LauncherHook() procedure much as we started the hook procedures in the last example: by calling the next hook in the chain, if there is one.

LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);       ⇐
        .
        .
        .

We’re looking for events with the code HC_ACTION, so we check for that first.


Getting the Key State

Note that GetKeyState() returns the state of the Shift, Ctrl, and Alt keys for the current message, not the current state of those keys on the keyboard.


LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);

    if(nCode == HC_ACTION){             ⇐
        .
        .
        .

We also must check to see whether the user has pressed ^C. The wParam parameter holds the key that the user pressed, but it doesn’t include any modifying keys, such as Shift, Ctrl, or Alt (which is one reason why it’s usually easier to use WM_CHAR when possible). Instead, we get the key state for the current message with GetKeyState(), so we check if the Ctrl key is down.

LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);

    if(nCode == HC_ACTION){
        if ((GetKeyState(VK_CONTROL) < 0) && (wParam == ‘C’)){        ⇐
                .
                .
                .

We know that the user has pressed the ^C key, but we don’t know whether this is a KeyUp or KeyDown message. We don’t want to launch the Windows calculator for both messages, so we check for the WM_KEYUP message.

If the user has released the key, the top bit of the lParam parameter will be set. We check that this way:

LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);

    if(nCode == HC_ACTION){
        if ((GetKeyState(VK_CONTROL) < 0) && (wParam == ‘C’)){
            if(lParam & 0x80000000){                   ⇐
                    .
                    .
                    .

At this point, we’re ready to launch the Windows calculator program c:\windows\calc.exe. We begin that process by setting up the STARTUPINFO and PROCESS_INFORMATION structures we need.

LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);

    if(nCode == HC_ACTION){
        if ((GetKeyState(VK_CONTROL) < 0) && (wParam == ‘C’)){
            if(lParam & 0x80000000){
                STARTUPINFO StartupInfo;                               ⇐
                PROCESS_INFORMATION ProcessInfo;                       ⇐

                memset(&StartupInfo, 0, sizeof(StartupInfo));         ⇐
                StartupInfo.cb = sizeof(StartupInfo);                  ⇐
                           .
                           .
                           .

Then we launch the calculator itself.

LRESULT CALLBACK LauncherHook (int nCode, WORD wParam, DWORD lParam )
{
    LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam);

    if(nCode == HC_ACTION){
        if ((GetKeyState(VK_CONTROL) < 0) && (wParam == ‘C’)){
            if(lParam & 0x80000000){
                STARTUPINFO StartupInfo;
                PROCESS_INFORMATION ProcessInfo;

                memset(&StartupInfo, 0, sizeof(StartupInfo));
                StartupInfo.cb = sizeof(StartupInfo);

                CreateProcess(”c:\\windows\\calc.exe”, NULL, NULL, NULL,
FALSE, 0,    NULL, NULL, &StartupInfo, &ProcessInfo);            ⇐
                Result = 0;                                    ⇐
            }
        }
    }
    return Result;                                               ⇐
}

That finishes the DLL. Create LauncherDLL.dll and LauncherDLL.lib now.

We need some way to call the InstallLauncher() function in order to install our new hook, so we put together a new program called Launch to do that.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.