今回使う関数はImmGetConversionStatusが主体です。
これは、現在の変換状態をセットします。BOOL ImmGetConversionStatus( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence );
hIMCには、入力コンテキストハンドルを指定します。
lpfdwConversionには、入力モードを受け取る変数へのポインタを指定します。
lpfdwSentenceには、変換モードを受け取る変数へのポインタを指定します。
入力モードは複数の値の組み合わせとなっています。実は、これが変換状態を 設定するときに大変面倒なのです。ヘルプは英語主体の説明なので日本語IMEの 場合どれとどれを組み合わせるかが大変わかりにくいです。 そこで、逆にIMEをいろいろな変換状態にしてその時、変換モードや入力モードが どうなっているかを調べて見ることはあとで、大変役に立ちます。
入力モード値
IME_CMODE_ALPHANUMERIC | 0x0000 |
IME_CMODE_NATIVE | 0x0001 |
IME_CMODE_CHINESE | IME_CMODE_NATIVE |
IME_CMODE_HANGEUL | IME_CMODE_NATIVE |
IME_CMODE_HANGUL | IME_CMODE_NATIVE |
IME_CMODE_JAPANESE | IME_CMODE_NATIVE |
IME_CMODE_KATAKANA | 0x0002 IME_CMODE_NATIVEが設定されているときのみ有効 |
IME_CMODE_LANGUAGE | 0x0003 |
IME_CMODE_FULLSHAPE | 0x0008 |
IME_CMODE_ROMAN | 0x0010 |
IME_CMODE_CHARCODE | 0x0020 |
IME_CMODE_HANJACONVERT | 0x0040 |
IME_CMODE_SOFTKBD | 0x0080 |
IME_CMODE_NOCONVERSION | 0x0100 |
IME_CMODE_EUDC | 0x0200 |
IME_CMODE_SYMBOL | 0x0400 |
IME_CMODE_FIXED | 0x0800 |
ここで、ちょっと気を付けなくてはいけないことがあります。 IME_CMODE_LANGUAGEは2進で11となり、これは
IME_CMODE_NATIVE | IME_CMODE_KATAKANA (これも2進で11となる)
と同じことになります。
変換モード値
IME_SMODE_NONE | 0x0000 |
IME_SMODE_PLAURALCLAUSE | 0x0001 |
IME_SMODE_SINGLECONVERT | 0x0002 |
IME_SMODE_AUTOMATIC | 0x0004 |
IME_SMODE_PHRASEPREDICT | 0x0008 |
IME_SMODE_CONVERSATION | 0x0010 |
IMEの名前を取得するには
を使います。UINT ImmGetDescription( HKL hKL, LPTSTR lpszDescription, UINT uBufLen );
hKLは、入力ロケール識別子を指定します。
lpszDescriptionは、説明文を受け取るバッファのポインタを指定します。
バッファサイズを文字数で指定します。これを0にするとバッファに必要な 文字数が関数の戻り値となります。(ヌル文字は含みません。WindowsNT/2000の時は Unicodeの文字数となります)
入力ロケール識別子がIMEを持つかどうかを調べるには
を使います。BOOL ImmIsIME( HKL hKL );
hKLに入力ロケール識別子を指定するとIMEを持つ場合は0以外が返ります。
全角ひらがな入力、連文節変換の時のATOK13の変換モード値、入力モード値の 組み合わせです。いろいろなモードに切り替えて、その時の値の組み合わせを 調べてみましょう。
では、プログラムを見てみましょう。
メニューとダイアログボックスのリソース・スクリプトです。ダイアログボックスの方は コントロールの数が多くて大変ですが特に難しいところはありません。// ime02x.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)...", IDM_END END POPUP "オプション(&O)" BEGIN MENUITEM "変換状態取得(&X)...", IDM_GETSTATUS END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 255, 205 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "IME変換状態" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,184,50,14 PUSHBUTTON "キャンセル",IDCANCEL,198,184,50,14 CONTROL "IME_CMODE_NATIVE",IDC_NATIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,109,14 CONTROL "IME_CMODE_KATAKANA",IDC_KATAKANA,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,23,109,14 CONTROL "IME_CMODE_FULLSHAPE",IDC_FULLSHAPE,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,39,109,14 CONTROL "IME_CMODE_ROMAN",IDC_ROMAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,109,14 CONTROL "IME_CMODE_CHARCODE",IDC_CHARCODE,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,71,109,14 CONTROL "IME_CMODE_HANJACONVERT",IDC_HANJACONVERT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,87,109,14 CONTROL "IME_CMODE_SOFTKBD",IDC_SOFTKBD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,103,109,14 CONTROL "IME_CMODE_NOCONVERSION",IDC_NOCONVERSION,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,119,109,14 CONTROL "IME_CMODE_EUDC",IDC_EUDC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,135,109,14 CONTROL "IME_CMODE_SYMBOL",IDC_SYMBOL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,151,109,14 CONTROL "IME_CMODE_FIXED",IDC_FIXED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,167,109,14 CONTROL "IMM_SMODE_PLAURALCLAUSE",IDC_PLAURALCLAUSE,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,131,7,109,14 CONTROL "IMM_SMODE_SINGLECONVERT",IDC_SINGLECONVERT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,131,29,109,14 CONTROL "IMM_SMODE_AUTOMATIC",IDC_AUTOMATIC,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,131,51,109,14 CONTROL "IMM_SMODE_PHRASEPREDICT",IDC_PHRASEPREDICT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,131,73,109,14 CONTROL "IMM_SMODE_CONVERSATION",IDC_CONVERSATION,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,131,95,109,14 EDITTEXT IDC_EDIT1,145,151,95,16,ES_AUTOHSCROLL LTEXT "IMEの名前",IDC_STATIC,145,135,41,12 END
imm.hをインクルードするのを忘れないでください。また、imm32.libをプロジェクトに参加させる のも忘れないでください。// ime02x.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <windowsx.h> #include <imm.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); BOOL MyGetStatus(HWND); char szClassName[] = "ime02x"; //ウィンドウクラス BOOL bNative, bKatakana, bFullshape, bRoman, bCharcode, bHanjaconvert, bSoftkbd, bNoconversion, bEudc, bSymbol, bFixed; BOOL bPlauralclause, bSingleconvert, bAutomatic, bPhrasepredict, bConversation; char szName[64];
いつもと同じです。int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるIME", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
親ウィンドウのプロシージャです。//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_GETSTATUS: MyGetStatus(hWnd); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
メニューからIDM_GETSTATUSが選択されたらMyGetStatus関数を呼んで変換状態を 表示します。
変換状態を調べる関数です。BOOL MyGetStatus(HWND hWnd) { HIMC hImc; DWORD dwConv, dwSent; HINSTANCE hInst; HKL hKl; hImc = ImmGetContext(hWnd); if (!ImmGetOpenStatus(hImc)) ImmSetOpenStatus(hImc, TRUE); hKl = GetKeyboardLayout(0); if (!ImmIsIME(hKl)) { MessageBox(hWnd, "IMEを持っていません", "OK", MB_OK); return FALSE; } ImmGetDescription(hKl, szName, 64); ImmGetConversionStatus(hImc, &dwConv, &dwSent); bNative = dwConv & IME_CMODE_NATIVE; bKatakana = dwConv & IME_CMODE_KATAKANA; bFullshape = dwConv & IME_CMODE_FULLSHAPE; bRoman = dwConv & IME_CMODE_ROMAN; bCharcode = dwConv & IME_CMODE_CHARCODE; bHanjaconvert = dwConv & IME_CMODE_HANJACONVERT; bSoftkbd = dwConv & IME_CMODE_SOFTKBD; bNoconversion = dwConv & IME_CMODE_NOCONVERSION; bEudc = dwConv & IME_CMODE_EUDC; bSymbol = dwConv & IME_CMODE_SYMBOL; bFixed = dwConv & IME_CMODE_FIXED; bPlauralclause = dwSent & IME_SMODE_PLAURALCLAUSE; bSingleconvert = dwSent & IME_SMODE_SINGLECONVERT; bAutomatic = dwSent & IME_SMODE_AUTOMATIC; bPhrasepredict = dwSent & IME_SMODE_PHRASEPREDICT; bConversation = dwSent & IME_SMODE_CONVERSATION; ImmReleaseContext(hWnd, hImc); hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); return TRUE; }
最初にIMEの説明文をszNameに取得しています。
ImmGetConversionStatus関数によって取得した入力モード、変換モード値に どの値が含まれるかを調べます。
たとえばdwConvにIME_CMODE_KATAKANAが含まれているとすれば
dwConv & IME_CMODE_KATAKANA
はTRUEとなります。
ダイアログボックスのプロシージャです。LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { HWND hNative, hKatakana, hFullshape, hRoman, hCharcode, hHanjaconvert, hSoftkbd, hNoconversion, hEudc, hSymbol, hFixed; HWND hPlauralclause, hSingleconvert, hAutomatic, hPhrasepredict, hConversation; HWND hName; switch (msg) { case WM_INITDIALOG: hName = GetDlgItem(hDlg, IDC_EDIT1); hNative = GetDlgItem(hDlg, IDC_NATIVE); hKatakana = GetDlgItem(hDlg, IDC_KATAKANA); hFullshape = GetDlgItem(hDlg, IDC_FULLSHAPE); hRoman = GetDlgItem(hDlg, IDC_ROMAN); hCharcode = GetDlgItem(hDlg, IDC_CHARCODE); hHanjaconvert = GetDlgItem(hDlg, IDC_HANJACONVERT); hSoftkbd = GetDlgItem(hDlg, IDC_SOFTKBD); hNoconversion = GetDlgItem(hDlg, IDC_NOCONVERSION); hEudc = GetDlgItem(hDlg, IDC_EUDC); hSymbol = GetDlgItem(hDlg, IDC_SYMBOL); hFixed = GetDlgItem(hDlg, IDC_FIXED); hPlauralclause = GetDlgItem(hDlg, IDC_PLAURALCLAUSE); hSingleconvert = GetDlgItem(hDlg, IDC_SINGLECONVERT); hAutomatic = GetDlgItem(hDlg, IDC_AUTOMATIC); hPhrasepredict = GetDlgItem(hDlg, IDC_PHRASEPREDICT); hConversation = GetDlgItem(hDlg, IDC_CONVERSATION); if (bNative) Button_SetCheck(hNative, BST_CHECKED); else Button_SetCheck(hNative, BST_UNCHECKED); if (bKatakana) Button_SetCheck(hKatakana, BST_CHECKED); else Button_SetCheck(hKatakana, BST_UNCHECKED); if (bFullshape) Button_SetCheck(hFullshape, BST_CHECKED); else Button_SetCheck(hFullshape, BST_UNCHECKED); if (bRoman) Button_SetCheck(hRoman, BST_CHECKED); else Button_SetCheck(hRoman, BST_UNCHECKED); if (bCharcode) Button_SetCheck(hCharcode, BST_CHECKED); else Button_SetCheck(hCharcode, BST_UNCHECKED); if (bHanjaconvert) Button_SetCheck(hHanjaconvert, BST_CHECKED); else Button_SetCheck(hHanjaconvert, BST_UNCHECKED); if (bSoftkbd) Button_SetCheck(hSoftkbd, BST_CHECKED); else Button_SetCheck(hSoftkbd, BST_UNCHECKED); if (bNoconversion) Button_SetCheck(hNoconversion, BST_CHECKED); else Button_SetCheck(hNoconversion, BST_UNCHECKED); if (bEudc) Button_SetCheck(hEudc, BST_CHECKED); else Button_SetCheck(hEudc, BST_UNCHECKED); if (bSymbol) Button_SetCheck(hSymbol, BST_CHECKED); else Button_SetCheck(hSymbol, BST_UNCHECKED); if (bFixed) Button_SetCheck(hFixed, BST_CHECKED); else Button_SetCheck(hFixed, BST_UNCHECKED); if (bPlauralclause) Button_SetCheck(hPlauralclause, BST_CHECKED); else Button_SetCheck(hPlauralclause, BST_UNCHECKED); if (bSingleconvert) Button_SetCheck(hSingleconvert, BST_CHECKED); else Button_SetCheck(hSingleconvert, BST_UNCHECKED); if (bAutomatic) Button_SetCheck(hAutomatic, BST_CHECKED); else Button_SetCheck(hAutomatic, BST_UNCHECKED); if (bPhrasepredict) Button_SetCheck(hPhrasepredict, BST_CHECKED); else Button_SetCheck(hPhrasepredict, BST_UNCHECKED); if (bConversation) Button_SetCheck(hConversation, BST_CHECKED); else Button_SetCheck(hConversation, BST_UNCHECKED); Edit_SetText(hName, szName); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: case IDCANCEL: EndDialog(hDlg, IDOK); return TRUE; } return FALSE; } return FALSE; }
WM_INITDIALOGメッセージが来たときに、各チェックボックスのウィンドウハンドルを 取得しています。そして各BOOL変数に従ってチェックを付けています。最後に IMEの説明文をエディットコントロールに表示しています。
さて、今回はちょっと面倒くさいプログラムでしたが内容は簡単でした。
IMEをいろいろな変換状態にして入力モード、変換モードの値の組み合わせをメモしておいてください。
また、ダイアログボックスのチェックを自分で書き換えて、それがIMEにどう影響するか を調べるプログラムも作ってみてください。
Update 16/Jul/2000 By Y.Kumei