搜索

C# 的输入法

Mar 12, 2017 pm 04:07 PM

C# 输入法

    虽说输入法不是什么新事物,各种语言版本都有,不过在C#不常见;这就会给人一种误会:C#不能做!其实C#能不能做呢,答案是肯定的——三种方式都行:IMM、TSF以及外挂式。IMM这种就是调windows的一些底层api,不过在新版本的windows中基本上已经不能用了,属于一种过时的操作方式。TSF是微软推荐的一种新方式,不过相对C#资料太少;线上主要的一些都是针对C++的版本资料,当然可以作为借鉴来实现C#版的。我这里主要介绍一种外挂式的(天啦撸,C#可以写外挂?),对于高手来说肯定不值一提,不过也算是实现了外挂及输入法!题外话——C#可以做外挂么?答案是可以的,C#针对windows的api编程资料还是很多的,下面就简单的介绍一下面可能要使用到的api:

 

安装了一个钩子,截取鼠标键盘等信号

public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

 

停止使用钩子

public static extern bool UnhookWindowsHookEx(int idHook);

 

通过信息钩子继续下一个钩子

public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);

 

 

线程钩子需要用到

static extern int GetCurrentThreadId();

 

使用WINDOWS API函数代替获取当前实例的函数,防止钩子失效

public static extern IntPtr GetModuleHandle(string name);

 

转换指定的虚拟键码和键盘状态的相应字符或字符

public static extern int ToAscii(int uVirtKey, //[in] 指定虚拟关键代码进行翻译。
                                        int uScanCode, // [in] 指定的硬件扫描码的关键须翻译成英文。高阶位的这个值设定的关键,如果是(不压)
                                        byte[] lpbKeyState, // [in] 指针,以256字节数组,包含当前键盘的状态。每个元素(字节)的数组包含状态的一个关键。如果高阶位的字节是一套,关键是下跌(按下)。在低比特,如果设置表明,关键是对切换。在此功能,只有肘位的CAPS LOCK键是相关的。在切换状态的NUM个锁和滚动锁定键被忽略。
                                        byte[] lpwTransKey, // [out] 指针的缓冲区收到翻译字符或字符。
                                        int fuState);

 

1.有了以上的这些api基本上就可能实现鼠标键盘的监控或者锁定等;那么首先要安装钩子:


   // 安装键盘钩子 public void Start()
        {         
            if (hKeyboardHook == 0)
            {
                KeyboardHookProcedure = new HookProc(KeyboardHookProc);

                hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);                //如果SetWindowsHookEx失败
                if (hKeyboardHook == 0)
                {
                    Stop();                    throw new Exception("安装键盘钩子失败");
                }
            }
        }

 

2.安装完后就要对获取到钩子进行处理:


private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {            // 侦听键盘事件
            if (nCode >= 0 && wParam == 0x0100)
            {
                KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));                #region 开关                if (MyKeyboardHookStruct.vkCode == 20 || MyKeyboardHookStruct.vkCode == 160 || MyKeyboardHookStruct.vkCode == 161)
                {
                    isLocked = isLocked ? false : true;
                }                #endregion

                #region
                if (isLocked)
                {                    if (isStarted && MyKeyboardHookStruct.vkCode >= 48 && MyKeyboardHookStruct.vkCode <= 57)
                    {                        var c = int.Parse(((char)MyKeyboardHookStruct.vkCode).ToString());
                        OnSpaced(c);
                        isStarted = false;                        return 1;
                    }                    if (isStarted && MyKeyboardHookStruct.vkCode == 8)
                    {
                        OnBacked();                        return 1;
                    }                    if ((MyKeyboardHookStruct.vkCode >= 65 && MyKeyboardHookStruct.vkCode <= 90) || MyKeyboardHookStruct.vkCode == 32)
                    {                        if (MyKeyboardHookStruct.vkCode >= 65 && MyKeyboardHookStruct.vkCode <= 90)
                        {
                            Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                            KeyEventArgs e = new KeyEventArgs(keyData);
                            KeyUpEvent(this, e);
                            isStarted = true;
                        }                        if (MyKeyboardHookStruct.vkCode == 32)
                        {
                            OnSpaced(0);
                            isStarted = false;
                        }                        return 1;
                    }                    else
                        return 0;
                }                #endregion
            }            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }

上面一些数字,对于刚入门的同学来说也不是什么问题,一看就明白是对哪些键做的操作。

3.停止钩子


 1 public void Stop() 2         { 3             bool retKeyboard = true; 4  5  6             if (hKeyboardHook != 0) 7             { 8                 retKeyboard = UnhookWindowsHookEx(hKeyboardHook); 9                 hKeyboardHook = 0;10             }11 12             if (!(retKeyboard))13                 throw new Exception("卸载钩子失败!");14         }

4.注册事件


1 private void WordBoard_Load(object sender, EventArgs e)2         {3             Program.keyBordHook.KeyUpEvent += KeyBordHook_KeyUpEvent;4             Program.keyBordHook.OnSpaced += KeyBordHook_OnSpaced;5             Program.keyBordHook.OnBacked += KeyBordHook_OnBacked;6         }

5.根据输入内容显示并进行转换


 1 private void ShowCharatar() 2         { 3             this.listView1.BeginInvoke(new Action(() => 4             { 5                 label1.Text = keys; 6  7                 try 8                 { 9                     this.listView1.Items.Clear();10                     var arr = CacheHelper.Get(keys);11                     if (arr != null)12                         for (int i = 0; i < (arr.Length > 10 ? 9 : arr.Length); i++)13                         {14                             this.listView1.Items.Add((i + 1) + "、" + arr[i]);15                         }16                 }17                 catch18                 {19                     label1.Text = keys = "";20                 }21             }));22         }

 

6.显示输入


1 private void KeyBordHook_KeyUpEvent(object sender, KeyEventArgs e)2         {3             keys += e.KeyCode.ToString().ToLower();4             this.ShowCharatar();5         }

 

7.空格上屏


 1 private void KeyBordHook_OnSpaced(int choose) 2         { 3             try 4             { 5                 if (CacheHelper.ContainsKey(keys)) 6                 { 7                     if (choose > 0) 8                     { 9                         choose = choose - 1;10                     }11 12                     Program.keyBordHook.Send(CacheHelper.Get(keys)[choose]);13                     label1.Text = "";14                     this.listView1.Clear();15                 }16             }17             catch18             {19 20             }21             keys = "";22         }

8.将数据发送到激活的输入框中


1 public void Send(string msg)2         {3             if (!string.IsNullOrEmpty(msg))4             {5                 Stop();6                 SendKeys.Send("{RIGHT}" + msg);7                 Start();8             }9         }

 

9.back键回退


1 private void KeyBordHook_OnBacked()2         {3             if (!string.IsNullOrEmpty(keys))4             {5                 keys = keys.Substring(0, keys.Length - 1);6             }7             this.ShowCharatar();8         }

 

当然这里还可以使其他键来完善更多的功能,例如拼音的分页处理等

 

至于什么五笔、拼音就要使用词库来解决了;其中五笔比较简单,拼音就非常复杂了,各种分词、联想等...这里以五笔为主,拼音为单拼来实现基本的输入功能;所以不需要什么高深算法,简单使用MemoryCache就轻松高效搞定(有兴趣的可以来http://www.php.cn/ 上完善)

10.键词转换


  1 /*****************************************************************************************************  2  * 本代码版权归@wenli所有,All Rights Reserved (C) 2015-2017  3  *****************************************************************************************************  4  * CLR版本:4.0.30319.42000  5  * 唯一标识:8ebc884b-ee5f-45de-8638-c054b832e0ce  6  * 机器名称:WENLI-PC  7  * 联系人邮箱:wenguoli_520@qq.com  8  *****************************************************************************************************  9  * 项目名称:$projectname$ 10  * 命名空间:Wenli.IEM 11  * 类名称:CacheHelper 12  * 创建时间:2017/3/3 16:18:14 13  * 创建人:wenli 14  * 创建说明: 15  *****************************************************************************************************/ 16 using System; 17 using System.Collections.Generic; 18 using System.IO; 19 using System.Linq; 20 using System.Runtime.Caching; 21 using System.Text; 22 using System.Windows.Forms; 23  24 namespace Wenli.IEM.Helper 25 { 26     public static class CacheHelper 27     { 28         static MemoryCache _wubiCache = new MemoryCache("wubi"); 29  30         static MemoryCache _pinyinCache = new MemoryCache("pinyin"); 31  32         static CacheHelper() 33         { 34             var path = Application.StartupPath + "\\Win32\\world.dll"; 35             var arr = File.ReadAllLines(path); 36             foreach (string item in arr) 37             { 38                 var key = item.Substring(0, item.IndexOf(" ")); 39                 var value = item.Substring(item.IndexOf(" ") + 1); 40                 _wubiCache.Add(key, (object)value, DateTimeOffset.MaxValue); 41             } 42  43             // 44  45             path = Application.StartupPath + "\\Win32\\pinyin.dll"; 46             arr = File.ReadAllLines(path); 47             foreach (string item in arr) 48             { 49                 var key = item.Substring(0, item.IndexOf(" ")); 50                 var value = item.Substring(item.IndexOf(" ") + 1); 51                 _pinyinCache.Add(key, (object)value, DateTimeOffset.MaxValue); 52             } 53         } 54  55         public static string[] Get(string key) 56         { 57             if (!string.IsNullOrEmpty(key)) 58             { 59                 var str = string.Empty; 60  61                 try 62                 { 63                     if (_wubiCache.Contains(key)) 64                         str = _wubiCache[key].ToString(); 65                 } 66                 catch { } 67                 try 68                 { 69                     if (_pinyinCache.Contains(key)) 70                         str += " " + _pinyinCache[key].ToString(); 71                 } 72                 catch { } 73  74                 if (!string.IsNullOrEmpty(str)) 75                 { 76                     var arr = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); 77                     for (int i = 0; i < arr.Length; i++) 78                     { 79                         if (arr[i].IndexOf("*") > -1) 80                         { 81                             arr[i] = arr[i].Substring(0, arr[i].IndexOf("*")); 82                         } 83                     } 84                     return arr; 85                 } 86             } 87  88             return null; 89         } 90  91  92         public static bool ContainsKey(string key) 93         { 94             if (_wubiCache.Contains(key)) 95                 return true; 96             if (_pinyinCache.Contains(key)) 97                 return true; 98             return false; 99         }100 101         public static void Clear()102         {103             _wubiCache.Dispose();104             GC.Collect(-1);105         }106     }107 }

 

到此一个基本型的C#版外挂输入法就成功完成了,源码地址:http://www.php.cn/ 

 

 

 

 


以上是C# 的输入法 的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
C#和.NET运行时:它们如何一起工作C#和.NET运行时:它们如何一起工作Apr 19, 2025 am 12:04 AM

C#和.NET运行时紧密合作,赋予开发者高效、强大且跨平台的开发能力。1)C#是一种类型安全且面向对象的编程语言,旨在与.NET框架无缝集成。2).NET运行时管理C#代码的执行,提供垃圾回收、类型安全等服务,确保高效和跨平台运行。

C#.NET开发:入门的初学者指南C#.NET开发:入门的初学者指南Apr 18, 2025 am 12:17 AM

要开始C#.NET开发,你需要:1.了解C#的基础知识和.NET框架的核心概念;2.掌握变量、数据类型、控制结构、函数和类的基本概念;3.学习C#的高级特性,如LINQ和异步编程;4.熟悉常见错误的调试技巧和性能优化方法。通过这些步骤,你可以逐步深入C#.NET的世界,并编写高效的应用程序。

c#和.net:了解两者之间的关系c#和.net:了解两者之间的关系Apr 17, 2025 am 12:07 AM

C#和.NET的关系是密不可分的,但它们不是一回事。C#是一门编程语言,而.NET是一个开发平台。C#用于编写代码,编译成.NET的中间语言(IL),由.NET运行时(CLR)执行。

c#.net的持续相关性:查看当前用法c#.net的持续相关性:查看当前用法Apr 16, 2025 am 12:07 AM

C#.NET依然重要,因为它提供了强大的工具和库,支持多种应用开发。1)C#结合.NET框架,使开发高效便捷。2)C#的类型安全和垃圾回收机制增强了其优势。3).NET提供跨平台运行环境和丰富的API,提升了开发灵活性。

从网络到桌面:C#.NET的多功能性从网络到桌面:C#.NET的多功能性Apr 15, 2025 am 12:07 AM

C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.

C#.NET与未来:适应新技术C#.NET与未来:适应新技术Apr 14, 2025 am 12:06 AM

C#和.NET通过不断的更新和优化,适应了新兴技术的需求。1)C#9.0和.NET5引入了记录类型和性能优化。2).NETCore增强了云原生和容器化支持。3)ASP.NETCore与现代Web技术集成。4)ML.NET支持机器学习和人工智能。5)异步编程和最佳实践提升了性能。

c#.net适合您吗?评估其适用性c#.net适合您吗?评估其适用性Apr 13, 2025 am 12:03 AM

c#.netissutableforenterprise-levelapplications withemofrosoftecosystemdueToItsStrongTyping,richlibraries,androbustperraries,androbustperformance.however,itmaynotbeidealfoross-platement forment forment forment forvepentment offependment dovelopment toveloperment toveloperment whenrawspeedsportor whenrawspeedseedpolitical politionalitable,

.NET中的C#代码:探索编程过程.NET中的C#代码:探索编程过程Apr 12, 2025 am 12:02 AM

C#在.NET中的编程过程包括以下步骤:1)编写C#代码,2)编译为中间语言(IL),3)由.NET运行时(CLR)执行。C#在.NET中的优势在于其现代化语法、强大的类型系统和与.NET框架的紧密集成,适用于从桌面应用到Web服务的各种开发场景。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用