Implementation of Win32 global hooks in VC

Source: Internet
Author: User

· He chengshi
The Windows system is based on the event-driven mechanism. To put it bluntly, the entire system is implemented through message transmission. A hook is a very important system interface in windows. It can be used to intercept and process the hook and send it to other applications.ProgramTo complete the functions that are difficult to implement in common applications. There are many types of hooks. Each Hook can intercept and process corresponding messages. For example, a keyboard Hook can intercept keyboard messages, and a shell Hook can intercept, start, and close application messages. This article implements a simple mouse hook program in the vc5 programming environment, the running mechanism of Win32 global hooks, the characteristics of Win32 DLL, the mfc dll in vc5 environment, and the knowledge of shared data are briefly described.

1. Win32 global hook Operation Mechanism

A hook is actually a program segment for message processing. It is called by the system and mounted to the system. When a specific message is sent, the hook program captures the message before it reaches the target window, that is, the hook function gets control of the message first. In this case, the hook function can process (Change) the message, continue to transmit the message without processing it, and forcibly end the message transmission. For each type of Hook, the system maintains a hook chain. The recently installed hook is placed at the beginning of the chain, and the first installed hook is put at the end, that is, the first added hook gets control. To implement Win32 system hooks, you must call the SDK's API function setwindowshookex to install this hook function. The prototype of this function is hhook setwindowshookex (INT idhook, hookproc lpfn, hinstance hmod, DWORD dwthreadid), where the first parameter is the hook type, the second parameter is the hook function address, and the third parameter is the module handle containing the hook function; the fourth parameter specifies the monitored thread. If a specific thread is specified, it is a dedicated hook. If it is specified as null, it is a global hook. Among them, the global hook function must be included in the DLL (Dynamic Link Library), and the thread-specific Hook can also be included in the executable file. After the hook function obtains control, if you want to continue transmitting the message after processing the message, it must call the API function callnexthookex in another SDK to transmit it. The hook function can also directly return true to discard the message and prevent the message from being transmitted.

Ii. Win32 DLL features

Win32 DLL differs greatly from Win16 DLL, which is mainly determined by the operating system design philosophy. On the one hand, in Win16 DLL, the program entry point function and exit point function (libmain and WEP) are implemented respectively, but in Win32 DLL, the same function is implemented by dllmain. This function is called whenever a process or thread loads and uninstalls a DLL. Its prototype is bool winapi dllmain (hinstance hinstdll, DWORD fdwreason, lpvoid lpvreserved );, the first parameter indicates the DLL instance handle, and the third parameter is retained. Here we mainly introduce the second parameter, which has four possible values: dll_process_attach (process loading ), dll_thread_attach (thread loading), dll_thread_detach (thread detaching), and dll_process_detach (process detaching). In the dllmain function, you can identify the value of this parameter passed in, perform necessary initialization or cleanup for the DLL based on different parameter values. For example, when a process loads a DLL, the second parameter assigned to the DLL by the system is dll_process_attach. In this case, you can initialize specific data based on this parameter. In Win16, all applications are in the same address space. In Win32, all applications have their own private space, the space of each process is independent of each other, which reduces the interaction between applications, but also increases the programming difficulty. As you know, in the Win16 environment, the global data of DLL is the same for every process that loads it. In the Win32 environment, the situation has changed, when a process loads a DLL, the system automatically maps the DLL address to the private space of the process and copies the global data of the DLL to the process space, that is to say, the global data values of the same DLL owned by each process are not necessarily the same. Therefore, to share data among multiple processes in a Win32 environment, you must make necessary settings. That is, the data to be shared is separated and placed in an independent data segment, and the attribute of this segment is set to share.

Iii. Classification and features of mfc dll in vc5

There are three forms of mfc dll in vc5 (you can use and inherit the existing MFC classes in this DLL) to choose from, that is, regular statically linked to mfc dll (Standard static link mfc dll) and regular using the shared mfc dll (Standard Dynamic Link mfc dll) and extension mfc dll (Extended mfc dll ). The first DLL is characterized byCodeTherefore, when using this program, you do not need to use other MFC dynamic link class libraries, but it occupies a large disk space. The second DLL is characteristic of running, dynamic Link to the MFC class library reduces space usage, but it depends on the MFC dynamic link class library at runtime; these two DLL types can be used by both the MFC program and Win32 program. The third type of DLL is similar to the second type. As an extension of the MFC class library, it can only be used by the MFC program.

4. Global data sharing in vc5

In the main file, use # pragma data_seg to create a new data segment and define shared data. The specific format is:

# Pragma data_seg ("shareddata ")

Hwnd sharedwnd = NULL; // share data

# Pragma data_seg ()

Defining only one data segment can not achieve the purpose of sharing data, but also tell the compiler the attributes of this segment, there are two ways to achieve this (the effect is the same ), one way is in. add the following statement to the def file:

Setctions

Shareddata read write shared

Another method is to add the following statement to the project setting link option:

/Section: shareddata, RWS

5. Specific implementation steps

Because the global hook function must be included in the dynamic link library, this example is implemented by two program bodies.

1. Create hook mousehook. dll

(1) Select MFC Appwizard (DLL) to create the project mousehook;

(2) Select the MFC extension DLL (shared MFC copy) type;

(3) because there is no ready-made hook class in vc5, create a mousehook. h file in the project directory and create a hook class in it:

Class afx_ext_class cmousehook: Public cobject

{

Public:

Cmousehook ();

// Constructor of the hook class

~ Cmousehook ();

// Hook class destructor

Bool starthook (hwnd );

// Install the hook function

Bool stophook ();

Uninstall Hook Function

};

(4) Add the # include "mousehook. H" Statement to the top of the mousehook. app file;

(5) Add the global shared data variable:

# Pragma data_seg ("mydata ")

Hwnd glhprevtarwnd = NULL;

// The Window handle pointed by the last mouse

Hwnd glhdisplaywnd = NULL;

// Display the handle of the title edit box of the target window

Hhook glhhook = NULL;

// The mouse hook handle for Installation

Hinstance glhinstance = NULL;

// DLL instance handle

# Pragma data_seg ()

(6) define the segment attribute in the def file:

Sections

Mydata read write shared

(7) Add the statement for saving the DLL instance handle to the dllmain function of the main file mousehook. cpp:

Dllmain (hinstance, DWORD dwreason, lpvoid lpreserved)

{

// If the lpreserved parameter is used, delete the following line.

Unreferenced_parameter (lpreserved );

If (dwreason = dll_process_attach)

{

Trace0 ("mousehook. dll initializing! \ N ");

// The extension DLL is initialized only once.

If (! Afxinitextensionmodule (mousehookdll, hinstance ))

Return 0;

New cdynlinklibrary (mousehookdll );

// Add the DLL to the dynamic MFC class library

Glhinstance = hinstance;

// Insert and save the DLL instance handle

}

Else if (dwreason = dll_process_detach)

{

Trace0 ("mousehook. dll terminating! \ N ");

// Call this library before terminating it

Afxtermextensionmodule (mousehookdll );

}

Return 1;

}

(8) Implementation of member functions of class cmousehook:

Cmousehook: cmousehook ()

// Class Constructor

{

}

Cmousehook ::~ Cmousehook ()

// Class destructor

{

Stophook ();

}

Bool cmousehook: starthook (hwnd)

// Install the hook and set the handle for receiving the display window

{

Bool bresult = false;

Glhhook = setwindowshookex (wh_mouse, mouseproc, glhinstance, 0 );

If (glhhook! = NULL)

Bresult = true;

Glhdisplaywnd = hwnd;

// Set the handle to display the title edit box of the target window

Return bresult;

}

Bool cmousehook: stophook ()

// Uninstall the hook

{

Bool bresult = false;

If (glhhook)

{

Bresult = unhookwindowshookex (glhhook );

If (bresult)

{

Glhprevtarwnd = NULL;

Glhdisplaywnd = NULL; // clear the variable

Glhhook = NULL;

}

}

Return bresult;

}

(9) Implementation of hook functions:

Lresult winapi mouseproc (INT ncode, wparam, lparam)

{

Lpmousehookstruct pmousehook = (mousehookstruct far *) lparam;

If (ncode> = 0)

{

Hwnd glhtargetwnd = pmousehook-> hwnd;

// Retrieve the target window handle

Hwnd parentwnd = glhtargetwnd;

While (parentwnd! = NULL)

{

Glhtargetwnd = parentwnd;

Parentwnd = getparent (glhtargetwnd );

// Obtain the handle of the main application window

}

If (glhtargetwnd! = Glhprevtarwnd)

{

Char szcaption [100];

Getwindowtext (glhtargetwnd, szcaption, 100 );

// Obtain the title of the target window

If (iswindow (glhdisplaywnd ))

Sendmessage (glhdisplaywnd, wm_settext, 0, (lparam) (lpctstr) szcaption );

Glhprevtarwnd = glhtargetwnd;

// Save the target window

}

}

Return callnexthookex (glhhook, ncode, wparam, lparam );

// Continue message transmission

}

(10) compile the project to generate mousehook. dll.

2. Create a hook executable program

(1) Use the Appwizard (exe) of MFC to create the project mouse;

(2) Select "Application Based on dialog" and press "finish;

(3) In the edit dialog box, delete the original two buttons, add the static text box and edit box, right-click the static text box, and select "attribute" in the pop-up menu ", set the title to "the title of the window where the mouse is located ";

(4) Add the include statement # include ".. \ mousehook. H" to the mouse. h ";

(5) add private data members to the cmousedlg class definition of cmousedlg. h:

Cmousehook m_hook; // Add the hook class as a data member

(6) modify the cmousedlg: oninitdialog () function:

Bool cmousedlg: oninitdialog ()

{

Cdialog: oninitdialog ();

Assert (idm_aboutbox & 0xfff0) = idm_aboutbox );

Assert (idm_aboutbox <0xf000 );

Cmenu * psysmenu = getsystemmenu (false );

If (psysmenu! = NULL)

{

Cstring straboutmenu;

Straboutmenu. loadstring (ids_aboutbox );

If (! Straboutmenu. isempty ())

{

Psysmenu-> appendmenu (mf_separator );

Psysmenu-> appendmenu (mf_string, idm_aboutbox, straboutmenu );

}

}

Seticon (m_hicon, true); // set big icon

Seticon (m_hicon, false); // set small icon

// Todo: add extra initialization here

Cwnd * pwnd = getdlgitem (idc_edit1 );

// Get the class pointer of the edit box

M_hook.starthook (pwnd-> getsafehwnd ());

// Obtain the window handle in the editing box and install the hook

Return true;

// Return true unless you set the focus to a control

}

(7) link the dll library to add .. \ mousehook \ debug \ mousehook. lib to the project setting link tag;

(8) compile the project to generate executable files;

(9) Copy mousehook. dll to the. \ mouse \ DEBUG directory;

(10)run several executable programs first, then run the mouse.exeprogram to move the mouse in different windows. The edit box in the mouse.exe program window displays the title of the application main window where the mouse is located.

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.