Using hook functions dynamic Chinese foreign language menu
Yangshan River
Introduction Current, English version of the application, generally has a Chinese version on the Chinese platform. This has a localized version of the Chinese language, and there are also third-party suppliers in China or foreign suppliers in China to launch Chinese versions for market needs. The way the latter is divided into kernel and plug-in. Due to the series of problems such as copyright, the source code design is not necessarily compatible with Chinese, so few people are used. Therefore, in today's China, all the ways from Chinese Star to Quartet Cubes will use plug-in Chinese. The plug-in Hanhua can also use a variety of ways, and depending on the language of the operating system platform (Simplified Chinese, Traditional Chinese, English, etc.), the degree of Chinese is also different. The author has a slightly well-appreciated, through research, and presents a method of hanging Chinese in the Chinese operating system platform and is discussed by colleagues in interested.
Prior to this, we must clear a few related concepts.
two. "Hook" of Windows
Unlike the old qualification operating system DOS on the PC, the programming of Windows must comply with Microsoft to give you the "Game Rules": establish a window, establish a message loop for the window, and complete a variety of work in window functions In short: Must listen to Microsoft's arrangements, otherwise your app is not compatible, it is difficult to guarantee compatibility. In fact, Microsoft left a lot of "back door", "hook function" is one of the means.
The so-called "hook function", that is, a means of reserving the application in the message processing mechanism, the application can use it to install a subroutine for a specific message, so that we can monitor before reaching the destination in some messages. Or modify them. Windows provides 7 hook functions, 13 of Windows 95. In view of the development trend of the operating system, it is not discussed by Windows3.x. He will refer to Windows 95 (referred to as Win95) when Windows is mentioned. Methods for installing and removing these hook functions are the same, Win95 uses the following API:
HHOOK SETWINDOWSHOKEX (// Installation
INT IDHOOK, / / Type to install the hook
HookProc lpfn, // hook function address (callback function)
Hinstance HMOD, // The example handle of the program where the hook function is located
DWORD DWTHREADID / / The ID of the thread to install the hook
);
A hook function chain is formed when some applications install the same class hook. The installation function returns the filter function instance handle that specifies the hook type. .
Bool unhookwindowshookex (// Remove
HHOOK HHK / / Handle of the hook function to be removed
);
The hook type under Win95 is:
Wh_callwndproc // Window Process Hook
Wh_callwndprocret // message has been processed in the window process
// After receiving the hook function of these messages
WH_CBT / / computer-based training hook
Wh_debug // Check the wrong hook
Wh_ForeGroundIdle // Front desk free window hook
Wh_getMessage // Receive the hook of delivery message
Wh_journalplayback // Playback Previous Enter Message Hook
WH_JOURNALRECORD / / Record Enter Message Hook
Wh_keyboard // Keyboard hook
Wh_mouse // mouse hook
Message hooks such as WH_MSGFILTER / / dialog
WH_SYSMSGFILTER / / System Message Hook
WH_SHELL / / hook hook
The hook function is typically placed in the DLL such that it can be accessed by each process within the system, so the third parameter in the mounting hook API should be the handle of the DLL module.
In these types of hooks, the hooks of the Wh_getMessage type can access the information of our access window. The hook intercepts all messages obtained from the application queue through the standard message loop acquisition function. These messages contain a lot of valuable data, such as window handles, etc. Under normal circumstances, the hook function will be called regardless of whether the associated process is active, it will reduce the performance of the system, and even the system is stable. Therefore, the use of hook functions should be cautious, and it should be removed immediately. Win95 is a multi-threaded system that requires the scope of the hook function used by the user. The following is an explanation of the scope of action:
Hook role range
WH_CallWndProc thread or system
WH_CBT thread or system
WH_Debug thread or system
WH_GetMessage thread or system
Wh_journalplayback is only available
Wh_journalrecord only system
WH_KEYBOARD thread or system
WH_MOUSE thread or system
WH_MSGFilter thread or system
WH_SHELL thread or system
Wh_sysmsgfilter only
Using the hook function to achieve Chinese If we know the handle of a window, we can get the getMenu function.
The menu handle of the window. After that, we can get the external string of each menu item by the following menu function, and the corresponding Chinese string can be obtained by check the dictionary, and finally the Chinese string is replaced with the Chinese string. Note that Chinese display This program does not solve, so it is necessary to execute on the Chinese operating system. The above process here can be expressed as:
HWnd (window handle)
GetMenu (hwnd)
HMENU (menu handle)
GetSubmenu (Hmenu, Flag, Position)
HSUBMENU (submenu handle)
GetMenuItemString (Hsubmenu, Position, LPString, Len, Flag)
LPSZText (menu items)
FindChinese (LPSTRING, LPCHINESE, LEN)
LPSZCHINESE (Chinese string)
ModifyMenu (Hsubmenu, Position, Flag, ID, LPCHINESE)
Menu 项
So, how do you get another program's window handle from a program? This must know the window of the window. Because the window class name is a global atom, it is impossible to be the same as the same class name, and can be used as a unique identifier. Through the class name, FindWindowEx can get the window handle of its currently running application instance.
Through the above analysis, we can make such a solution:
Run a specific application that completes two tasks:
Search for the class name of our foreign language program, get the window handle of the program current instance, the ID of the main thread, install a hook function of the wh_getMessage type. Use the window handle to get the main menu handle, add a custom menu item after the menu. This menu item is primarily used to send messages to the window process so that the hook function of the wh_getMessage type can be activated, and
The handle of the main menu of the program makes the above-described Chinese process.
2.
The hook function is mainly working in Chinese. The hook function should exist in a DLL. Mainly used to intercept custom menu messages, in this menu message processing, get the main menu handle, find the dictionary in the DLL, replace the foreign menu item.
Program Description Since Win95 is a multi-threaded environment, the thread ID must be specified when the hook function is hooked. This parameter is usually set to NULL in a Windows 3.x environment. When the hook installer is looking for a window class, if you can't find it, you should use the WINEXEC function to start according to the path to the external program, and then look for so that you can install the hook function smoothly. The hook installer can also perform menu Hanhua by getting a window handle. However, considering that many applications often modify the menu during operation, the main process of Chinese is placed in the hook function. Because the front hook is not effective, dynamic Chinese can be easily performed by the selection of custom menu items. The hook installer and the foreign language we want Chinese are two different processes, and there are two different application spaces in Win95. To implement a dictionary of a dynamic connection library for foreign programs, because the hook function is mounted, the same process is the same process space, and DLL is a hook installer, so you must use the dictionary and some hook functions. Variables are set to memory sharing and need to be used to use the #pragma Date_SEG instruction. See the program code. This is very important, otherwise it will have an annoying protection. For simplicity, the number of dictionary entries in the dynamic connection library is limited. In fact, Win95 can be greater than 64K. In addition, the pattern used in the example is extremely simple, and everyone can improve the subsection. The menu often contains a lot of keyboard operational simplekekes, so the Chinese string must inherit the relevant content in the foreign language, and all the operations of the original program must not be changed. . After replacing the menu item, you must immediately perform the refresh of the menu bar, otherwise the display of the menu is extremely confusing. The DrawMenubar function should be called immediately after replacement. To define the .def file, export to the function, the introduction must be accurate, otherwise it will cause compilation to fail. The program passes in the PWIN95, BC5.0, and PMMX166 environments. Some dynamically connected public libraries of BC may be required, pay attention to when commissioning. 10 In order to demonstrate the purpose, reduce the space, hereby commenting the part of the program. Hook function installer:
#define strict
#include
#include
#include "mate.h"
BOOL WINAPI _IMPORT InstallmsgfilterHook (HWND HWND);
Int Pascal Winmain (Hinstance Hinstance, Hinstance Hpre, LPSTR LPCMDLINE, INT NCMDSHOW)
{
Char szprogramclass [30] = "shi"; // The class name of the foreign language is here, this demonstration // program class name
Char szprogrampath [30] = "E: //ysh/shi//shi.exe"; // Foreign program path, this
// The program path to be used by the reader can be set as the reader
MSG msg;
HWND _HWND; / / 要 外 程序 程序 程序 程序
HMENU HMENU; // Main menu handle
INT NTOPLVEL; / / Top popup menu item
_hWnd = findwindow (szprogramclass, null);
IF (_hWnd = = null) // Not found
{
IF (Winexec (SZPROGRAMPATH, SW_SHOW) == ERROR_FILE_NOT_FOUND) // Didn't find the specified program
{
MessageBox (Null, "File Not Found!", "Chinese Mallace", MB_OK;
Return (False);
}
_hWnd = findwindow (szprogramclass, null); // Looking for IF again (_hWnd == null)
{
MessageBox (NULL, "Find Window Faild!", "Chinese Mallace", MB_OK;
Return (False);
}
}
LoadLibrary ("mate.dll"); // loaded into the library
HMENU = GetMenu (_hwnd); // Get menu
Appendmenu (HMENU, MF_BITMAP | MF_ENABED, CM_MYMENUITEM, "Chinese && English"); // Add your own menu item
Drawmenubar (_hwnd); // Heavy paintings, otherwise the menu shows chaos
IF (! installmsgfilterhook (_hwnd)) // Install the hook
{
Messagebox (NULL, "Hook Function Failed!", "Chinese Mallace", MB_OK;
Return (False);
}
}
Return (TRUE);
}
The main code of the dynamic connection library:
#define CommonNum 100
#include
#include
#include
#include "mate.h"
#pragma data_seg ("tweny") / / must be explained in .def as a shared section
Static hHOOK MSGFILTERHOK = null; // Receive delivery message hook handle
Static hinstance hinstance = null;
Static HWnd ShihWnd = NULL; // Foreign Program Window Handle
Static bool flag = true;
Static HMenu HWndMenu = NULL; // Menu Handle
Commondict Word [CommonnUM] = // Dictionary, the structure is defined in the head
//
{
{"& File", "file & f"},
{"& New", "New & n"},
{"& Open", "Open & O"},
{"& Savior", "save & s"},
{"Save & AS", "Save As & A"},
{"P & Rinter Setup", "Printer Settings & R"},
{"Page SET & UP", "Page Settings & U"},
{"& Print", "Print & P"},
{"E & XIT", "Exit & X"},
{"& Edit", "Edit & E"},
{"& Undo", "revoke & u"},
{"& Redo", "red do & r"},
{"Cu & T", "Cut & T"},
{"& Copy", "copy & c"},
{"& Paste", "Paste & P"},
{"& Window", "Window & W"},
{"& Windows", "Window & W"}, {"& Tile", "Cascade & T"}
{"& Cascade", "laminated & c"},
{"& Hide", "Hide & H"},
{"& Hidden", "Hide & H"},
{"& View", "show & v"},
{"& All", "all & a"},
{"& Hidden Document List", "Hide all text windows & h"},
{"& Help", "Help & H"},
{"Help Topics", "Help Topic & W"},
{"& What's this?", "What is this & w"},
{"& About", "About & A"},
}
#pragma data_seg () // shared segment declaration end
Bool WinApi_export installmsgfilterhook (hwnd hwnd);
LResult Callback_export msgfilter (int ncode, wparam wparam, lparam lparam); // hook type declaration
Bool WinApi SearchDict1 (Char * English, Char * Chinese); // Tatting Dictionary
Bool WinApi DllenTryPoint (Hinstance Hinthis, DWord FDWREASON, LPVOID LPVRESVERED)
{
Hinstance = Hinthis;
Switch (FDWREASON)
{...} // See related documents
Return (TRUE);
}
Bool WinAPI_Export Installmsgfilterhook (HWND HWND)
{// Install the hook function
DWORD PID; // Thread ID
ShihWnd = hwnd; // Mapped program window
HWndMenu = GetMenu (ShihWnd); // Get menu handle
IF (! hwndmenu) MessageBox (Null, "Get Menu Faild",
"Install", MB_OK;
Return (msgfilterhook = setwindowshookex (WH_GetMessage, (HookProc) msgfilter, hinstance, getwindowthreadprocessid (hwnd, & pid))! = null); / / Install the hook function of the specified thread
}
LResult Callback_export Msgfilter (int Ncode, WPARAM WPARAM, LPARAM LPARAM)
{// message filter function
HMENU HPOPUP; // Main menu handle
Char lpmenustr [30]; // menu item string
INT I, Count;
IF (ncode> = 0) // less than zero remaining to system processing
{
Switch (ncode)
{
Msg * msg;
HMENU HSUBMENU, HSUB2MENU; // Two-layer menu
HWND HWNDTHIS;
Char BUF [100], Chinese [100]; // Character buffer
INT TOPNUM, SUBNUM, SUB2NUM; // is the top-level menu item, respectively,
// Pop up menu item, the secondary submenu number
INT i = 0, j = 0, k = 0; uint itemid; // menu item ID, modify the command ID of the menu when modifying the menu item
Menuiteminfo MenuItem;
Case HC_Action:
MSG = (msg *) lparam;
Switch (msg-> message)
{
Case WM_COMMAND:
IF (msg-> wparam == cm_mymenuitem) / / Is it a custom menu item?
{
HWNDTHIS = msg-> hwnd; // Get window handle
HWndMenu = GetMenu (hwndthis); // Get the main menu handle
TopNum = getMenuItemcount (hwndMenu); // Get the top-level menu item
For (i = 0; i { IF (Getmenustring (HWndMenu, I, BUF, 100, MF_BYPOSITION)) / / Get the string of the specified location menu item { IF (SearchDict1 (BUF, Chinese)) // If you find it from the dictionary { Itemid = getMenuItemID (HWndMenu, i); // get menu ID ModifyMenu (HWndMenu, I, MF_String | MF_BYPOSITION, ITEMID, Chinese); // Modify the menu Drawmenubar (hwndthis); // Update Now } Else { } } } IF (HWndMenu) { For (i = 0; i {// Chinese pop-up menu item Hsubmenu = GetSubmenu (HWndMenu, i); Subnum = getMenuItemcount (Hsubmenu); For (j = 0; j <= Subnum; J ) { { IF (Getmenustring (HSubmenu, J, BUF, 100, MF_BYPOSITION)) // Pop-up menu item content is character? { IF (SearchDict1 (BUF, Chinese) // Tatches Dictionary { Itemid = getMenuItemID (HSubmenu, J); IF (itemid == 0xfffffffff) // Is there any submenu? {// Chinese HSUB2MENU = GetSubmenu (HsubMenu, J); Sub2Num = getMenuItemcount (HSUB2MENU); For (k = 0; k { IF (Getmenustring (HSUB2MENU, K, BUF, 100, MF_BYPOSITION)) { IF (SearchDict1 (BUF, Chinese)) { ItemID = GetMenuItemID (HSUB2MENU, K); Modifymenu (HSUB2MENU, K, MF_STRING | MF_BYPOSITION, ITEMID, Chinese); } } } } ModifyMenu (Hsubmenu, J, MF_String | MF_BYPOSITION, ITEMID, Chinese); Drawmenubar (hwndthis); // Update Now } } } } } } Else MessageBox (NULL, "HWndMenu Is Null", "My Hook", MB_OK; } // Unaffected the main menu handle Break; DEFAULT: Break; } Break; } } Return (CallNexthooKex (Msgfilterhook, Ncode, WPARAM, LPARAM); } Bool WinApi SearchDict1 (Char * English) { Char in [100], OUT [100]; INT I; Bool flag; // Find a sign LSTRCPY (IN, ENGLISH); For (i = 0; i <60 / * number * /; i ) // Level the length of the dictionary { LSTRCPY (OUT, WORD [I] .english); Flag = LSTRCMP (IN, OUT); IF (! flag) // { LSTRCPY (Chinese, Word [i] .chinese; // Copy Chinese characters Break; } Else {// Add to check the code for the second dictionary here } } Return (! flag); // Return to find results } == Written in 1998