当前位置:文档之家› 键盘映射机制详解

键盘映射机制详解


数组,以找到相应的条目。
*/
theEntry = FindEntry( in->wParam, w->winKeyboard );
/*
消息; 4. 在 WindowDispatchMessage() 里 , 先 找 到 最 上 面 的 活 动 窗 体 , 再 调 用
TranslateMessage()函数来完成按键到具体窗体事件的映射转换; 5. 由此可见,键盘映射的实际转换工作是在 TranslateMessage()函数里实现的,下
Scancode AutoRepeat
KEYTRANSLATION KeyBeep
type
Key KeyInfo
ControlKeyInfo keydownEvent keyupEvent
表1
有了上面的基础知识,我们再来看键盘的映射过程,就比较简单了,其实现机理如下所 述:
首先,对于,每一个窗体 w,其结构体里,都有一个 KEYBOARD 的结构体,其实际上 是一张键盘映射表。具体如下: typedef struct KEYBOARDtag
面,我们就来深入剖析一下此函数;
BOOLEAN TranslateMessage( UIWINDOW * w, UIMSG * out, const UIMSG * in,
BOOLEAN * stopTranslate )
/*
参数说明: 1.w ----要进行按键转换的窗体; 2.out ----出口参数,即返回值,是一个消息结构,其格式是固定的,
1. 用户按下某个键,UH 捕捉到此事件,直接向 AL 层发送一个 ALKeyEventInd 的消 息;
2. AL 层捕捉到此消息后,调用 DoALKeyEventInd()对此消息进行处理; 3. 在 DoALKeyEventInd 里,调用 WindowDispatchMessage( UIMSG * msg )派发此
映射表,则转换过程应该继续到它的父窗体上去进 行,或者键产生的事件同处理键的 AutoRepeat 的 函数派发出去了。
*/ { const KEYTRANSLATION *theEntry; *out = *in;
/* 只转换键盘消息 */
if ( in->cmd == WM_HWKEYEVENT )
extern const UINT16 name##KeydownEvents[]; \ static CONTROLKEYINFO name##CtrlKeyInfo = { name##KeydownEvents,
keyupEvent }; \ static const KEY name##Key = { ControlKey, AKEY( name##CtrlKeyInfo ) }; \ const UINT16 name##KeydownEvents[] 看到这么多,大家是不是快晕了,没关系,宏吗,无外乎就是直接替换而已,我们慢慢 来,一个一个地替换。 /* 声明一个名为 SelectKeydownEvents 的数组,用来存放按键的按下事件, 之所以为数组,原因是一个键按下,可以产生多个事件。 */ extern const UINT16 SelectKeydownEvents[]; /* 声明一个 SelectCtrlKeyInfo 的变量,并赋值为: KeydownEvent = SelectKeydownEvents // 是一个数组哦 KeyupEvent =EV_NULL */ static CONTROLKEYINFO SelectCtrlKeyInfo = { SelectKeydownEvents,
{
if ( w->winKeyboard )
/*
在窗体的键盘映射表里找到相应的条目(通过 ScanCode,所以,
整个按键消息传了好多层,但最重要的,就是这个 ScanCode,因为,
这个唯一标识了一个按键)。键盘映射表的表项可以参看表 1。
其实现原理很简单,就是按 ScanCode 直接搜索存放键盘映射表的
#define AKEY( k ) ((SIMPLEKEYINFO*)(&k))
typedef union { const SIMPLEKEYINFO *const simple; const SHIFTKEYINFO *const shift; const CONTROLKEYINFO *const ctrl; const UCINTLKEYINFO *const UCIntl; const INTLKEYINFO *const intl; } KEYINFO; 最后,再讲一下键的 Repeat 属性,这个东东,其注释的英文没有仔细看懂,由于时间
综合上面的替代过程,可以发现这个宏,其实做的事如下: 声明了一个 Key 结构体的变量 SelectKey,并填充相应的数据(最主要,就两个,一个 是类型域,一个是键信息域(此域按类型的不同,有不同的解释))
SelectKey.type = ControlKey; SelctKey.k = SelectCtrKeyInfo; 而键信息又等于 k.KeydownEvent[] = { EV_SELECT,EV_NULL }; // 键按下时,可以触发多个事件 k.KeyupEvent = EV_NULL; // 键弹起时只触发一个事件 好了,明白了这些道道之后,以后会直接使用它就好了。 接下来,再讲一下 AKEY(k)这个宏定义,这个宏定义的原理很简单,就是将任何 KeyInfo 类型的变量,转化为 SimpleKeyInfo 的类型,之所以要做如此转换,关键是 KeyInfo 是一个 联合体(联合体内存的占用只取最大的那个,其实,每次,不同的类型变量,其指针地址都 是一样的,只是内存所指的区域,其解释不一样罢了!),因此,为了避免不同的 KeyInfo 的 类型不一致,就直接将其转换为占用内存最少的 SimpleKeyInfo 就可以了,这样,指针是一 样的,只是以后,我们用时,解释不一样罢了。
/* The Hardware Keyscan code */
/*
键盘映射表,很有用的东东,这里最重要的就是 Key 这个结构体,包含了
和 Key 有关的所有信息,比如 key 的类型,和 Key 的响应函数等。chh
*/
const KEY *const key;
const AUTOREPEAT *const repeat; /* AutoRepeat 属性 */
但参数内容视具体情况而定, typedef struct
{
UINT16 cmd;
// 消息类型
UINT16 wParam; // 消息参数 1,指针,可以指向任何 // 东东;
// 由于只有 16 位,所以,一般,不用来 // 作指针用,而是用于标识消息
UINT32 lParam; } UIMSG;
EV_NULL};
/* 再声明一个 SelectKey 的变量,并赋初值为: KEYTYPE type = ControlKey KEYINFO k = SelectCtrlKeyInfo
*/ static const KEY SelectKey = { ControlKey, SelectCtrlKeyInfo }; /*
// 消息参数 2,同上; // 一般用来存放发送消息时要传送的 // 信息,指向具体的结构体
3.in ---- 入口参数 cmd = WM_HWKEYEVENT;
wParam = keyScanCode;
lParam = pressed;
4. stopTranslate ---转换是否完成,因为,有可能子窗体没有配置键盘
上述的代码实现的功能为: 定义了一个 KEYTRANSLATION 的键盘映射表 AmoiMenuKeyboardLookup(其实就是 一个结构体数组而已),其中定义了两个按键,一个为 KEY_1(扫描码),其所对应的事件,存 放在 OneKey(这个键的定义,即是我们上面所讲的,只不过,查找时,要将后面的 Key 去掉,因为,宏定义时会帮我们自动填上)里面,再有就是指定此键的 AutoRepeat 属性, 最后,就是此键的按键声音。其详细情况可以参看下面的键盘映射表:
const KEYBEEP beep;
/* 按键声音 */
} KEYTRANSLATION;
如上表 1 所示,每一个窗体都有这样一张键盘映射表------假如它需要的话,至于这个 键盘映射表的实现方式,在程序里,是以结构体数组的方式来实现的;
那一个按键究竟是如何变成一个窗体的事件的呢?其具体步骤如下:(更详细的说明, 可以参看文档《深入剖析 UIF 的消息派发机制.pdf》)。
2.在指定的时间内连续按两次键,只产生两次按下的事件,而只在最后一次产生弹起事 件;
3.相当于双击键; 定义了键,那如何定义键盘映射表呢,很简单,请看下面的代码: static const KEYTRANSLATION AmoiMenuKeyboardLookup[] = { {KEY_1, &OneKey, &NoAutoRepeat, NormalBeep}, {KEY_SOFT1, &SelectKey, &NoAutoRepeat, NormalBeep}, };
首先,我们来看一下如何定义一个按键,下面,就是深度剖析 SelectKey 的定义过程, 其语法如下:
DEFINECTRLKEY( Select, EV_NULL ) = { EV_SELECT, EV_NULL
}; DEFINECTRLKEY 这个宏比较特别,值得深入地讲一下,以后,大家如果理解了,则 不用去深究它了,只要会用就好了。DEFINECTRLKEY 宏的定义如下所示: #define DEFINECTRLKEY( name, keyupEvent ) \
关系,也没有去做测试,只能大致描述如下,有问题的话,还希望其它高手指正。 键的 AutoRepeat 有以下几种类型:
相关主题