A Typing Program Sample based on Win32 Multilingual IME

(the IME mechanism in this example is outdated and not working in Windows Vista. Please refer to the TSF example)

By Y Lam (yick.lam@gmail.com), Hong Kong, China (Last Update: 2003-07-08)


    This tutorial is based on a sample code YLam Input. You enter an email address below to get a link to download it.

Name: Email:

I will first describe what YLam Input does, how to install etc. Later on, I will talk about the code.


What does YLam Input sample code do:

    If you are familiar with Far East (Chinese, Japanese and Korean) Version of Windows 95/98/ME, you may notice that there are some *.ime files in windows\system directories. They are actually programs that change your keystrokes to some characters that output to different applications. The sample code is a demonstration on how to write these *.ime files.

    Here is a screen capture (in Traditional Chinese Windows) of YLam Input:

   

Purpose of the sample code:

    Provide sample code to programmers who are:

  • strong in C, C++ programming

  • have knowledge but not so familiar with Windows MFC programming, Windows DLL Programming

  • have no idea in Windows IME mechanism.

  • to develop his/her own input method. The sample code provided ideas on how to implement basic functionalities like how to

  • capture all key stroke

  • draw simple UI  and implement basin UI functionality like dragging

  • send strings to applications

  • that is need by any input method. Programmers can add functionality like lookup tables to this sample and write his own input method.

        However, many of Win32 IME feature are not shown:

    Please find relevant sample codes from Microsoft.

    How to compile the sample code:  

        You MUST have Visual C/C++ 6.0 or later. I assume you have installed it

    D:\Program Files\Microsoft Visual Studio\VC98

    and your windows is in C:\windows

        Here are the steps to compile and install the sample code:

    How to install the sample code:


    Explanation of the source code:

        The following is based on my understanding of Win32 IME from various sources and sometimes what is described here may be even WRONG! Please refer to Microsoft documentation if required.

        Here is the picture of Win32 IME in my mind:

        For each input method, there is one instance of IME Conversion Interface. When a user in an application (for example Microsoft Word, Internet Explorer etc) started a Input Method, a "Input Context" will be created. The IME conversion interface communicates with the Windows Application through these Input Context.

    IME Conversion Interface

        An *.ime file actually is a Windows DLL. It should provide the following functions so that the Windows 95/98/ME can recognize it as a Input Method:

    ImeConversionList
    ImeConfigure
    ImeDestroy
    ImeEscape
    ImeInquire
    ImeProcessKey
    ImeSelect
    ImeSetActiveContext
    ImeToAsciiEx
    NotifyIME
    ImeRegisterWord
    ImeUnregisterWord
    ImeGetRegisterWordStyle
    ImeEnumRegisterWord
    ImeSetCompositionString

        You MUST declare them in a *.def file in the Visual C/C++ project. For some of them, I don't even what they do, but some of them (those bolded) are important ones and must be implemented. I will explain them later.

    IME UI

        "An IME is expected to register its own UI class for the system. The UI class provided by each IME should be responsible for IME-specific functionality. The IME should register the classes that are used by IME itself when the IME is attached to the process. This occurs when DLLEntry is called with DLL_PROCESS_ATTACH. The IME then has to set the UI class name in the lpszClassName parameter, which is the second parameter of ImeInquire." (from Win32 Multilingual IME Overview for IME Development, MSDN)

    What is the order of the functions are called?

        I think the best way to make people understand how the source code work is to describe what functions are called, starting from a user switch a IME on in a application, hit a key and then how a string is sent to the application.

    1. When you first turn your computer on, Windows will collect all the name of the input methods registered in the Windows Registry (use regedit to view). The registry entries related to input methods are:
      • HKEY_CURRENT_USER\keyboard\layout\preload
      • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Keyboard Layouts
      @

      Windows will extract the Input Method icon  (see ResourceView / ICON / YLAMIMEICON in Visual C/C++ project downloaded above) and the input method name (see ResrouceView / VERSION / FileDescription) from the *.ime
    2. Now supposed you turned on Microsoft Word and then switch to "YLam IME" Input method. The following functions will be called and what I do in these functions:
      1. DLLMain -- Here I registered 2 windows classes namely UI_CLASS_NAME and STATUS_CLASS_NAME. Please note the windows procedure for the IME UI class is UIWndProc and for status window is StatusWndProc.
      2. If this is the first time you started the input method after you started Windows, so ImeInquire will be called. I just initialize set some field of IMEInfo and also the UIClass name of the IME.
      3. ImeSelect -- here the size of Composition String in the input context is resized. The sample code for resizing the input method can be found from "Access the HIMCC section in Win32 Multilingual IME Overview, MSDN". I borrowed the idea from there!
      4. UIWndProc (with msg = WM_CREATE) --  here the memory block for the window instance is allocated. The sample code for this can be found in "UI Window section in Win32 Multilingual IME Overview, MSDN".
      5. UIWndProc (with msg = WM_IME_SELECT) --  nothing is done here.
      6. UIWndProc (with msg = WM_IME_NOTIFY and wParam = IMN_OPENSTATUSWINDOWS) -- please note that this function is handled with a function NotifyHandle. Here the status windows is created and displayed.
      7. StatusWndProc calls. I assume you have programming experience with Win32 and you should be quite familiar with these callback functions.
      8. Other not so important calls....
    3. Suppose you hit a key 'B'. Here is what will happen:
      1. IMEProcessKey will be called. If you return false or true to determine whether to process this key or not. If you return true, IMEAsciiEx will be called. In my sample program I always return true as hitting any key will output the string "apple" to the application. Please also note, sometimes you may want to update the user interface when a user hits a key. You can do it through the function MyGenerateMessage (I spent so much time to find out the use of this function). This is how IME Conversion Interface communicate with Input Context and the UI. Calling MyGenerateMessage in the IME Conversion interface side will result in the Input Context side's UIWndProc (with msg = WM_IME_NOTIFY be called). In my sample code, I have passed wParam = IMN_CHANGE_CANDIDATE (IMN_CHANGE_CANDIDATE is created by me, and you can create your own signal type) to  MyGenerateMessage  and as a result, UIWndProc (with msg=WM_IME_NOTIFY and wParam = IMN_CHANGE_CANDIDATE) is called. The NotifyHandler is then called and the UI is updated.
      2. IMEAsciiEx is called. Here the string "apple" is sent to application. By saying "send a string to application", I mean send the application the following signals:
        1. WM_IME_STARTCOMPOSITION
        2. WM_IME_COMPOSITION (with wParam = GCS_RESULTSTR)
        3. WM_IME_ENDCOMPOSITON
        How can the IME Conversion Interface send message to the application? You can call MyGenerateMessageToTransKey function written by me. The code of this function is copied from "Generating Messages section in Win32 Multilingual IME Overview, MSDN).

    Miscellaneous Note

    Bibliography