利用IME完成接收輸入法輸入功能.

来源:https://www.cnblogs.com/kent-apple/archive/2018/09/24/9696106.html
-Advertisement-
Play Games

調用windows的imm32.dll完成窗體接收輸入法功能. 代碼如下 public ImeComponent(Form from) { var handle = from.Handle; hIMC = ImmGetContext(handle); this.handle = handle; } ...


調用windows的imm32.dll完成窗體接收輸入法功能.

代碼如下

   /// <summary>
    /// 輸入法組件
    /// </summary>
    class ImeComponent
    {
        #region Event
        /// <summary>
        /// 輸入文本事件
        /// </summary>
        public delegate void InputTextEvent(string text);
        /// <summary>
        /// 輸入文本事件
        /// </summary>
        public event InputTextEvent InputText;
        #endregion

        #region PrivateField
        IntPtr hIMC;
        IntPtr handle;
        private const int WM_IME_SETCONTEXT = 0x0281;
        private const int WM_IME_CHAR = 0x0286;
        private const int WM_CHAR = 0x0102;
        private const int WM_IME_COMPOSITION = 0x010F;
        private const int GCS_RESULTSTR = 0x0800;
        private const int GCS_COMPSTR = 0x0008;
        #endregion

        #region Construction
        public ImeComponent(UserControl control)
        {
            var handle = control.Handle;
            hIMC = ImmGetContext(handle);
            this.handle = handle;
        }
     

      public ImeComponent(Form from)
      {
        var handle = from.Handle;
        hIMC = ImmGetContext(handle);
        this.handle = handle;
      }

#endregion

        #region Method
        /// <summary>
        /// 輸入事件
        /// </summary>
        /// <param name="m"></param>
        public void ImmOperation(Message m)
        {
            if (m.Msg == ImeComponent.WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
            {
                this.ImmAssociateContext(handle);
            }
            else if (m.Msg == WM_IME_COMPOSITION)
            {
                var res = m.WParam.ToInt32();
                string text = CurrentCompStr(this.handle);
                if (!string.IsNullOrEmpty(text))
                {
                    InputText(text);
                }
            }
            else if (m.Msg == WM_CHAR)
            {
                char inputchar = (char)m.WParam;
                if (inputchar > 31 && inputchar < 127)
                {
                    InputText(inputchar.ToString());
                }
            }
        }
        /// <summary>
        /// 當前輸入的字元串流
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public string CurrentCompStr(IntPtr handle)
        {
            try
            {
                int strLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, null, 0);
                if (strLen > 0)
                {
                    var buffer = new byte[strLen];
                    ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buffer, strLen);
                    return Encoding.Unicode.GetString(buffer);
                }
                else
                {
                    return string.Empty;
                }
            }
            finally
            {
                ImmReleaseContext(handle, hIMC);
            }
        }
        #endregion

        #region Win Api
        /// <summary>
        /// 建立指定輸入環境與視窗之間的關聯
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        private IntPtr ImmAssociateContext(IntPtr hWnd)
        {
            return ImeComponent.ImmAssociateContext(hWnd, hIMC);
        }

        [DllImport("imm32.dll")]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
        [DllImport("Imm32.dll")]
        public static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);
        [DllImport("Imm32.dll")]
        private static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern int ImmCreateContext();
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern bool ImmDestroyContext(int hImc);
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SetFocus(IntPtr hWnd);
        [DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
        private static extern int ImmGetCompositionStringW(IntPtr hIMC, int dwIndex, byte[] lpBuf, int dwBufLen);
        [DllImport("imm32.dll")]
        static extern int ImmGetCompositionString(IntPtr hIMC, int dwIndex, StringBuilder lPBuf, int dwBufLen);
        #endregion
    }

此外還需要重構一下窗體或控制項的WndProc方法

代碼如下:

     /// <summary>
        /// win消息
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (isInitialization)
            {
                this.imeComponent.ImmOperation(m); //輸入法
            }
        }

需要註意的是要保證輸入法組件在實例化之後才會執行對象的ImmOperation方法.

這樣修改之後綁定事件即可接收到鍵盤輸入.

 

水平有限難免有所紕漏,如有錯誤請留言指出.=_=


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 閑來無事,買了一個雲伺服器來玩玩。想要做的第一件事情就是搭建web項目,查詢了網上的資料得知,部署web項目的步驟是 (1)配置java環境(這裡選擇的是jdk1.8) (2)配置tomcat伺服器(這裡選擇的是tomcat7) (3)上傳web項目 (4)訪問web項目 那麼就開始我們的第一步和第 ...
  • 隨著微處理機技術的發展,人們只需花幾百美元就能買到一個CPU晶元,這個晶元每秒鐘執行的指令比80年代最大的大型機的處理機每秒鐘所執行的指令還多。如果你願意付出兩倍的價錢,將得到同樣的CPU,但它卻以更高的時鐘速率運行。因此,最節約成本的辦法通常是在一個系統中使用集中在一起的大量的廉價CPU。所以,傾... ...
  • 在我們的應用程式中日誌是不可缺少的部分,在Apache中由一個功能無比強大的日誌組件,它提供了方便的日誌記錄,這個開源的項目就是我們慣用的Log4j,jar包我麽們一顆取Apache官網下載最新版本的。log4j下載地址 一.入門篇 1.打開我們的Eclipse新建一個Java項目並且導入Log4j ...
  • 在開源文件大行其道的今天,基於java種種解決方案和框架紛繪踏至而來,猶如浩瀚如海,看不完也學不盡。在採用這些解決方案和框架進行項目開發時,往往會出現當程式卡殼時,既無異常提示信息亦沒有與之對應的日誌輸出的局面。每每出現這樣的困境時,往往只能通過打斷點來一步一步調試跟蹤來解決。更有甚者,基於某一底層... ...
  • 題目介紹:現在輸入一組數據,寫入學生的考試分數。已知學生數為N,學生編號為1到N,且0<N<=30000,每個學生都有一個分數;操作數為M且0<M<5000。輸入第一行為N M,接下來是1行N列數據代表學生的初試分數,接下來是M行操作數據。已知操作有兩種,分為Q和U。一次操作的格式為 C A B,當 ...
  • 線性表是一種隨機存取的結構,和鏈表不同,鏈表順序存取的結構。但是,線性表是一種順序存儲的結構,而鏈表是鏈式存儲結構。兩者都是線性的,但區別不同。 進入主題: 1.假如有一串數據元素,要求刪除其中的重覆元素。 首先想到的是用兩層迴圈,第一層從第一個元素開始,第二層從第一層元素的下一個元素開始。 就是假 ...
  • 1、指令:<%@ 指令名 屬性名="值"%> 1) page:page指令告訴servlet容器,這是一個Jsp頁面 pageEncoding 指頁面文本的字元集編碼 contentType 告訴Browser 和Servlet端,要使用哪個格式哪個字元集進行解析 獨立的@page指令,可以使用im ...
  • 在分散式系統中,服務發生異常是很正常的現象。為了處理這類“例外”,可以採取不同的應對策略,斷路器模式即是其中一種方法。這個模式的主要特點是其可以阻斷失敗的級聯影響,不會因為一個服務的失敗導致其它關聯服務一併失敗。 在Spring Cloud生態系統中有Hystrix類庫可以提供這個模式的解決方案,而 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...