· 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.