CandidateListを取得する
IMEのCandidateListを取得する方法
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for Page3.xaml
/// </summary>
public partial class Page3 : Page
{
public Page3()
{
InitializeComponent();
}
public class Win32
{
[DllImport("user32.dll")]
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint Msg, uint wParam, IntPtr lPara);
[DllImport("imm32.dll", SetLastError = true)]
public static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport("Imm32.dll")]
public static extern long ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);
[DllImport("imm32.dll")]
public static extern int ImmGetCandidateList(IntPtr hIMC, int iIndex, byte[] lpCandidateList, int iBuffLen);
[DllImport("Imm32.dll")]
public static extern int ImmNotifyIME(IntPtr hIMC, IntPtr dwAction, IntPtr dwIndex, IntPtr dwValue);
}
const int WM_APP = 0x8000;
const int WM_CLOSE = 0x0010;
const int GWL_WNDPROC = -4;
// WM_IME_
const int WM_IME_CHAR = 0x0286;
const int WM_IME_COMPOSITION = 0x010f;
const int WM_IME_COMPOSITIONFULL = 0x0284;
const int WM_IME_CONTROL = 0x0283;
const int WM_IME_ENDCOMPOSITION = 0x010e;
const int WM_IME_KEYDOWN = 0x0290;
// const int WM_IME_KEYLAST = 0x010f;
const int WM_IME_KEYUP = 0x0291;
const int WM_IME_NOTIFY = 0x0282;
const int WM_IME_REPORT = 0x0280;
const int WM_IME_REQUEST = 0x0288;
const int WM_IME_SELECT = 0x0285;
const int WM_IME_SETCONTEXT = 0x0281;
const int WM_IME_STARTCOMPOSITION = 0x010d;
// WM_IME_SETCONTEXT lParam
const int ISC_SHOWUICOMPOSITIONWINDOW = -2147483648;
const int ISC_SHOWUIGUIDWINDOW = -2147483648;
const int ISC_SHOWUISOFTKBD = -2147483648;
const int ISC_SHOWUICANDIDATEWINDOW = 0x0001;
const int ISC_SHOWUIALLCANDIDATEWINDOW = 0x000F;
// WM_IME_NOTIFY wParam
const int IMN_CHANGECANDIDATE = 0x0003;
const int IMN_OPENCANDIDATE = 0x0005;
const int IMN_SETCONVERSIONMODE = 0x0006;
const int IMN_SETOPENSTATUS = 0x0008;
const int IMN_SETCOMPOSITIONFONT = 0x000A; // 10
const int IMN_SETCOMPOSITIONWINDOW = 0x000B; // 11
const int GCS_COMPSTR = 0x0008;
const int GCS_RESULTSTR = 0x0800;
const int GCS_RESULTREADSTR = 0x0200;
const int GCS_COMPREADSTR = 0x0001;
// ImmNotifyIMe dwAction
const int NI_CHANGECANDIDATELIST = 0x0013; // 現在選択している候補を変更した ( dwIndex:変更リストのインデックス dwValue:使わない) (dwIndex:変更リストのインデックス
const int NI_CLOSECANDIDATE = 0x0011; //候補リストをクローズした (dwValue:使わない)
const int NI_COMPOSITIONSTR = 0x0015; // 変換文字列を操作する (具体的な操作はdwIndexで指定する)
const int NI_IMEMENUSELECTED = 0x0018; // 指定のメニューのハンドル (dwIndex:メニューID dwValue:アプリケーション定義の値)
const int NI_OPENCANDIDATE = 0x0010; // 候補リストをオープン
const int NI_SELECTCANDIDATESTR = 0x0012; // 候補の一つを選択した (dwIndex:候補リストのインデックス dwValue:選択した単語のインデックス)
const int NI_SETCANDIDATE_PAGESIZE = 0x0017; // 候補リストのページサイズを変更した(dwValue:0~31の数値)
const int NI_SETCANDIDATE_PAGESTART = 0x0016; // 候補リストを設定した (dwIndex:候補リストを指定する0~31の値)
// ImmNotifyIME dwIndexの定数
const int CPS_CANCEL = 0x0004; // 変換文字列をクリアする
const int CPS_COMPLETE = 0x0001; // 変換文字列を確定文字にする
const int CPS_CONVERT = 0x0002; // 次の候補に変換する
const int CPS_REVERT = 0x0003; // 変換文字列を取り消し、確定前確定前に戻す
// ImmAssociateContextEx dwFlags
const int IACE_CHILDREN = 0x0001;
const int IACE_DEFAULT = 0x0010;
const int IACE_IGNORENOCONTEXT = 0x0020;
int ItextLength = 0;
IntPtr Hwnd;
private string Us100ConverterStr2(byte[] str, int start, int byteNum)
{
if (byteNum + start > str.Length)
{
byteNum = str.Length - start;
}
byte[] str2 = new byte[byteNum];
for (int cnt = 0; cnt < byteNum; cnt++)
{
str2[cnt] = str[cnt + start];
}
return Encoding.Default.GetString(str2);
}
private void WindowMain_SizeChanged(object sender, SizeChangedEventArgs e)
{
InputMethod.Current.ImeState = InputMethodState.On;
TextBoxInput.Focus();
}
private void WindowMain_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("WindowMain Loaded ");
var helper = new WindowInteropHelper(Application.Current.MainWindow);
Hwnd = helper.Handle;
HwndSource source = HwndSource.FromHwnd(Hwnd);
source.AddHook(new HwndSourceHook(WndProc));
// IME Default CandidateWindow を隠す Start (非表示にするとImmGetCandidateList のサイズが設定される)
var lp = ~ISC_SHOWUICANDIDATEWINDOW;
var lParam = new IntPtr(lp);
Win32.DefWindowProc(helper.Handle, WM_IME_SETCONTEXT, 1, lParam); // 3 para は zero 以外
// IME Default CandidateWindow を隠す End
}
public IntPtr WndProc(IntPtr hwnd, int imsg, IntPtr wParam, IntPtr lParam, ref bool bhandled)
{
switch (imsg)
{
case WM_IME_NOTIFY: // 0x0282
Debug.WriteLine("WndProc NOTIFY : " + wParam.ToString("0") + " : " + lParam.ToString("0"));
switch ((int)wParam)
{
case IMN_CHANGECANDIDATE: // 0x0003
ItextLength = TextBoxInput.Text.Length;
bhandled = true;
var himc = Win32.ImmGetContext(hwnd);
var isize = Win32.ImmGetCandidateList(himc, 0, null, 0);
if (isize > 0)
{
Debug.WriteLine("CandidateChange isize : " + isize.ToString("0"));
byte[] bytebuf = new byte[isize];
ListBoxA.Items.Clear();
Win32.ImmGetCandidateList(himc, 0, bytebuf, (int)isize);
int icount = System.BitConverter.ToInt32(bytebuf, 8);
for (int cnt = 0; cnt < icount; cnt++)
{
int iOffset = System.BitConverter.ToInt32(bytebuf, cnt * 4 + 24);
int len = 0;
while (bytebuf[iOffset + len] != '\0')
{
len++;
}
ListBoxA.Items.Add(Us100ConverterStr2(bytebuf, iOffset, len));
}
Win32.ImmReleaseContext(hwnd, himc);
}
break;
default:
Debug.WriteLine("WM_IME_NOTIFY 3 以外 : " + wParam.ToString("0") + lParam.ToString("0"));
break;
}
break;
default:
break;
}
if (!bhandled)
{
Win32.DefWindowProc(hwnd, (uint)imsg, (uint)wParam, lParam);
}
return IntPtr.Zero;
}
private void ListBoxA_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var iidx = ListBoxA.SelectedIndex;
if (iidx >= 0)
{
var slist = ListBoxA.Items[iidx].ToString();
TextBoxInput.Text = TextBoxInput.Text + slist;
var himc = Win32.ImmGetContext(Hwnd);
Win32.ImmNotifyIME(himc, (IntPtr)NI_SELECTCANDIDATESTR, (IntPtr)iidx, IntPtr.Zero);
Win32.ImmReleaseContext(Hwnd, himc);
}
}
}
}