Archived:如何在Qt程序中拦截所有Symbian事件
文章信息
Contents |
引言
有时候在用Qt写Symbian应用的时候,我们会希望直接从Symbian操作系统获得事件,因为经过Qt翻译之后的事件有时候满足不了我们的需要。
截获所有Symbian事件,会使我们的程序拥有更高的自主权,也给了我们更多自由发挥的空间。熟悉Symbian的同学们更会觉得方便。
从Qt 4.6 开始Qt就开始支持截获所有Symbian事件了,下面我们就具体看一下如何实施。
继承QApplication
通常Qt GUI程序都是从构造一个QApplication对象开始的,但是我们如果想截获所有Symbian事件是不能简单的这么做的。首先我们需要设计一个自己的QApplication类。也就是我们写一个继承自QApplication的类。 例如:
#ifndef FNAPPLICATION_H
#define FNAPPLICATION_H
#include <QApplication>
#include <QSymbianEvent>
class FNApplication : public QApplication
{
Q_OBJECT
public:
explicit FNApplication(int argc, char *argv[]);
virtual bool symbianEventFilter ( const QSymbianEvent * event );
signals:
void layoutChange();
void focusGained();
void focusLost();
public slots:
};
#endif // FNAPPLICATION_H
并且实现QApplication的虚方法:
bool QApplication::symbianEventFilter ( const QSymbianEvent * event ) [virtual]
其中的event参数可以是任何类型的Symbian事件,这都是由QSymbianEvent进行封装的。在实现此函数时,如果我们想拦截此事件就return true,否则的话return false。此函数的默认实现是return false,即不做任何处理,交由Qt底层处理。
拦截ResourceChangeEvent
我们可以使用这个函数获取ResourceChangeEvent中具体的事件类型:
int QSymbianEvent::resourceChangeType () const
使用方法举例。
例如拦截横竖屏切换的ResourceChangeEvent如下:
if(event->type() == QSymbianEvent::ResourceChangeEvent)
{
if(event->resourceChangeType() == KEikDynamicLayoutVariantSwitch)
{
emit layoutChange(); //我们这里通过发送一个信号来进行我们自己的处理
return true; //如果我们想让系统继续处理,就可以写return false;
}
else
return false;
}
拦截WindowServerEvent
我们可以使用这个函数直接获取WindowServerEvent中所包含的TWsEvent(Symbian的Window server event):
const TWsEvent * QSymbianEvent::windowServerEvent () const
使用方法举例。
例如拦截window group获取失去焦点的Window server事件的代码如下:
const TWsEvent * wsevent = event->windowServerEvent();
if( !wsevent ) {
return false;
}
switch( wsevent->Type() )
{
case EEventFocusGained: {
emit focusGained();
return true;
break;
}
case EEventFocusLost: {
emit focusLost();
return true;
break;
}
default:
return false;
break;
}
拦截CommandEvent
int QSymbianEvent::command () const
我们可以通过此函数获得even中所包含的command,使用方法与以上类似。
拦截后对所拦截事件进行处理
有很多种方式。我们这里采用signal slot的方式进行处理,在上述例子代码中我们拦截到事件后都发送了一个signal。对signal的处理我们可以放在任何地方,比如我们就交由主窗口的一个slot进行处理。那么我们只需要在main函数中进行连接一下就可以了。例如:
int main(int argc, char *argv[])
{
#if defined(Q_WS_S60)
FNApplication a(argc, argv);
#else
QApplication a(argc, argv);
#endif
MainWindow w;
#if defined(Q_WS_S60)
QObject::connect(&a, SIGNAL(layoutChange()), &w, SLOT(handleLayoutChange())); //交由MianWindow的slot处理
QObject::connect(&a, SIGNAL(focusGained()), &w, SLOT(handlefocusGained()));
QObject::connect(&a, SIGNAL(focusLost()), &w, SLOT(handlefocusLost()));
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}
加入必要的头文件和库
例如我们如果使用TWsEvent就需要加上w32std.h,如果我们使用ResourceChangeEvent就需要加上akndef.h,具体需要什么请大家参考Symbian文档。
示例代码
#include "fnapplication.h"
#include <w32std.h>
#include <akndef.h>
FNApplication::FNApplication(int argc, char *argv[]) :
QApplication(argc, argv)
{
}
bool FNApplication::symbianEventFilter ( const QSymbianEvent * event )
{
switch( event->Type() )
{
case QSymbianEvent::ResourceChangeEvent:{
if(event->resourceChangeType() == KAknFullOrPartialForegroundGained)
{
emit focusGained();
return true;
}
else
return false;
break;
}
case QSymbianEvent::WindowServerEvent:{
const TWsEvent * wsevent = event->windowServerEvent();
switch( wsevent->Type() )
{
case EEventFocusGained: {
emit focusGained();
return true;
break;
}
case EEventFocusLost: {
emit focusLost();
return true;
break;
}
default:
return false;
break;
}
break;
}
default:
return false;
break;
}
}


(no comments yet)