2009年3月19日木曜日

Change IME in web page

  How to change IME in web page bothered us for a long time. Note I means change IME and not IME mode. IME mode can be changed in IE by setting styles which like style="ime-mode:active". But how to change IME? I have two IME in my windows xp. One is Microsoft IME Standard 2003, and one is Google IME. In the normal cases I use Microsoft IME Standard 2003 to input datas and in some special cases I need to use Google IME. It seems there is no way to change IME with Java applet or Javascript. IME is obviously depending on the system, so I think maybe JNI(Java Native Interface) is the only way. But what windows api should I use become an another problem. I used ActivateKeyboardLayout with flag KLF_SETFORPROCESS at first and it worked well under jre1.5. But when jre was upgraded to 1.6u10, it no longer worked because Java Plug-In's architecture has been substantially redesigned. In the release note of jre 6u10 it said "Rather than executing applets in a Java virtual machine (JVM) instance which is embedded in the web browser's process, the JVM instance which executes the applet is now a separate process from the web browser." It can be found in the url: http://java.sun.com/javase/6/webnotes/6u10/plugin2/version-selection/index.html It means before jre 1.6, when I used ActivateKeyboardLayout, it changed the applet's IME. Because the applet is embedded in the web browser's process, so web browser's IME was also changed. But since 1.6u10 the applet's process is different to the web browser's so ActivateKeyboardLayout changed the applet's IME and could not change the web browser's. I googled the solution for a long time and this time I could not find the answer, but I got a edification from them. PostMessage is used to post message to the window and if I can post the IME change message to the web browser's window, whether applet's process is same to web browser or not, IME will be changed. And a bit of test codes proved that this is the right way. Use PostMessage with WM_INPUTLANGCHANGEREQUEST, the IME has been changed successfully.

  To get keyboard layout handle, use the function below:
JNIEXPORT jlong JNICALL Java_XXXX_getImeHkl(JNIEnv *env, jobject obj){
    HKL hkls[100];
    HKL hklGgl = NULL;
    UINT nCount, i;
    long lLangId;

    //get the keyboard layout list
    memset(hkls, '\0', sizeof(hkls));
    nCount = GetKeyboardLayoutList(100, hkls);
    //find the handle of Google IME
    for(i=0; i<nCount; i++){
        memset(szName, '\0', sizeof(szName));
        ImmGetDescription(hkls[i], szName, 200);
        if(strcmp(szName, "Google IME's Name") == 0){
            hklGgl = hkls[i];
            break;
        }
    }

    return (long)hklGgl;
}

  To change the IME, use the function below:
JNIEXPORT void JNICALL Java_XXXX_changeIme(JNIEnv *env, jobject obj, jlong lHkl){
//    ActivateKeyboardLayout((HKL)lHkl, KLF_SETFORPROCESS);
    HKL curHkl;
    HKL hkl = (HKL)lHkl;
    HWND hwnd = GetForegroundWindow();
    curHkl = GetKeyboardLayout(GetWindowThreadProcessId(hwnd, NULL));
    if(curHkl != hkl){
        PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET,(LPARAM)hkl);
    }

    return;
}

0 件のコメント:

コメントを投稿