触笔触摸屏幕->

产生中断->

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

/**************************************************************************/

这里也可以在程序建立一个任务,来不断地调用GUI_TOUCH_Exec函数

这里是需要调用四次的,每次读取一次x或是y。

第一次读取,调用_StoreUnstable(x, y)函数。这个函数中包含一个消除抖动的过程,处理的也很巧妙。

第二次读取已经去掉抖动了。调用GUI_TOUCH_StoreUnstable函数

/**************************************************************************/

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

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)

WM_pfHandlePID = WM_HandlePID;

#endif

}

->

中断返回->

/**************************************************************************/

GUI_Exec()函数可以通过GUI_WaitKey()来调用。

/**************************************************************************/

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

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

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

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以及用户自定义回调函数会处理这个消息。为什么会是这样,因为,对一个对话框,其结构如下:

再次返回到 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);
    
 }

}

/***********************************************************************************************/

_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);这个函数中,调用了

void GUI_StoreKey(int Key) {
  if (!_Key) {
    _Key = Key;
  }
  GUI_X_SIGNAL_EVENT();
}

而在GUI_WaitKey中会调用

int GUI_GetKey(void) {
  int r = _Key;
  _Key = 0;
  return r;
}

/************************************************************************************************/

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;

ucgui触摸屏消息处理相关推荐

  1. UCGUI的模拟器UCGUISim详解

    From: http://www.cnblogs.com/shellstudio/articles/ucgui.html 本文转自www.ucgui.com感谢原作者(最近发现该网站已经撤销,不知道作 ...

  2. emWin 2天速成实例教程000_如何快速入门ucGUI/emWin

    备注:(1)打开工程目录下的"Exe\GUISimulationDebug.exe"即可看到效果.(2)看完教程000-005就基本会用emWin做项目,其他章节可以需要时再参考. ...

  3. EmWin学习课堂_小白EmWin_EmWin快速入门_EmWin动态内存,显示和触摸屏_EmWin基础配置

    一.先说说什么是EmWin,它就是一款中间软件包,弄好了之后,我们的界面设计就会变得很简单,在电脑GUI_Builder上做一个界面,生成.c文件,复制到自己的工程里面,我们的显示屏就能得到一模一样的 ...

  4. 【转】基于SAM3U + CooCox CoOS + UCGUI的MP3设计 (1)

    我们的设计方案是在英蓓特公司的EM-SAM3U开发板(ATMEL ATSAM3U4E内核)上设计一个完整的MP3播放器,它的功能包括: 1. 能够从SD卡读取音乐文件及中文字库: 2. 能够播放wav ...

  5. [stm32][ucos][ucgui] 2、LED闪烁、串口、滑块、文本编辑框简单例程

    上一篇:[stm32][ucos] 1.基于ucos操作系统的LED闪烁.串口通信简单例程 * 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了7个任务             任务名  ...

  6. ucgui下制作漂亮按键

    源:ucgui下制作漂亮按键 转载于:https://www.cnblogs.com/LittleTiger/p/10313161.html

  7. 一步一步实现自己的模拟控件(9)——消息处理

    这次我们将要给Widget增加一些状态,并使其能够接受出消息处理扩展,测试工程中实现了一个按钮的消息处理扩展. Widget状态: 之前的控件只是绘制了一个边框,并且总是会在窗口中显示.实际上我们往往 ...

  8. 4.1 ucGUI 图片显示方法

    图片显示步骤 1.运行uC-GUI-BitmapConvert.exe,打开图片file->open. 该文件在ucgui3.98\Micrium\Software\uC-GUI\Tool 目录 ...

  9. 威纶通触摸屏与单片机MODBUS_威纶通案例集锦51-55

    51 三菱PLC可读不可写 Q:MT8102IQ和三菱Q系列PLC通讯,屏无法写入PLC,但是可以读取PLC的状态和数值? A:PLC程序中"允许RUN中写入"打钩,程序下载重启后 ...

最新文章

  1. python使用imbalanced-learn的SMOTETomek方法同时进行上采样和下采样处理数据不平衡问题
  2. 在TSQL中替换换行符
  3. offSet().left 与position().left的区别
  4. QtQuick 中的 qml 与 Qt 的 C++
  5. Android-消息机制总结
  6. ltp-ddt realtime_cpu_load涉及的cyclictest 交叉编译
  7. ORACLE PL/SQ入门
  8. [转]我不敢!⋯⋯⋯⋯致所有拼搏的年輕人。
  9. -bash: vim: command not found 两种解决方法
  10. 网易用户认证架构设计 | session token | 公开课笔记-01
  11. asp.net2.0自定义控件---鼠标移到按钮上更改背景颜色,移出后恢复
  12. VS2010中配置OpenGL的一些问题小结
  13. 用R进行文本挖掘与分析--软件分词统计词频
  14. chrome 开启HEVC硬件解码
  15. C++ MFC控件重影-编辑框重影
  16. Sample抽样函数
  17. php 根据时间算年龄,PHP根据出生日期计算年龄的方法
  18. 目前流行的装修风格_2020最新装修风格,目前流行的装修风格,值得收藏!
  19. 许久不动笔,,再来点人生感悟吧
  20. 福利来啦!花瓣网图片批量下载助手APP终于完工,再也不用一张一张保存美图了。

热门文章

  1. React自定义组件使用onClick传参注意:onClick只是一个名字而已!
  2. DL/T645-2007 与DL/T645-1997协议解析对比
  3. 程序员合同日期不到想辞职_“我又辞职了”
  4. 顺通订单及客户档案资料管理系统
  5. 专升本英语——英语的九种时态总结
  6. 2022 Jiangsu Collegiate Programming Contest I. Cutting Suffix
  7. HTTP协议格式以及Fiddler用法
  8. 相机模型-鱼眼模型/鱼眼镜头标定基本原理及实现(2)
  9. 在Windows中开启Wifi热点共享,无需第三方工具
  10. 互动百科疑借“反垄断”进行炒作