如何模拟点击事件
文章信息
Contents |
概述
Simulating Pointer Events这篇文章介绍了如何在应用程序内模拟点击事件。但是有时候程序需要向其它应用程序发送点击事件。本文描述了如何使用RWsSession::SimulateRawEvent()模拟点击事件,并解释了为什么不能使用RWsSession::SendEventToWindowGroup()向后台应用程序发送点击事件。
方案
RWsSession::SimulateRawEvent()可以用来模拟点击事件,即向前台应用程序发送点击事件。假定手机处于竖屏模式,那么使用以下代码可以模拟对前台应用程序“选项”按钮的点击操作。如果前台应用程序有“选项”按钮,那么它的选项菜单会弹出。
TPoint p(60,600); // within the "Options" CBA button area
TRawEvent event;
event.Set(TRawEvent::EButton1Down, p.iX, p.iY);
iCoeEnv->WsSession().SimulateRawEvent(event); // SwEvent
User::After(1000);
event.Set(TRawEvent::EButton1Up, p.iX, p.iY);
iCoeEnv->WsSession().SimulateRawEvent(event); // SwEvent
源代码
完整的示例程序:HelloWorld(SimulatePointerEvent).zip
如何在仿真上使用该程序:
1. 为winscw目标构建应用程序,然后启动仿真器。
2. 启动应用程序后按“多任务”键(也被称作菜单键)
如何在真机上使用该程序:
1. 使用可以授权SwEvent能力的证书签署HelloWorld_gcce.sis
2. 安装签署后的安装包并启动应用程序。
3. 按“多任务”键
执行以上操作后可以看到应用程序被带到后台,然后前台应用程序(功能表)弹出了它的选项菜单。
不可能完成的任务
许多开发者尝试过使用RWsSession::SendEventToWindowGroup()给指定的应用程序发送点击事件,但目标应用程序总会发生KERN-EXEC 3严重错误。
为了理解为什么此路不通,我们必须了解控件环境(CONE)和窗口服务器之间的约定:
1. 当拥有窗口的控件(CCoeControl)被创建时,它的地址会被用作窗口的句柄。
2. 当有点击事件产生时,窗口服务器会确定应该由哪个窗口处理该事件,然后将窗口的句柄赋值给该事件的iHandle成员变量,最后将事件发送给拥有该窗口的应用程序。
3. 当应用程序的控件环境接收到该事件时,它将该事件的iHandle成员变量的值强制类型转换成一个CCoeControl指针,然后对该指针调用HandlePointerEventL();
如果用以下代码发送点击事件:
TWsEvent event;
event.SetType(EEventPointer);
event.SetHandle(0); // "handle是什么东西?管他呢清零吧..."
TPointerEvent& pointerEvent = *(event.Pointer());
pointerEvent.iType = TPointerEvent::EButton1Down;
pointerEvent.iParentPosition = TPoint(0,0);
pointerEvent.iPosition = TPoint(10,10);
pointerEvent.iModifiers = 0;
ws.SendEventToWindowGroup(...); // 发送事件给目标应用程序
当目标应用程序接收到该事件后,灾难发生了:
// CONE code
…
CCoeControl* ctrl = reinterpret_cast(event.Handle());
ctrl->HandlePointerEventL(*(event.Pointer())); // KERN-EXEC 3严重错误,因为ctrl是空指针
窗口服务器负责管理所有窗口,所以它知道iHandle应该赋什么值,但你不知道, 所以“窗口服务器满分,你零蛋!”
参考
ER5 SDK(登录下载)中控件环境的源代码


(no comments yet)