IME関連
Aleaさんのとこから(http://d.hatena.ne.jp/alea/20050715#p1)。
コンソールアプリ中でウィンドウハンドルを渡すという話があったので、コンソールウィンドウにユニークなタイトルを付けてFindWindowでハンドルを入手してみたけど、Imm系の関数呼び出しは失敗してしまった。ウィンドウハンドルを渡せばいいというものではないみたい。(^^;
ふと思い立ってImm系の関数をC#から呼んでみた。(無駄にC#2.0で組んでいます)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; unsafe public struct CANDIDATELIST { public uint dwSize; public uint dwStyle; public uint dwCount; public uint dwSelection; public uint dwPageStart; public uint dwPageSize; public fixed uint dwOffset[1]; } public enum GCL : uint { CONVERSION = 0x0001, REVERSECONVERSION = 0x0002, REVERSE_LENGTH = 0x0003, } unsafe public class Imm { [DllImport("imm32")] public extern static IntPtr ImmGetContext(IntPtr hWnd); [DllImport("imm32")] public extern static bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC); [DllImport("imm32")] public extern static uint ImmGetConversionList(IntPtr hKL, IntPtr hIMC, string src, sbyte lpDst, uint dwBufLen, GCL uFlag); } public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("user32")] internal extern static IntPtr GetKeyboardLayout(uint idThread); static void GetConversionList(IntPtr hWnd, string src, List<string> dst) { IntPtr hIMC = Imm.ImmGetContext(hWnd); IntPtr hKL = GetKeyboardLayout(0); uint dwSize = Imm.ImmGetConversionList(hKL, hIMC, src, null, 0, GCL.REVERSECONVERSION); sbyte buf = new sbyte[dwSize]; Imm.ImmGetConversionList(hKL, hIMC, src, buf, dwSize, GCL.REVERSECONVERSION); unsafe { fixed (sbyte* p = &buf[0]) { CANDIDATELIST* lpCand = (CANDIDATELIST*)p; for (uint i = 0; i < lpCand->dwCount; ++i) dst.Add(new string(p + lpCand->dwOffset[i])); } } Imm.ImmReleaseContext(hWnd, hIMC); } private void button1_Click(object sender, EventArgs e) { List<string> dst = new List<string>(); GetConversionList(this.Handle, "明日", dst); foreach (string s in dst) MessageBox.Show(s); } }
P/Invokeで文字列と構造体のポインタを渡すところはstringとsbyte[]でいいのですが、戻ってきた後でunsafeになるのがちょっと嫌。Marshalクラス使ってマネージドオブジェクトに詰め直せばなんとかなるけど、それも効率悪いし。