Windows 窗体—— 键盘输入工作原理
方法 |
注释 |
---|---|
此方法在应用程序级截获排队的(也称为已发送的)Windows 消息。 |
|
此方法在 Windows 消息处理前在窗体和控件级截获它们。 |
|
此方法在窗体和控件级处理 Windows 消息。 |
|
此方法在窗体和控件级执行 Windows 消息的默认处理。 这提供了窗口的最小功能。 |
|
此方法在消息处理后在窗体和控件级截获它们。 若要调用此方法,必须设置 EnableNotifyMessage 样式位。 |
KeyDown 事件的预处理相关方法:ProcessCmdKey、IsInputKey、ProcessDialogKey
KeyPress 事件的预处理相关方法:IsInputChar、ProcessDialogChar
Control的ProcessCmdKey方法:该方法处理命令键,命令键的优先级高于常规键。命令键的例子包括快捷键和菜单快捷方式
// true:将不调度键消息,而且将不发生键事件
// false:将调用IsInputKey
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected virtual bool ProcessCmdKey(ref Message msg, Keys keyData)
{
ContextMenu menu = (ContextMenu) this.Properties.GetObject(PropContextMenu);
return (((menu != null) && menu.ProcessCmdKey(ref msg, keyData, this)) || ((this.parent != null) && this.parent.ProcessCmdKey(ref msg, keyData)));
}
Control的IsInputKey方法:
// true:表示该控件为常规字符,将引发 KeyDown 事件
// false:表示还没有做处理,将会调用ProcessDialogKey进行处理
[UIPermission(SecurityAction.InheritanceDemand, Window=UIPermissionWindow.AllWindows)]
protected virtual bool IsInputKey(Keys keyData)
{
// 1.检查该键是否为需要预处理的特殊键
// Alt需要特殊处理
if ((keyData & Keys.Alt) == Keys.Alt)
{
return false;
}
int num = ;
switch ((keyData & Keys.KeyCode))
{
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
num = ;
break; case Keys.Tab:
num = ;
break;
}
// 2.检查它是否为应引发KeyDown 事件并且被调度到某个控件的普通字符键
// IsHandleCreated 指示控件是否有与它关联的句柄
return (this.IsHandleCreated && ((((int) ((long) this.SendMessage(0x87, , ))) & num) != ));
}
※预处理的键包括 Tab、Return、ESC 以及向上键、向下键、向左键和向右键。
ProcessDialogKey:此方法在控件内实现特殊功能(如在控件及其父级之间切换焦点)的物理按键。 如果中间控件不处理该键,则将调用父控件的 ProcessDialogKey,直至层次结构中的最顶端控件。
// true:将完成预处理,而且将不生成按键事件。
// false:将发生 KeyDown 事件
[UIPermission(SecurityAction.InheritanceDemand, Window=UIPermissionWindow.AllWindows), UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected virtual bool ProcessDialogKey(Keys keyData)
{
return ((this.parent != null) && this.parent.ProcessDialogKey(keyData));
}
处理键盘消息
ProcessKeyMessage:此方法处理由控件的 WndProc 方法接收的所有键盘消息。
[SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected internal virtual bool ProcessKeyMessage(ref Message m)
{
return (((this.parent != null) && this.parent.ProcessKeyPreview(ref m)) || this.ProcessKeyEventArgs(ref m));
}
ProcessKeyPreview:此方法将键盘消息发送到控件的父控件。 如果 ProcessKeyPreview 返回 true,则将不生成键事件;否则将调用 ProcessKeyEventArgs。
[SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected virtual bool ProcessKeyPreview(ref Message m)
{
return ((this.parent != null) && this.parent.ProcessKeyPreview(ref m));
}
ProcessKeyEventArgs:此方法根据需要引发 KeyDown、KeyPress 和 KeyUp 事件。
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected virtual bool ProcessKeyEventArgs(ref Message m)
{
KeyEventArgs e = null;
KeyPressEventArgs args2 = null;
IntPtr zero = IntPtr.Zero;
if ((m.Msg == 0x102) || (m.Msg == 0x106))
{
int imeWmCharsToIgnore = this.ImeWmCharsToIgnore;
if (imeWmCharsToIgnore > )
{
imeWmCharsToIgnore--;
this.ImeWmCharsToIgnore = imeWmCharsToIgnore;
return false;
}
args2 = new KeyPressEventArgs((char) ((ushort) ((long) m.WParam)));
// OnKeyPress
this.OnKeyPress(args2);
zero = (IntPtr) args2.KeyChar;
}
else if (m.Msg == 0x286)
{
int num2 = this.ImeWmCharsToIgnore;
if (Marshal.SystemDefaultCharSize == )
{
char ch = '\0';
byte[] lpMultiByteStr = new byte[] { (byte) (((int) ((long) m.WParam)) >> ), (byte) ((long) m.WParam) };
char[] lpWideCharStr = new char[];
int num3 = UnsafeNativeMethods.MultiByteToWideChar(, , lpMultiByteStr, lpMultiByteStr.Length, lpWideCharStr, );
if (num3 <= )
{
throw new Win32Exception();
}
lpWideCharStr = new char[num3];
UnsafeNativeMethods.MultiByteToWideChar(, , lpMultiByteStr, lpMultiByteStr.Length, lpWideCharStr, lpWideCharStr.Length);
if (lpWideCharStr[] != '\0')
{
ch = lpWideCharStr[];
num2 += ;
}
else if ((lpWideCharStr[] == '\0') && (lpWideCharStr.Length >= ))
{
ch = lpWideCharStr[];
num2++;
}
this.ImeWmCharsToIgnore = num2;
args2 = new KeyPressEventArgs(ch);
}
else
{
num2 += - Marshal.SystemDefaultCharSize;
this.ImeWmCharsToIgnore = num2;
args2 = new KeyPressEventArgs((char) ((ushort) ((long) m.WParam)));
}
char keyChar = args2.KeyChar;
// OnKeyPress
this.OnKeyPress(args2);
if (args2.KeyChar == keyChar)
{
zero = m.WParam;
}
else if (Marshal.SystemDefaultCharSize == )
{
string wideStr = new string(new char[] { args2.KeyChar });
byte[] pOutBytes = null;
int num4 = UnsafeNativeMethods.WideCharToMultiByte(, , wideStr, wideStr.Length, null, , IntPtr.Zero, IntPtr.Zero);
if (num4 >= )
{
pOutBytes = new byte[num4];
UnsafeNativeMethods.WideCharToMultiByte(, , wideStr, wideStr.Length, pOutBytes, pOutBytes.Length, IntPtr.Zero, IntPtr.Zero);
int num5 = Marshal.SizeOf(typeof(IntPtr));
if (num4 > num5)
{
num4 = num5;
}
long num6 = ;
for (int i = ; i < num4; i++)
{
num6 = num6 << ;
num6 |= pOutBytes[i];
}
zero = (IntPtr) num6;
}
else if (num4 == )
{
pOutBytes = new byte[num4];
UnsafeNativeMethods.WideCharToMultiByte(, , wideStr, wideStr.Length, pOutBytes, pOutBytes.Length, IntPtr.Zero, IntPtr.Zero);
zero = (IntPtr) pOutBytes[];
}
else
{
zero = m.WParam;
}
}
else
{
zero = (IntPtr) args2.KeyChar;
}
}
else
{
e = new KeyEventArgs(((Keys) ((int) ((long) m.WParam))) | ModifierKeys);
if ((m.Msg == 0x100) || (m.Msg == ))
{
// OnKeyDown
this.OnKeyDown(e);
}
else
{
// OnKeyUp
this.OnKeyUp(e);
}
}
if (args2 != null)
{
m.WParam = zero;
return args2.Handled;
}
if (e.SuppressKeyPress)
{
this.RemovePendingMessages(0x102, 0x102);
this.RemovePendingMessages(0x106, 0x106);
this.RemovePendingMessages(0x286, 0x286);
}
return e.Handled;
}
来源:键盘输入工作原理
Windows 窗体—— 键盘输入工作原理的更多相关文章
- windows下的host工作原理
在Window系统中有个Hosts文件(没有后缀名),在Windows98系统下该文件在Windows目录,在Windows2000/XP系统中位于C:\Winnt\System32\Drivers\ ...
- cocos2dx 在windows上实现键盘输入
cocos2d主要面向的是触摸屏幕设备的,在WINDOWS下的定位感觉多多少少就是相当于一个模拟器,因此并没有太多的PC下重要的键盘支持.然而响应键盘消息对于调试来说可以提供不少方便.下边就通过更改c ...
- 深入Windows窗体原理及控件重绘技巧
之前有学MFC的同学告诉我觉得Windows的控件重绘难以理解,就算重绘成功了还是有些地方不明白,我觉得可能很多人都有这样的问题,在这里我从Windows窗体的最基本原理来讲解,如果你有类似的疑惑希望 ...
- Windows工作原理
Windows工作原理中心思想 Windows工作原理的中心思想就是“动态链接”概念.Windows自身带有一大套函数,应用程序就是通过调用这些函数来实现它的用户界面和在屏幕上显示文本与图形的.这些函 ...
- DirectX11 With Windows SDK--05 键盘和鼠标输入
前言 提供键鼠输入可以说是一个游戏的必备要素.在这里,我们不使用DirectInput,而是使用Windows的消息处理机制,不过要从头开始实现会让事情变得很复杂.DXTK提供了鼠标输入的Mouse. ...
- 《浏览器工作原理与实践》<04>从输入URL到页面展示,这中间发生了什么?
“在浏览器里,从输入 URL 到页面展示,这中间发生了什么? ”这是一道经典的面试题,能比较全面地考察应聘者知识的掌握程度,其中涉及到了网络.操作系统.Web 等一系列的知识. 在面试应聘者时也必问这 ...
- Windows下ARP协议的工作原理简介
ARP协议(Address Resolve Protocol,地址解析协议)工作在TCP/IP协议的第二层-数据链路层,用于将IP地址转换为网络接口的硬件地址(媒体访问控制地址,即MAC地址). ...
- [Windows编程] 使用AttachThreadInput 来捕捉其它窗口的键盘输入
在一些情况下(比如屏幕软键盘或者输入法程序),自己的窗口没有输入焦点但是想要当前焦点窗口的键盘输入消息,可以使用Win32 API函数AttachThreadInput()来解决这个问题.Attach ...
- VB模拟键盘输入的N种方法
VB模拟键盘输入的N种方法http://bbs.csdn.net/topics/90509805hd378发表于: 2006-12-24 14:35:39用VB模拟键盘事件的N种方法 键盘是我们使用计 ...
随机推荐
- C#基础精华08(反射,程序集)
什么是程序集? 程序集是.net中的概念. .net中的dll与exe文件都是程序集.(exe与dll的区别?) 程序集(Assembly),可以看做是一堆相关类打一个包,相当于java中的jar包( ...
- 告别无止境的增删改查:Java代码生成器
对于一个比较大的业务系统,我们总是无止境的增加,删除,修改,粘贴,复制,想想总让人产生一种抗拒的心里.那有什么办法可以在正常的开发进度下自动生成一些类,配置文件,或者接口呢? 有感于马上要做个比较 ...
- ubuntu服务器/home/分区替换3T硬盘
一,关机,将硬盘连接到主机. 二,开机 1,查看/dev/ 是否有多余的sdb 注,sda,sdb可以直接看做一整块硬盘. 而sda1,sda2即sda硬盘上的分区. 2,执行fdisk –l,确保添 ...
- 12个目标跟踪方面的资料12 Tracking
Goal Tracking Template - FEMA.gov Goal Tracking Template Set a weekly or biweekly deadline to report ...
- 10个最佳的PHP图像操作库
Thomas Boutell 以及众多的开发者创造了以GD图形库闻名的一个图形软件库,用于动态的图形计算. GD提供了对于诸如C, Perl, Python, PHP, OCaml等等诸多编程语言的支 ...
- php整理(一):变量和字符串
PHP中的变量: 1. 定义:$符号来定义变量 2. 说明: (1)PHP弱语言,定义变量的时候不用声明类型,但是并不代表PHP没有数据类型 (2)变量名是区分大小写的,只能是数字,字母或者下划线 ( ...
- ExtJs自学教程(1):一切从API开始
题 记 该系列文章不侧重全方位的去介绍ExtJs的使用,只是侧重于解决ExtJs问题的思考方法.写的人不用长篇大论,学的人则能够自立更生.l 学习的人只要有一些CSS的javascript的基础知识 ...
- 将Ftp添加到资源管理器中直接使用
在资源管理器中,右键,添加网络位置. 然后输入ftp的url ftp://server2008 使用匿名方式登录
- Lunix中文乱码解决方案
sudo vi /var/lib/locales/supported.d/local#添加下面的中文字符集zh_CN.GBK GBKzh_CN.GB2312 GB2312zh_CN.GB18030 G ...
- 注意:C++中double的表示是有误差的
注意:C++中double的表示是有误差的,直接通过下面的例子看一下 #include<iostream> using namespace std; int main() { double ...