第279章 IMEの操作 その2


今回は、IMEの変換状態を取得します。


今回使う関数はImmGetConversionStatusが主体です。

BOOL ImmGetConversionStatus( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence );

これは、現在の変換状態をセットします。

hIMCには、入力コンテキストハンドルを指定します。

lpfdwConversionには、入力モードを受け取る変数へのポインタを指定します。

lpfdwSentenceには、変換モードを受け取る変数へのポインタを指定します。

入力モードは複数の値の組み合わせとなっています。実は、これが変換状態を 設定するときに大変面倒なのです。ヘルプは英語主体の説明なので日本語IMEの 場合どれとどれを組み合わせるかが大変わかりにくいです。 そこで、逆にIMEをいろいろな変換状態にしてその時、変換モードや入力モードが どうなっているかを調べて見ることはあとで、大変役に立ちます。

入力モード値
IME_CMODE_ALPHANUMERIC0x0000
IME_CMODE_NATIVE0x0001
IME_CMODE_CHINESEIME_CMODE_NATIVE
IME_CMODE_HANGEULIME_CMODE_NATIVE
IME_CMODE_HANGULIME_CMODE_NATIVE
IME_CMODE_JAPANESEIME_CMODE_NATIVE
IME_CMODE_KATAKANA0x0002
IME_CMODE_NATIVEが設定されているときのみ有効
IME_CMODE_LANGUAGE0x0003
IME_CMODE_FULLSHAPE0x0008
IME_CMODE_ROMAN0x0010
IME_CMODE_CHARCODE0x0020
IME_CMODE_HANJACONVERT0x0040
IME_CMODE_SOFTKBD0x0080
IME_CMODE_NOCONVERSION0x0100
IME_CMODE_EUDC0x0200
IME_CMODE_SYMBOL0x0400
IME_CMODE_FIXED0x0800

ここで、ちょっと気を付けなくてはいけないことがあります。 IME_CMODE_LANGUAGEは2進で11となり、これは

IME_CMODE_NATIVE | IME_CMODE_KATAKANA (これも2進で11となる)

と同じことになります。

変換モード値
IME_SMODE_NONE0x0000
IME_SMODE_PLAURALCLAUSE0x0001
IME_SMODE_SINGLECONVERT0x0002
IME_SMODE_AUTOMATIC0x0004
IME_SMODE_PHRASEPREDICT0x0008
IME_SMODE_CONVERSATION0x0010

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

メニューとダイアログボックスのリソース・スクリプトです。ダイアログボックスの方は コントロールの数が多くて大変ですが特に難しいところはありません。

// 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];

imm.hをインクルードするのを忘れないでください。また、imm32.libをプロジェクトに参加させる のも忘れないでください。

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にどう影響するか を調べるプログラムも作ってみてください。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 16/Jul/2000 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。