ucGUI390 触摸消息响应过程

by Nathan.Yu  2006-12-11

触笔触摸屏幕->

产生中断->

中断处理获得触摸物理坐标->

其后(仍在中断处理函数中)的处理过程:

GUI_TOUCH_Exec->GUI_TOUCH_StoreUnstable(x, y) ->

GUI_TOUCH_StoreState(x, y)在此函数中,改写局部静态变量static GUI_PID_STATE _State如下:

if ((x >= 0) && (y >= 0)) {

_State.Pressed = 1;

_State.x = x;

_State.y = y;

} else {

_State.Pressed = 0;

}

->

GUI_TOUCH_StoreStateEx(&_State),做如下事:

if (memcmp(pState, &_State, sizeof(_State))) {

_State = *pState;

GUI_PID_StoreState(pState);

}

->

void GUI_PID_StoreState(const GUI_PID_STATE *pState) {

_PID_Load();

if (memcmp(&_State, pState, sizeof(_State))) {

_State = *pState;

GUI_X_SIGNAL_EVENT();

}

}

->

static void _PID_Load(void) {

#if (GUI_WINSUPPORT)

<!--[if !vml]--><!--[endif]-->    WM_pfHandlePID = WM_HandlePID;

#endif

}

->

中断返回->

进入以下函数,循环执行:

GUI_Exec()->GUI_Exec1()->WM_Exec()->WM_Exec1()->

在WM_Exec1()函数中做如下判断:

<!--[if !vml]--><!--[endif]-->  if (WM_pfHandlePID) {

if (WM_pfHandlePID())//因此实际调用函数WM_HandlePID;

return 1;               /* We have done something ... */

}

让我们分析函数WM_HandlePID:(位于WMTouch.c中)

1)GUI_PID_GetState(&StateNew);//获得刚刚触摸的状态

2)CHWin.hWin = _Screen2Win(&StateNew);//判断被触摸的是哪个东东!具体如下:

static WM_HWIN _Screen2Win(GUI_PID_STATE* pState) {

if (WM__hCapture == 0) {

return WM_Screen2hWin(pState->x, pState->y);

}

return WM__hCapture;

}

->

WM_HWIN WM_Screen2hWin(int x, int y) {

WM_HWIN r;

WM_LOCK();

r = _Screen2hWin(WM__FirstWin, 0, x, y);//yhm20061211AC, WM__FirstWin = hNew; in //func _AddToLinList

WM_UNLOCK();

return r;        //yhm20061211AC,return the handle of the obj which is hitted!!!

}

->

static WM_HWIN _Screen2hWin(WM_HWIN hWin, WM_HWIN hStop, int x, int y) {

WM_Obj* pWin = WM_HANDLE2PTR(hWin);

WM_HWIN hChild;

WM_HWIN hHit;

/* First check if the  coordinates are in the given window. If not, return 0 */

if (WM__IsInWindow(pWin, x, y) == 0) {

return 0;

}

/* If the coordinates are in a child, search deeper ... */

for (hChild = pWin->hFirstChild; hChild && (hChild != hStop); ) {

WM_Obj* pChild = WM_HANDLE2PTR(hChild);

if ((hHit = _Screen2hWin(hChild, hStop, x, y)) != 0) {

hWin = hHit;        /* Found a window */

}

hChild = pChild->hNext;

}

return hWin;            /* No Child affected ... The parent is the right one */

}

3) WM__IsInModalArea(CHWin.hWin)//判断是否模态?

是:

看状态是否改变,if ((WM_PID__StateLast.Pressed != StateNew.Pressed) && CHWin.hWin)

是:

Msg.MsgId  = WM_PID_STATE_CHANGED;

WM__SendMessageIfEnabled(CHWin.hWin, &Msg);

以按钮为例,这时按钮的默认回调函数:BUTTON_Callback就会收到这个消息

并调用WIDGET_HandleActive(hObj, pMsg),在此函数中有如下代码:

case WM_PID_STATE_CHANGED:

if (pWidget->State & WIDGET_STATE_FOCUSSABLE) {

const WM_PID_STATE_CHANGED_INFO * pInfo = (const WM_PID_STATE_CHANGED_INFO*)pMsg->Data.p;

if (pInfo->State) {                   //如果是按下,这设置焦点

WM_SetFocus(hObj);

}

}

返回到WM_HandlePID接下来处理触摸事件:Msg.MsgId = WM_TOUCH;其中包括按下和提起两个触摸事件,首先判断上次触摸的窗体和这次是否是同一个,如果不是,则先发送WM_TOUCH消息给上次触摸的窗体:

if (StateNew.Pressed) {

/* Moved out -> no longer in this window

* Send a NULL pointer as data

*/

Msg.Data.p = NULL;//留意这里

//Uart_Printf("Move out/n");

}

WM__SendTouchMessage(WM__CHWinLast.hWin, &Msg);

WM__CHWinLast.hWin = 0;

在WM__SendTouchMessage函数中,还会把这个消息发送给上次触摸的窗体的所有父窗体呢!你看:

void WM__SendPIDMessage(WM_HWIN hWin, WM_MESSAGE* pMsg) {

WM_MESSAGE Msg;

/* Send message to the affected window */

Msg = *pMsg;                 /* Save message as it may be modified in callback (as return value) */

WM__SendMessageIfEnabled(hWin, &Msg);

/* Send notification to all ancestors.

We need to check if the window which has received the last message still exists,

since it may have deleted itself and its parent as result of the message.

*/

Msg.hWinSrc = hWin;

Msg.MsgId   = WM_TOUCH_CHILD;

while (WM_IsWindow(hWin)) {

hWin = WM_GetParent(hWin);

if (hWin) {

Msg.Data.p  = pMsg;            /* Needs to be set for each window, as callback is allowed to modify it */

WM__SendMessageIfEnabled(hWin, &Msg);    /* Send message to the ancestors */

}

}

}

假设上次触摸的窗体也是一个按钮,则,这时BUTTON_Callback就会收到这个消息:

case WM_TOUCH:

_OnTouch(hObj, pObj, pMsg);

_OnTouch函数如下:

static void _OnTouch(BUTTON_Handle hObj, BUTTON_Obj* pObj, WM_MESSAGE*pMsg) {

const GUI_PID_STATE* pState = (const GUI_PID_STATE*)pMsg->Data.p;

#if BUTTON_REACT_ON_LEVEL

if (!pMsg->Data.p) {  /* Mouse moved out */

_ButtonReleased(hObj, pObj, WM_NOTIFICATION_MOVED_OUT);

}

#else

if (pMsg->Data.p) {  /* Something happened in our area (pressed or released) */

if (pState->Pressed) {

if ((pObj->Widget.State & BUTTON_STATE_PRESSED) == 0){

_ButtonPressed(hObj, pObj);

}

} else {

/* React only if button was pressed before ... avoid problems with moving / hiding windows above (such as dropdown) */

if (pObj->Widget.State & BUTTON_STATE_PRESSED) {

_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);

}

}

} else {//在这个函数中将执行这个调用,因为pMsg->Data.p==NULL

    _ButtonReleased(hObj, pObj, WM_NOTIFICATION_MOVED_OUT);

  }

#endif

其中_ButtonReleased函数如下:

static void _ButtonReleased(BUTTON_Handle hObj, BUTTON_Obj* pObj, int Notification) {

WIDGET_AndState(hObj, BUTTON_STATE_PRESSED);

if (pObj->Widget.Win.Status & WM_SF_ISVIS) {

WM_NotifyParent(hObj, Notification);

}

if (Notification == WM_NOTIFICATION_RELEASED) {

GUI_DEBUG_LOG("BUTTON: Hit/n");

GUI_StoreKey(pObj->Widget.Id);

}

}

由于调用了WM_NotifyParent函数,因此按钮的父窗体就会收到WM_NOTIFICATION_MOVED_OUT这个消息,我们假设其父是个FRAMEWIN_Obj

则FRAMEWIN_Obj的回调函数FRAMEWIN__cbClient以及用户自定义回调函数会处理这个消息。为什么会是这样,因为,对一个对话框,其结构如下:

FrameWin_Obj:有一个儿子DialogClient

DialogClient:可有多个儿子,如Button, Edit, Text等

Button

<!--[if !vml]--> <!--[endif]-->        再次返回到 WM_HandlePID 接下来向本次触摸的窗体发送 WM_TOUCH 消息。

首先,如果是按下,则保存窗体句柄WM__CHWinLast.hWin = CHWin.hWin;然后发送消息:          Msg.Data.p = (void*)&StateNew;

          WM__SendTouchMessage (CHWin.hWin, &Msg);

按照上面的分析,一直调用,再次进入BUTTON.C中的_OnTouch函数:

此时,pMsg->Data.p!=NULL因此执行如下操作:

if (pMsg->Data.p) {  /* Something happened in our area (pressed or released) */

if (pState->Pressed) {

if ((pObj->Widget.State & BUTTON_STATE_PRESSED) == 0){   //如果不是按下状态

_ButtonPressed(hObj, pObj);

}

} else {

/* React only if button was pressed before ... avoid problems with moving / hiding windows above (such as dropdown) */

if (pObj->Widget.State & BUTTON_STATE_PRESSED) {   //如果是按下状态

_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);

}

}

}

static void _ButtonPressed (BUTTON_Handle hObj, BUTTON_Obj* pObj) {

WIDGET_OrState(hObj, BUTTON_STATE_PRESSED);

if (pObj->Widget.Win.Status & WM_SF_ISVIS) {

WM_NotifyParent(hObj, WM_NOTIFICATION_CLICKED);// 产生单击事件

}

}

此时,我们就可以在应用程序自定义的回调函数中处理按钮的按下和提起事件了。例如:

case WM_NOTIFY_PARENT:

Id    = WM_GetId(pMsg->hWinSrc);    /* Id of widget */

NCode = pMsg->Data.v;               /* Notification code */

switch (NCode) {

case WM_NOTIFICATION_RELEASED:    /* React only if released */

if (Id == GUI_ID_OK) {          /* OK Button */

GUI_MessageBox("This text is shown/nin a message box",

"Caption/Title", GUI_MESSAGEBOX_CF_MOVEABLE);

}

if (Id == GUI_ID_CANCEL) {      /* Cancel Button */

GUI_EndDialog(hWin, 1);

}

break;

}

break;

......................

ucGUI390 触摸消息响应过程相关推荐

  1. 非全屏Activity实现,以及触摸消息的处理

    非全屏Activity实现,以及触摸消息的处理 本次主要针对,非全屏的Activity做些了解: 作为初学者,之前接触到的activity大部分情况,都是全屏显示: 想要实现局部窗口的时候,都是采用悬 ...

  2. (转)非全屏Activity实现,以及触摸消息的处理

    做一个数据库APP,添加数据总是需要切换Activity,觉得太不流畅了,对theme不熟悉,就度娘了一下,先借鉴下这篇博文,效果还不错,准备等做完项目再好好研究一下相关的属性,现在先拿来主义.做出来 ...

  3. MFC 消息响应与消息处理过程

    WPARAM 和 LPARAM,消息响应机制 wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数: 一个是WORD类型的16位整型变量:另一 ...

  4. android触摸消息的派发过程

    1.触摸消息是消息获取模块直接派发给应用程序的. 2.触摸消息在处理时, 需要根据触摸坐标计算该消息应该派发给哪个View/ViewGroup, 在案件取消处理中不存在 该计算过程. 3.没有类似&q ...

  5. 触摸消息总体派发过程

    和按键派发类似,当消息获取模块通过pipe将消息传递到客户端, InputQueue中的next()函数内部 调 用 nativePollOnce()函数中会读取该消息.如果有消息,则 回 调View ...

  6. iOS实现ScrollView中子控件(Button,自定义View)的触摸事件响应

    最近要做个信息登记界面,在scrollView中添加了多个button和一个自定义的view(画板)来实现签名效果,画板中实现了touchBegin,touchMove等触摸事件方法.为了使butto ...

  7. 通过HTTP请求响应过程了解HTTP协议

    首先了解一次完整的HTTP请求到响应的过程需要的步骤 1. 域名解析 2. 发起TCP的3次握手 3. 建立TCP连接后发起http请求 4. 服务器端响应http请求,浏览器得到html代码 5. ...

  8. MFC中动态创建控件及添加消息响应的方法实例

    动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态控件: 为了对照,我们先来看一下静态控件的创建. 放置静态控件时必须先建立一个容器,一般是对话框, ...

  9. sip协议详解_SIP协议详解-INVITE消息发送过程

    SIP协议是VoIP中最重要的信令控制协议.SIP中第一件事情就是主叫发送INVITE给被叫,被叫响铃.本文从多角度详细描述INVITE消息发送的全过程. 一.阅读RFC权威描述 关于INVITE消息 ...

最新文章

  1. 机器学习实战 k-近邻算法 使用matplotlib创建散点图
  2. 边工作边刷题:70天一遍leetcode: day 27
  3. 关于webpack的使用
  4. 【跃迁之路】【731天】程序员高效学习方法论探索系列(实验阶段488-2019.2.21)...
  5. [python]逆水行舟不进则退(1)
  6. 对于多个 BAPI一起commit!
  7. npm mysql 事务_一文解读MySQL事务
  8. 利用python转换图片格式
  9. html中描述性文本,HTML5文本 描述性信息 引述
  10. 剑指offer面试题[17]-合并两个排序的链表
  11. php5 相关软件下载
  12. 用了很多年的 CMS 垃圾收集器,终于换成了 G1,真香!!
  13. 异常处理 Exceptions
  14. prism.js让页面代码变漂亮
  15. 部门管理系统_维修工单管理系统的功能介绍
  16. Directx11教程(60) tessellation学习(2)
  17. 一条命令关闭极域电子教室学生端
  18. 钓鱼网站检测技术的演进
  19. 刺猬猫服务器维护2020,刺猬猫杂谈:我认真起来连老板的号都敢封!
  20. 爬虫学习01 什么是爬虫 爬虫的分类

热门文章

  1. C# 委托及各种写法
  2. IE6、IE7、IE8之IE多版本共存的几种方法
  3. 商战计划商业逻辑和商业模式
  4. 【程序人生】:腾讯的职级系统
  5. Linux CentOS7 安装Oracle11gR2
  6. 两个整数相乘的java实现
  7. PowerDesigner数据建模
  8. 实验项目3———8枚硬币问题
  9. Mysql第一阶段结束语
  10. Source Insight 4.x完美激活破解安装图文教程