Development of key pronunciation program using keyboard hooks

Source: Internet
Author: User
Preface

One day, I saw my mom practicing typing on a computer and frequently looked down at the keyboard. I thought: If the keyboard can be pronounced, will it help her develop a good habit of "playing blindly? If you just want to do it, you can't do it. Start the action.

Keys can be pronounced. The key is to let the program know which key is being pressed on the Current keyboard and play the corresponding sound. Of course, the program cannot be used, how can we know which key is currently pressed by other programs? Using keyboard hooks can be a good solution.

Basic Principles of hook

When Windows calls a mounted callback function, it first calls the function at the beginning of the function chain. If we place our callback function at the beginning of the chain, the callback function will be called first. So how can we place our own callback function at the beginning of the chain of the function chain? The setwindowshookex () function implements this function. Let's first take a look at the prototype of the setwindowshookex function:

HHOOK SetWindowsHookEx(  int idHook,         HOOKPROC lpfn,       HINSTANCE hMod,      DWORD dwThreadId  ); 
  • The first parameter: Specifies the hook type. There are more than 10 types of hooks, such as WH_MOUSE and WH_KEYBOARD (see MSDN for details)
  • The second parameter indicates the entry address of the hook function.
  • Third parameter: handle of the module where the hook function is located;
  • The fourth parameter: the ID of the hook-related function is used to specify the thread to which the hook is to hook. If the value is 0, messages of the entire system are intercepted.

In addition, to capture all events, hook functions should be placed in the dynamic link library DLL.

Implementation

In theory, run VC ++ 6.0 to create an MFC Appwizard (DLL) project named hook and use the default option to create the DLL type, that is, use the shared mfc dll and click Finish to write the code.

Define global functions in hook. h

Bool installhook (); // hook installation function lresult callback keyboardproc (INT ncode, wparam, lparam); // Hook Function

Add the code for defining the global variable hook under # endif In the hook. cpp file:

Static hhook hkb = NULL; hinstance hins; // handle of the module where the hook function is located

Add core code

BOOL installhook(){    hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);    return TRUE;}

The first parameter specifies the hook type, which is set to WH_KEYBOARD because only keyboard operations are used. The second parameter specifies the hook function entry address as KeyboardProc, call this function when the hook hooks any message. That is, KeyboardProc is triggered immediately when any keyboard input in the System window exists; the third parameter is the sentence handle of the module where the hook function is located. The last parameter is the ID of the hook-related function to specify the thread to which the hook is to be hooked, if the value is 0, messages of the entire system are intercepted.

Now, let's start to define what the program will do when the key on the keyboard is pressed.

KeyboardProc action:

Lresult callback KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) {if (DWORD) lParam & 0x40000000) & (HC_ACTION = nCode) {switch (wParam) // keyboard key ID {case '1': sndPlaySound ("1.wav", SND_ASYNC); break; // when the number key 1 is pressed case '2 '': sndPlaySound ("2.wav", SND_ASYNC); break; case '3': sndPlaySound (" 3.wav", SND_ASYNC); break; case '4''': sndPlaySound ("4.wav ", SND_ASYNC); break ;.... case ''a': sndPlaySound ("a.wav", SND_ASYNC); break; // when primary key A is pressed, case ''B ': sndPlaySound (" B .wav ", SND_ASYNC); break; case 'C': sndPlaySound ("c.wav", SND_ASYNC); break; case ''d': sndPlaySound ("d.wav", SND_ASYNC ); break ;....}} LRESULT RetVal = CallNextHookEx (hkb, nCode, wParam, lParam); return RetVal ;}

In the above Code, we use the playing sound as the action after the button is pressed. The first parameter of the API function sndPlaySound defines the absolute path of the sound file (for example, to play the.wav under drive C, it is defined as "C: \ a.wav"). The second parameter defines the playing mode. The SND_ASYNC mode can release the playing audio files in time, immediately stop playing the current sound and play the new sound, so that we don't have a sense of excitement when we press the key continuously. to execute the sndPlaySound function. add the following to the cpp file header:

 #include "mmsystem.h"

Click "project"-"Settings" on the VC ++ menu to go to the Link property page. Enter winmm. lib in the L object/Library module and click "OK.

Add the output identifier and add it at the end of Hook. def.

installhookKeyboardProc

In just four steps, the preparation of the keyboard hook is complete. After compilation, the DLL file can be freely called by other programs. How To Call DLL in a program? That's easy. Use VC ++ 6.0 to create an MFC AppWizard (exe) project, name it KeySound, click "OK", select the program type as the dialog box, and click "OK.

In the KeySoundDlg. cpp file, OnInitDialog () initializes the function's CDialog: OnInitDialog (); Add the following:

// Prevent the program from repeatedly resident in the memory and prevent errors when two programs read the DLL at the same time. createMutex (NULL, FALSE, "KeySound"); if (GetLastError () = ERROR_ALREADY_EXISTS) OnOK (); // read DLLstatic HINSTANCE hinstDLL; typedef BOOL (CALLBACK * inshook) (); inshook instkbhook; if (hinstDLL = LoadLibrary (LPCTSTR) "Hook. dll ") {instkbhook = (inshook) GetProcAddress (hinstDLL," installhook "); instkbhook () ;}else {MessageBox (" Hook not found in the current directory. dll file, program initialization failed "); OnOK ();}

Put the generated keysound.exeand hook.dllin the same directory, define the audio file, run keysound.exe, open the notepad or tablet, and experience the pleasure of the system to read every key you press in real time.

It must be noted that the standard keyboard has 101 keys, and you must define the number of keys in the above KeyboardProc action to enable the sound of keys, the commonly used 10 numeric keys and 26 English letters do not bring you too much difficulty, as long as the corresponding ''a' corresponds to the key, ''1'' corresponds to the 1 key, but if you want more keys to have a variety of special music, you may encounter some keyboard coding troubles, for example, the ESC key cannot be simply identified by the ''esc '', VK_ESCAPE is used, and the Alt key must be defined by the VK_MENU, if you do not have a key-disk encoding table, it will be quite a headache. Here I will introduce a method for the program to tell you the name of the keyboard key:

Add the PreTranslateMessage ing to a project and add the following code:

char KeyName[50];ZeroMemory(KeyName,50);if(pMsg -> message == WM_KEYDOWN){    GetKeyNameText(pMsg->lParam,KeyName,50);   MessageBox(KeyName);} 

When the program window is displayed in front of a key, a message will pop up showing the name of the key, and then wrap it with ''', such as periods, is '','', and ''. '', simple

At this point, we have all completed the preparation of the key pronunciation program. By changing the name of the audio file, you can change the key sound without modifying the program itself, the location of the sound file on the hard disk cannot be changed, and it cannot be played from drive C to drive D. How can we flexibly read the sound file? You can use the API function GetModuleFileName to obtain the program's contents. The specific implementation method is as follows:

Add the following in public: of Hook. h:

BOOL InitInstance (); // initialization Function

Add the code for defining global variables under # endif in Hook. cpp:

char szBuf[256];char *p;CString msg;

Add the following content in Hook. cpp:

BOOL CHookApp::InitInstance (){    hins=AfxGetInstanceHandle();   GetModuleFileName(AfxGetInstanceHandle( ),szBuf,sizeof(szBuf));   p = szBuf;   while(strchr(p,''\\''))    {         p = strchr(p,''\\'');         p++;    }   *p = ''\0'';    msg=szBuf;   return TRUE; }

Create a folder and name it Sound. Change the definition of the physical location of the Sound file.

case ''1'':sndPlaySound(msg+"sound\\1.wav",SND_ASYNC);break; 

Msgspecifies the 1.wav file in the sound under the current directory. In this way, you can change the absolute path of the audio file to a flexible path. You only need to set keysound.exe and Hook. the dll and Sound folders are placed in the same folder. After moving the entire folder, you can move the Sound file.

During debugging, note that the hook.dllw.sounddirectory is stored in the execution directory of keysound.exe. If the unresolved external symbol _ imp _ sndPlaySoundA @ 8 Information appears during the compilation of the link, add Winmm. lib to the Project Settings.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.