I have always wanted to write something about input method programming. Today is a little time, and I hope it will be helpful to later users. I would like to express my special thanks to Li zhenchun, the author of "free pinyin". He helped me solve some of my first problems.
First, we need to understand what the input method is. Currently, there are basically two types of commonly used input methods: External mounting (such as the early million records) and Input Method interface (input method ).
Editor-ime ). The external mounting method is simple. It is an EXE file. It inputs text to the active editing window by simulating some windows input messages. A significant advantage is that the input method only needs to be started once, it can be used in all processes, but its shortcomings cannot be ignored. It is not easy to implement first. A bigger problem is that its compatibility is not good enough, generally, a Windows version requires an input method version corresponding to one user. In order to intercept user input, a keyboard hook is usually required, which may cause system instability or low efficiency. Most of the input methods are implemented using ime. The following sections mainly discuss the issues that need to be paid attention to and solutions for IME programming.
What is ime? IME is a standard input method Interface Specification used on Windows platforms. It is actually a DLL. Windows defines a series of interfaces for this DLL. Different interfaces implement specified functions. When writing an input method program, programmers only need to implement these interfaces and export them as input methods. The definition of specific interfaces is not the focus of this Article. If you need to understand, you only need to search for "Input Method programming guide" on the network to understand
For more information, see msdn.
At the beginning, the most difficult problem in input method programming is that the program framework has been set up but does not know how to use and debug it. An important problem involved here is the installation of the input method. The input method is a plug-in for windows. You must register the plug-in before Windows can recognize and use it. To do this, you need to copy the generated DLL to the system directory (Windows/system32) before calling the API
Imminstallime can be implemented. In my practice, I first compile a simple program for installation. After each input method recompilation, I call it once to complete the registration of the input method. Note that Windows provides a mechanism that allows the input method to stop exiting once started, this means that if your program code has been modified and needs to be re-installed, you will have to restart your computer. An IME-defined interface provides IME initialization, Which is bool.
Winapi imeinquire (lpimeinfo, lptstr lpszuiclass, lpctstr
Lpszoption), the following code comes from the input method I wrote:
Bool winapi imeinquire (lpimeinfo, lptstr lpszuiclass, lpctstr lpszoption)
{
Lpimeinfo-> dwprivatedatasize = sizeof (contextpriv); // The system allocates space for inputcontext. hprivate.
Lpimeinfo-> fdwproperty = ime_prop_kbd_char_first |
# Ifdef _ Unicode
Ime_prop_unicode |
# Endif
Ime_prop_special_ui |
Ime_prop_end_unload;
Lpimeinfo-> fdwconversioncaps = ime_cmode_fullshape |
Ime_cmode_native;
Lpimeinfo-> fdwsentencecaps = ime_smode_none;
Lpimeinfo-> fdwuicaps = ui_cap_2700;
Lpimeinfo-> fdwscscaps = 0;
Lpimeinfo-> fdwselectcaps = select_cap_conversion;
_ Tcscpy (lpszuiclass, clsname_ui );
Return true;
}
Lpimeinfo-> fdwproperty tells the Windows system about some features of the input method you have compiled. Pay attention to the ime_prop_end_unload mark, the input method you write will exit with the exit of the application that starts your input method (such as NotePad); otherwise, it will remain in the system, this is why many input methods need to restart the computer before upgrading and installing.
Note that lpimeinfo-> dwprivatedatasize can be used to allocate space for inputcontext. hprivate in Windows only after many tests. In addition, if you have modified this interface, I personally need to call imminstallime again to install it.
After installation, you must have your own input method in the input method list. Click Debug. Because it is a DLL, You need to select a Host Program. Generally, select "Notepad" and start "Notepad" in debug mode, open your input method in this notepad, And you can set a breakpoint in the source code. It should be noted that the vc6.0 DLL debugging is not easy to use. First, you need to set SP5 or SP6. In this way, you cannot set breakpoints when the DLL is started. We recommend that you use. Net for debugging.
Input Method context (himc): What is himc? When programming the input method, you must be familiar with the term "input method context". It sounds like you are not familiar with it. As the input method is a plug-in, it needs to communicate with the application that calls it. In the input method, where can the generated encoding and re-code information be correctly read by the application? The answer lies in the input method context. Then, it passes the data to the application.
Uiwnd: an interface needs to be exported in ime. The prototype is lresult winapi uiwndproc (hwnd huiwnd, uint
Message, wparam, lparam
Lparam,, huiwndis the window handle passed by user.exe. It is the window created in the input method, such as the encoding window, the re-code window, and the owner of the status bar window ), beginners may ask where this window is displayed? In fact, it is not a common window, it is just a window for passing Windows messages (Message
Only), you don't need to worry about where it is, just use it.
One IME needs to export 19 (Win98) interfaces, but for a software that only needs to implement general text input, you only need to implement several basic interfaces to make the input method work normally. The following describes these interfaces one by one.
/**********************************************************************/
/* ImeSelect() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL WINAPI ImeSelect(HIMC hIMC,BOOL fSelect)
In this interface, the system notifies you whether the input method is enabled. Generally, the input method is called once at startup. In some software (such as emeditor), the function of enabling and disabling the input method is implemented through this interface. If the input method is enabled, some data initialization work is generally done in this interface.
/*************************************** ********************************/
/* The system calls this interface to determine whether IME processes the current keyboard input */
/* Himc: Input Context */
/* Uint ukey: key value */
/* Lparam lkeydata: Unknown */
/* Const lpbyte lpbkeystate: the keyboard status, including the 256 key status */
/* Return: TRUE-IME processing, false-system processing */
/* The system calls imetoasciiex; otherwise, the keyboard message is directly sent to the application */
/*************************************** *******************************/
Bool winapi imeprocesskey (himc, uint ukey, lparam lkeydata, const lpbyte lpbkeystate)
Observe the annotations and you can see the interface is used to determine which key the user needs to process and which key should be handed over to the system for processing. If the input method needs to process the user's input key, returns true in this interface; otherwise, returns false.
/*************************************** **************************************** *********************************/
/* Function: the application calls this interface to convert the input context. The input method converts the user input in this interface */
/* Uint uvkey: key value. If the ime_prop_kbd_char_first attribute is set for fdwproperty in the imeinquire interface, the high byte value is the input key value */
/* Uint uscancode: Scan code of the key. Sometimes the two keys have the same key value. In this case, uscancode must be used to distinguish between them */
/* Const lpbyte lpbkeystate: the keyboard status, including the 256 key status */
/* Lpdword lpdwtranskey: Message Buffer, used to save messages sent to the application by IME. The first dual-word is the maximum number of messages that the buffer can hold */
/* Uint fustate: Active menu flag (come from msdn )*/
/* Himc: Input Context */
/* Return: return the number of messages saved in the message buffer lpdwtranskey */
/*************************************** **************************************** *********************************/
Uint winapi imetoasciiex (uint uvkey, uint uscancode, const lpbyte lpbkeystate, lpdword lpdwtranskey, uint fustate, himc)
This interface can be said to be the most important part of the input method. In this interface, programmers need to convert the encoding and re-encoding. The conversion is completed or displayed in the encoding window and the re-encoding window, or sent to the application. Because no window handle is input in this interface, what if the window update display of the notification input method program is displayed? The producer processes the messages and transmits them to the uiwnd window.
How to input text? Three messages are required for text input, namely wm_ime_startcomposition, wm_ime_composition, and wm_ime_endcomposition. They indicate that the input encoding starts, the input encoding or result (depending on the parameter), and the encoding is complete. At the beginning of writing the input method, in order to save trouble, my input method continuously calls the three messages to input text to the encoder only when the user determines that a duplicate code is required. Since wm_ime_startcomposition and wm_ime_endcomposition need to be used in pairs, this method ensures that they are paired. At first, this method worked well, but later it was found that some software encountered compatibility problems. For example, this problem exists in "intelligent five strokes" in "traveling". In the address bar of "traveling", open "intelligent five strokes". When you need to use the return key to delete the encoding of incorrect input, you will find that not the encoding in the encoding window, but the text in the editor. Stopped. Therefore, the correct process should be to send wm_ime_startcomposition when the encoding is started, and send the wm_ime_endcomposition message after the input is complete.
/**********************************************************************//* UIWndProc() *//* IME UI window procedure *//**********************************************************************/LRESULT WINAPI UIWndProc(HWND hUIWnd, UINT message,WPARAM wParam, LPARAM lParam)
This is a very important interface, basically it is responsible for the transmission of various messages. Generally, you need to display, hide, and update the input window (such as the encoding window, re-code window, and status bar window) based on different message types in this interface. The functions implemented by this interface may be very complex and vary based on the situation, so we will not go into more details here. For more information, see the sample project.
BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData)
This is the last interface that requires attention. Windows will call this interface when displaying the input method property configuration.
The basic interface is introduced here. Next we will talk about some problems I encountered when writing the input method program or some notes I have found.
1. About the input method window: reading some input method code is strange. Why do I need to specify the wm_disable attribute when creating the input method window? It turns out that if this attribute flag is not specified, enabling the input method will cause the current application to lose the input focus. However, after this flag is specified, the input method window cannot receive the mouse message. What should I do? The solution lies in the message wm_setcursor. This message is received no matter whether the window is available or not, as long as you have a mouse in the window. You can simulate the mouse message in the message or call the setcapture function to receive the mouse message in the window.
2. Window mode: After several input methods are used, you will find that some input methods have the same encoding window and re-code window, and some have two windows. What are their differences? Some people may think this problem is ridiculous, but when you study an input method, you may find that you have similar problems: there are four user interface functions in the export interface of the input method, and the other three categories correspond to three window callback functions. In fact, there is no essential difference between them. The key lies in the scope of your input method. Some software (such as some games) do not want users to display their input method windows when they open the input method for the overall appearance of the interface, instead, you want the input method to display the content to be displayed in the input method window as per its intention.
Aware. Because my own input method is not intended to be used in the game and is not managed according to this rule, I want to simplify it, put the content displayed in the encoding and re-encoding windows in one window.
3. About custom message: uiwndproc provides an imn_private in wm_ime_policy. At first, I understood that the message should be the same as that of wm_user, when I need more than one custom message, I only need to add value based on this ID. However, the fact is that the value you defined may be occupied by the system (depending on the Windows version). You can only use this custom message, to indicate multiple message types, we use the lparam method of wm_ime_policy to differentiate them.
4. debugging information output: Generally, the input method does not use MFC. to output debugging information, you can only use the outputdebugstring API. In the sample code, helper. in C, I wrote a function helper_trace to simulate trace. You can use this function to output debugging information to the debugging window.
5. Finally, let's talk about the input method type: the input method is divided into two types: the external type and the ime type. However, some input methods are developed into 3rd types, which is the advantage of combining these two types. For example, if you start the process, you will find that there is an additional process in the process list. In fact, it is the kernel of the input method, that is, the data processing part. The IME part of Pinyin plus is just a shell, which provides the same system compatibility as the traditional IME input method. I also used this structure in my input method, and used memory file ing and common Windows messages to achieve communication between two processes. You can find the source code of inter-process communication and input code in the source code of my input method.
It seems that there is no more experience. In short, the input method is actually not mysterious. In my opinion, as long as the code can be tracked in VC, I don't believe I will be confused about it!
If you have any mistakes, please criticize and correct them.
Sample Code: The sample code is a framework of the most basic input method program I have compiled. It displays the encoding you entered and a fixed duplicate code, enter a space to enable this function. Generally, the code we can find is a complete project, so that beginners may fall into a large number of non-input encoding frameworks, it does not make much sense for the actual input method programming. This code is used to free you from reading unnecessary code.
If you need a more complete input method code, we recommend that you refer to the source code of "free pinyin". Of course, you can also refer to the code of my input method "Departure input Star, you can find the download, http://www.setoutsoft.cn on my website. I think the Interface part of this Code is well written in the current input method.