您的位置:首页 > 其它

关于symbian按键事件的一些总结(2)----------按键事件的处理

2008-07-22 17:04 597 查看
不论是OfferKeyEventL还是HandleKeyEventL,这两个函数传递的参数都是一样的:

const TKeyEvent& aKeyEvent ------------记录了按键的具体信息
iCode(键盘码)
iScanCode(扫描码) 上面这两个是重点,后面会重点介绍。
iModifier(修饰键....暂且这么叫吧)
iRepeats(是个标记,告诉你产生的这个按键事件是你重复按键还是长按一个键时周期产生的按键事件)。
TKeyEvent 还是要看下e32keys.h头文件(epoc32/include),定义都在里面。

TEventCode aType -------记录键盘事件类型:

EEventKeyDown (接收按键按下时的信息),

EEventKey(在按键按下后,到按键松开前,周期性的收集信息.键盘连击率,RWsSession::SetKeyboardRepeatRate方法设置时间间隔.),

EEventKeyUp(收集按键释放信息).

而每次按键时,都会依次产生上面三个按键事件(其实也不完全是这样,后面会说到),根据不同的应用需求做处理,在很多基本的应用时,我们不太关心键按下或松开的时刻,而只关心我们按的是什么键,比如在对话框里输入一些,我们只关心按的是a还是b,而合适按下a或b对我们来说并不重要,那么我们在OfferKeyEventL或HandleKeyEventL中,只需对 aTyep == EEvenKey 时做处理。

而另外一种情况,比如游戏,一个键的按下或释放的时刻就显得很重要了,这时需要对 aTyep == EEvenKeyDown 或 aTyep == EEvenKeyUp时进行处理,比如我们可以在aTyep == EEvenKeyDown 时移动一个物体,在aTyep == EEvenKeyUp时停止移动。

好了,大概的把这些简单的说完了,下面就开始我们的重头戏----aKeyEvent

aKeyEvent 记录了我们按键的详细信息,我们先从最简单的两个iRepeats和 iModifier开始。

iRepeats

w32std.h里是这样定义iRepeats的:

/** Count of auto repeats generated.
0 means an event without repeats. 1 or more means "this many auto repeat events".
It is normal to ignore this value and treat it as a single event. */
TInt iRepeats;

说的很清楚了,你按键时不是先产生个aTyep=EEvenKeyDown的事件嘛,紧接着产生aTyep= EEvenKey的事件,如果你按下那个键(比如a)的时间足够长(也不需要太长,呵呵),超过了系统默认时间间隔(如果你没有用RWsSession::SetKeyboardRepeatRate设置的时间间隔)的话,那么经历那个系统默认时间间隔后,会再次产生aTyep= EEvenKey 的事件,而这两次aTyep= EEvenKey事件的唯一区别就是前一个的aKeyEvent.iRepeats =0,而之后的aKeyEvent.iRepeats =1。所以aTyep= EEvenKey(且aKeyEvent.iRepeats =1)的事件每隔一定时间间隔就会自动产生,直到你松开按键。而后产生aTyep= EEvenKeyUp事件。

iModifier

w32std.h里是这样定义iModifier的:

/** State of modifier keys and pointing device. Modifier keys are defined in TEventModifier. */
TUint iModifiers;

那么我们再看看TEventModifier 的定义(e32keys.h中)

enum TEventModifier
{
EModifierAutorepeatable=0x00000001, /**< Key event can auto-repeat.*/
EModifierKeypad=0x00000002, /**< The key that generated the event was on the numeric keypad, on the emulator.*/
EModifierLeftAlt=0x00000004, /**< Left Alt key.*/
EModifierRightAlt=0x00000008, /**< Right Alt key.*/
EModifierAlt=0x00000010, /**< Single Alt key.*/
EModifierLeftCtrl=0x00000020, /**< Left Control (Ctrl) key.*/
EModifierRightCtrl=0x00000040, /**< Right Control (Ctrl) key.*/
EModifierCtrl=0x00000080, /**< Single Control (Ctrl) key.*/
EModifierLeftShift=0x00000100, /**< Left Shift key.*/
EModifierRightShift=0x00000200, /**< Right Shift key.*/
EModifierShift=0x00000400, /**< Single Shift key.*/
EModifierLeftFunc=0x00000800, /**< Left Fn key.*/
EModifierRightFunc=0x00001000, /**< Right Fn key.*/
EModifierFunc=0x00002000, /**< Single Fn key.*/
EModifierCapsLock=0x00004000, /**< Caps lock key.*/
EModifierNumLock=0x00008000, /**< Num lock key.*/
EModifierScrollLock=0x00010000, /**< Scroll lock key.*/
EModifierKeyUp=0x00020000, /**< Key up event.*/
EModifierSpecial=0x00040000, /**< The keycode is a non-standard keyboard character that has been generated in a special keyboard mode, for example accented vowels.*/
EModifierDoubleClick=0x00080000, /**< Double click.*/
EModifierPureKeycode=0x00100000, /**< The key code in the key event is not changed. E.g.an alphabetic key is not changed by the Caps Lock or Shift key being pressed.*/
EModifierKeyboardExtend=0x00200000, /**< The "Keyboard extend" generated modifier. */
EModifierCancelRotation=0x00000000, /**< No Keyboard rotation is in effect. */
EModifierRotateBy90=0x00400000, /**< Keyboard rotation through 90 degrees clockwise is in effect. */
EModifierRotateBy180=0x00800000, /**< Keyboard rotation through 180 degrees clockwise is in effect. */
EModifierRotateBy270=0x01000000, /**< Keyboard rotation through 270 degrees clockwise is in effect. */
EModifierPointer3DButton1=0x02000000,/**< 3D pointer device specific modifier (button 1). */
EModifierPointer3DButton2=0x04000000,/**< 3D pointer device specific modifier (button 2). */
EModifierPointer3DButton3=0x08000000,/**< 3D pointer device specific modifier (button 3). */
EAllModifiers=0x0fffffff /**< A combination of all event modifiers.*/
};

定义虽然有点多,但是很容易看出,iModifier就是指shift alt ctrl等这种修饰键有没有被按下。想想也很容易理解,我们单独按一个a,和shift+ a(产生的是A,大写)结果是不一样的,总得有个参数标记一下,这个参数就是iModifier了。另外,从定义中不知道你发现没,他们都是单字节位定义的,比如

EModifierAutorepeatable=0x00000001 对应的二进制是 0001

EModifierKeypad=0x00000002 对应的二进制是 0010

EModifierLeftAlt=0x00000004 对应的二进制是 0100

这样做是因为有时候我们可能按下不只一个的修饰键,比如两个(shift + alt),而把这样同时两个或者更多修饰键被按下的情况一一枚举出来是不科学和不实用的,使用这种单字节位定义的好处就是我们在判断某个修饰键有没有被按下时,只需要按位与(&)一下就行了,比如,如果没有其他修饰键,一般按a时产生的iModifer是3(对应的二进制是 0011),那么
if(aKeyEvent.iModifier & EModifierAutorepeatable)和
if(aKeyEvent.iModifier & EModifierKeypad)时都为真,
而if(aKeyEvent.iModifier & EModifierLeftAlt)就为假,
这样我们在处理按键事件时就能方便的判断出来那些修饰键被按下了。
另外需要注意的就是,我测试时发现按下修饰键时只产生EEvenKeyDown和EEvenKeyUp事件,而无EEvenKey。

简单的说完了,下面该唠叨唠叨iScanCode 和 iCode了。

iCode 是每次完整的按键事件对应的一个唯一键盘码,所谓完整的按键事件就是EEvenKeyDown、EEvenKeyUp及EEvenKey 这三个事件,iCode在EEvenKeyDown和EEvenKeyUp中均为0,只有在EEvenKey 中才对应相应的键盘码,这在SDK中有说:

The character code generated for an
EEventKey
, or 0 for a down or up event.

Key codes for special keys are defined in
TKeyCode
.

可见,在EEvenKeyDown和EEvenKeyUp中我们无法根据iCode进行相应处理,因为所有按键的iCode都是0,我们只能根据iScanCode来判断按下的键位并处理。那么什么是iScanCode呢?

iScanCode在SDK中是这样描述的:

The scan code of the key that caused the event

怎么样,迷糊了吧,我们按下a这个键,不就是“a”这个键cause the event,而且The character code generated for the
EEventKey
也是a 啊,iScancode 和 iCode的区别在哪呢?别忘了,可能还有修饰键呢,如果我们只按下a,那么iScancode = 0x41 和 iCode = 0x61(对应ASCII中小写的a),而如果我们按下shift + a,那么iScancode = 0x41 和 iCode = 0x41(对应ASCII中大写的A)。至于为啥小写a的iScancode 为啥是0x41而不是0x61那就得问symbian了,人家就是这么定义的 -.-!!!

下面让我们看看两个完整的按键事件的实例:

a:

184.190 --->code :0
184.190 --->scan code :41
184.190 --->iModifiers :0
184.190 --->iRepeats :0

EEvenKeyDown:a
184.190 *********************************
184.190 --->code :61
184.190 --->scan code :41
184.190 --->iModifiers :1
184.190 --->iRepeats :0

EEvenKey :a
184.190 *********************************
184.320 --->code :0
184.320 --->scan code :41
184.320 --->iModifiers :0
184.320 --->iRepeats :0

EEvenKeyUp:a
184.320 *********************************

shift + a (实际上是左shift):

233.020 --->code :0
233.020 --->scan code :12
233.020 --->iModifiers :500
233.020 --->iRepeats :0
233.020 leftshift was pressed

EEvenKeyDown:shift
233.020 *********************************
233.210 --->code :0
233.215 --->scan code :41
233.215 --->iModifiers :500
233.215 --->iRepeats :0
233.215 leftshift was pressed

EEvenKeyDown:a
233.215 *********************************
233.215 --->code :41
233.215 --->scan code :41
233.215 --->iModifiers :501
233.215 --->iRepeats :0
233.215 leftshift was pressed

EEvenKey:shift + a
233.215 *********************************
233.340 --->code :0
233.340 --->scan code :41
233.340 --->iModifiers :500
233.340 --->iRepeats :0
233.340 leftshift was pressed

EEvenKeyUp:a
233.345 *********************************
233.680 --->code :0
233.680 --->scan code :12
233.680 --->iModifiers :0
233.680 --->iRepeats :0

EEvenKeyUp:shift
233.680 *********************************

实际上有兴趣的话可以自己随便测测其他的按键,只需要在OfferKeyEventL或HandleKeyEventL中加入下面代码:

RDebug::Printf("--->code :%x",aKeyEvent.iCode); //需要RDebug的头文件
RDebug::Printf("--->scan code :%x",aKeyEvent.iScanCode);
RDebug::Printf("--->iModifiers :%x",aKeyEvent.iModifiers);
RDebug::Printf("--->iRepeats :%d",aKeyEvent.iRepeats);
if(aKeyEvent.iModifiers& EModifierLeftShift)
RDebug::Printf("leftshift was pressed");
if(aKeyEvent.iModifiers& EModifierShift)
RDebug::Printf("shift was pressed");
if(aKeyEvent.iModifiers& EModifierRightShift)
RDebug::Printf("rightshift was pressed");
if(aKeyEvent.iModifiers& EModifierLeftCtrl)
RDebug::Printf("leftctrl was pressed");
if(aKeyEvent.iModifiers& EModifierCtrl)
RDebug::Printf("ctrl was pressed");
if(aKeyEvent.iModifiers& EModifierRightCtrl)
RDebug::Printf("rightctrl was pressed");
RDebug::Printf("*********************************");

在调试模式下,通过carbide里面的控制台就能看到相应的按键信息了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: