[轉貼] C# IME 輸入法 教程

2012072709:18
出處:http://hi.baidu.com/752664788/item/3e950d5275f677dfd48bacd2

首先,我要介紹一下編寫這個控件的核心dll:

DLL 文件: imm32.dll
DLL 名稱: Microsoft Windows IMM32 API Client DLL 或
描述:
imm32.dll是微軟Microsoft Windows輸入法管理相關文件。
屬於: Microsoft Windows (IMM)

   我們要做的,就是調用這個dll中的:
        [DllImport("Imm32.dll")]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
和:
    [DllImport("Imm32.dll")]
    public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);

簡單介紹一下:
ImmAssociateContext,這個api函數是調用輸入法的,第一個句柄是要調用輸入法的控件或窗體的句柄,第二個是不太好解釋,簡單說下要在IME中檢索或設置信息,應用程序必須首先獲得一個與指定窗口相關聯的輸入上下文的句柄。你可以通過ImmGetContext函數來獲得這個句柄,這樣說很彆扭啊,不知朋友們能否理解?

ImmGetContext這個api是為ImmAssociateContext它的第二個參數準備的,他的參數是控件或窗體的句柄,返回的是某控件聯繫上下文的句柄。如果你不理解,其實也無所謂,理論性的東西,誰叫微軟搞的這麼抽像呢!
下一步,我們新建一個winform創意,放上一個label控件,name是label1

我先把代碼貼出來,因為過程十分簡單,我也不做太多的介紹了:
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;
namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        IntPtr m_hImc;
        public const int WM_IME_SETCONTEXT = 0x0281;
        private const int WM_CHAR = 0x0102;
        private const int WM_IME_COMPOSITION = 0x010F;
        private const int GCS_COMPSTR = 0x0008;
        [DllImport("Imm32.dll")]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
        [DllImport("Imm32.dll")]
        public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
        private const int HC_ACTION = 0;
        private const int PM_REMOVE = 0x0001;
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
            {
                ImmAssociateContext(this.Handle, m_hImc);
            }
            switch (m.Msg)
            {
                case WM_CHAR:
                    KeyEventArgs e = new KeyEventArgs(((Keys)((int)(m.WParam))) | ModifierKeys);
                    if (e.KeyCode == Keys.Back)
                        ChangeChar("back");
                    else if (e.KeyCode == Keys.Enter)
                        ChangeChar("enter");
                    else
                    {
                        char a = (char)e.KeyData;
                        intoText(a.ToString());
                    }
                    break;
            }
        }
        private void intoText(string a)
        {
            label1.Text += a;
        }
        void ChangeChar(string a)
        {
            switch (a)
            {
                case "back":
                    if (label1.Text.Length > 0)
                        label1.Text = label1.Text.Remove(label1.Text.Length - 1);
                    break;
                case "enter":
                    label1.Text += "\r\n";
                    break;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            m_hImc = ImmGetContext(this.Handle);
        }
    }
}