正しい IME の殺し方
正直、どうやったらええのんかなあと。
Windows だと WINNLSEnableIME だかなんだかいう(旧式の)API 一発でとりあえず切り離せたのですが、OS/2 の PM にも似たような API がありまして…
/* PMNLSSSC.15 -> ULONG APIENTRY WinDBCSModeControl(HAB, HWND, ULONG, ULONG, PULONG); PMNLSSSC.16 -> ULONG APIENTRY WinDBCSIMEControl(HAB, HWND, ULONG, PIMEMODE); */ static HMODULE hmIMDll = NULLHANDLE; typedef struct my_IMEMODE { ULONG lenIMEMODE; ULONG fIMEMode; ULONG hIME; ULONG hModIME; } myIMEMODE; static ULONG (APIENTRY *myWinDBCSModeControl)(HAB, HWND, ULONG, ULONG, PULONG); static ULONG (APIENTRY *myWinDBCSIMEControl)(HAB, HWND, ULONG, myIMEMODE *); BOOL myDBCSEnableIME(HAB hab, HWND hFrame, BOOL bActive) { ULONG imeEnable = 1; /* DBE_IMCTL_IMEENABLE */ ULONG imeDisable = 2; /* DBE_IMCTL_IMEDISABLE */ ULONG imemodemask = ~(imeEnable | imeDisable); BOOL prevmode; myIMEMODE imm; if (myWinDBCSIMEControl == 0) return FALSE; memset(&imm, 0 ,sizeof(imm)); imm.lenIMEMODE = sizeof(imm); (*myWinDBCSIMEControl)(hab, hFrame, 1 /* DBE_IMCTL_QUERY */, &imm); prevmode = (imm.fIMEMode & imemodemask) == imeEnable; imm.fIMEMode &= imemodemask; imm.fIMEMode |= bActive ? imeEnable : imeDisable; (*myWinDBCSIMEControl)(hab, hFrame, 2 /* DBE_IMCTL_SET */, &imm); return prevmode; } ULONG loadIMDll() { ULONG rc; PSZ dllname = (PSZ)"PMNLSSSC.DLL"; HMODULE hm = NULLHANDLE; char errpn[_MAX_PATH]; if (hmIMDll) return 0; rc = DosLoadModule(errpn, sizeof(errpn), dllname, &hm); if (rc != 0) return rc; hmIMDll = hm; myWinDBCSIMEControl = 0; rc = DosQueryProcAddr(hm, 16L, NULL, (PFN *)&myWinDBCSIMEControl); if (rc != 0) return rc; myWinDBCSModeControl = 0; rc = DosQueryProcAddr(hm, 15L, NULL, (PFN *)&myWinDBCSModeControl); return rc; }
(OS/2 だと、こういうしょーもない関数ほど Windows に比べて行数多めになるのは何故だろう…いや、API にポインタ引数が多いからですが……)
これで一応 Alt-漢字 を押しても変換モードにはならなくなる…のですが、かな漢以外の日本語入力機能は依然として有効だったりする。つまり全角/半角、ひらがな/カタカナ、英数あたりが利いてしまう。単に各キーに一対一で対応する仮想キーコード(がなければスキャンコードでも可)が欲しいだけのときはまだダメなのでした。WndProc のメッセージを捕まえて NLS 方面の特殊キーコードをどうにかしないとダメなのか(実はこのへん、Windows も似たり寄ったりだけど)。あと Warp V4 以上向けの IM32 API(Win9x で実装された IME 方面の API とほぼ同等、というかクリソツ)でこのへん楽になるとも思えないしなあ。
なんかメンドくさくなってきたので、もっと適当にやっつけることにした。メッセージキューのコードページを非 DBCS 圏に切りかえちゃえば IME とあっさりおさらばできるのですよな、実は。
int SwitchToSBCSCp(HMQ hmq) { int rc = 1; ULONG cp; cp = WinQueryCp(hmq); switch(cp) { case 932: case 942: /* Japan */ case 934: case 944: /* Korea */ case 936: case 946: /* PRC */ case 938: case 948: /* Taiwan */ if ((rc = WinSetCp(hmq, 850)) == 0) rc = WinSetCp(hmq, 437); default: break; } return rc; }
しかしウィンドウ内で日本語なんか使わねえ、とか開き直っていないとできないソリューション。
ちなみにメッセージキューと OS/2 システム側のコードページはそれぞれ個別に設定可能で、日本語 OS/2 だとシステムコードページは基本的に 932 と 437 しか選べませんが、メッセージキューのコードページはかなり無節操に選択可能なようです。というか設定可能なコードページのリストを API (WinQueryCpList) で調べたら 108 エントリあったヨ…。