- 浏览: 155522 次
- 性别:
- 来自: 杭州
文章分类
最新评论
ucGUI390 触摸消息响应过程
ucGUI390 触摸消息响应过程
by Nathan.Yu <chsdate year="2006" month="12" day="11" islunardate="False" isrocdate="False" w:st="on">2006-12-11</chsdate>
触笔触摸屏幕->
产生中断->
中断处理获得触摸物理坐标->
其后(仍在中断处理函数中)的处理过程:
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 gte vml 1]><v:rect id="_x0000_s1032" style='position:absolute; left:0;text-align:left;margin-left:18pt;margin-top:0;width:180pt;height:15.6pt; z-index:3;mso-position-horizontal:absolute;mso-position-vertical:absolute'> <v:fill opacity="0" /> </v:rect><![endif]--><!--[if !vml]--><!--[endif]--> WM_pfHandlePID = WM_HandlePID;
#endif
}
->
中断返回->
进入以下函数,循环执行:
GUI_Exec()->GUI_Exec1()->WM_Exec()->WM_Exec1()->
在WM_Exec1()函数中做如下判断:
<!--[if gte vml 1]><v:rect id="_x0000_s1031" style='position:absolute; left:0;text-align:left;margin-left:18pt;margin-top:0;width:89.85pt;height:15.6pt; z-index:2;mso-position-horizontal:absolute;mso-position-vertical:absolute'> <v:fill opacity="0" /> </v:rect><![endif]--><!--[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);//yhm<chmetcnv w:st="on" unitname="ac" sourcevalue="20061211" hasspace="False" negative="False" numbertype="1" tcsc="0">20061211AC</chmetcnv>, WM__FirstWin = hNew; in //func _AddToLinList
WM_UNLOCK();
return r; //yhm<chmetcnv w:st="on" unitname="ac" sourcevalue="20061211" hasspace="False" negative="False" numbertype="1" tcsc="0">20061211AC</chmetcnv>,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以及用户自定义回调函数会处理这个消息。为什么会是这样,因为,对一个对话框,其结构如下:
<!--[if mso & !supportInlineShapes & supportFields]><span lang=EN-US><span style='mso-element:field-begin;mso-field-lock:yes'></span><span style='mso-spacerun:yes'></span>SHAPE <span style='mso-spacerun:yes'></span>/* MERGEFORMAT <span style='mso-element:field-separator'></span></span><![endif]--><!--[if gte vml 1]><v:group id="_x0000_s1026" editas="canvas" style='width:414pt;height:241.8pt;mso-position-horizontal-relative:char; mso-position-vertical-relative:line' coordorigin="2362,2545" coordsize="7200,4212"> <o:lock v:ext="edit" aspectratio="t" /> <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_s1027" type="#_x0000_t75" style='position:absolute; left:2362;top:2545;width:7200;height:4212' o:preferrelative="f"> <v:fill o:detectmouseclick="t" /> <v:path o:extrusionok="t" o:connecttype="none" /> <o:lock v:ext="edit" text="t" /> </v:shape><v:rect id="_x0000_s1028" style='position:absolute;left:2988;top:2681; width:5791;height:3668' fillcolor="blue"> <v:textbox> <![if !mso]> <table cellpadding=0 cellspacing=0 width="100%"> <tr> <td><![endif]> <div> <p class=MsoNormal><span lang=EN-US>FrameWin_Obj:</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family: "Times New Roman"'>有一个儿子</span><span lang=EN-US>DialogClient</span></p> </div> <![if !mso]></td> </tr> </table> <![endif]></v:textbox> </v:rect><v:rect id="_x0000_s1029" style='position:absolute;left:3771;top:3088; width:4226;height:2718' fillcolor="red"> <v:textbox> <![if !mso]> <table cellpadding=0 cellspacing=0 width="100%"> <tr> <td><![endif]> <div> <p class=MsoNormal><span lang=EN-US>DialogClient:</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family: "Times New Roman"'>可有多个儿子,如</span><span lang=EN-US>Button, Edit, Text</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family: "Times New Roman"'>等</span></p> </div> <![if !mso]></td> </tr> </table> <![endif]></v:textbox> </v:rect><v:rect id="_x0000_s1030" style='position:absolute;left:4866;top:3904; width:2192;height:1087' fillcolor="green"> <v:textbox> <![if !mso]> <table cellpadding=0 cellspacing=0 width="100%"> <tr> <td><![endif]> <div> <p class=MsoNormal><span lang=EN-US>Button</span></p> </div> <![if !mso]></td> </tr> </table> <![endif]></v:textbox> </v:rect><w:wrap type="none" /> <w:anchorlock /> </v:group><![endif]--><!--[if !vml]--><!--[endif]--><!--[if mso & !supportInlineShapes & supportFields]><span lang=EN-US><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:414pt; height:241.8pt'> <v:imagedata croptop="-65520f" cropbottom="65520f" /> </v:shape><span style='mso-element:field-end'></span></span><![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,开发者需要了解其API接口,通过调用相关函数来实现界面布局、图形绘制、事件响应等功能。同时,根据提供的资料,可能还会包含示例代码、配置指南、API文档等,帮助开发者快速上手和深入理解UCGUI...
ucGui是一款轻量级的...总的来说,ucGui触摸屏移植是一个涉及硬件、软件和用户交互设计的综合过程。通过深入理解ucGui的工作原理和触摸屏技术,开发者可以成功地将触摸功能集成到他们的嵌入式产品中,提升用户体验。
通过UCGUI390,开发者可以在μC/OS平台上实现复杂的图形操作,如动画效果、触摸屏支持以及自定义的图形绘制。 UCGUI390的特性包括: 1. **小内存占用**:UCGUI390针对微控制器的有限资源进行了优化,能够在极低的...
综上所述,《ucgui触摸屏移植手册》不仅为开发者提供了清晰的实施路径,还强调了在移植过程中需要注意的细节。通过遵循上述步骤,开发者可以有效地将触摸屏功能集成到基于ucgui的嵌入式项目中,从而提升用户体验和...
4. **触摸屏支持**:对于配备触摸屏的设备,UCGUI提供了触摸事件处理机制,可以轻松实现触控操作的用户界面。 5. **内存优化**:考虑到嵌入式系统的资源限制,UCGUI在内存使用上进行了优化,例如使用位图操作函数来...
标题中的"S3C44B0+UCOSII+UCGUI+触摸屏+摄像头"是一个嵌入式系统开发的综合项目,涉及到多个关键组件和技术。接下来,我们将详细探讨这些技术及其在实际应用中的作用。 首先,S3C44B0是一款由Samsung公司生产的ARM7...
ucGUI390a可能是ucGUI的一个特定版本,版本号中的“390a”可能代表该库的更新或修订版。 ucGUI的核心特性包括: 1. **跨平台兼容性**:ucGUI设计时考虑了不同硬件平台的兼容性,能够运行在多种微处理器和操作系统上...
在该DEMO程序中,uCGUI可能已经预设了一些基本的界面布局和交互逻辑,例如触摸屏的事件响应,使开发者可以快速搭建出具有视觉吸引力且易于操作的用户界面。 至于触摸屏的支持,这通常涉及到STM32的GPIO口或特定的...
ucGUI提供了一些API用于处理触摸事件,如`GUI_TOUCH_GetState()`,你需要将硬件的触点坐标转换为 ucGUI 的逻辑坐标,以便于UI组件的响应。 在实际应用中,你可能还需要定制化ucGUI的主题、布局和控件样式以满足项目...
### UCGUI消息机制的应用 #### 一、引言 UCGUI(User Control Graphical User Interface)是一款轻量级的嵌入式图形用户界面库,主要用于资源受限的嵌入式设备上,提供丰富的图形界面功能。UCGUI的核心之一是其...
4. **事件驱动**:ucGUI 采用事件驱动模型,处理用户的触摸或其他输入事件,使得程序响应更及时。 5. **低内存占用**:考虑到嵌入式系统的资源限制,ucGUI 设计时特别注重内存占用,力求在最小的内存空间内实现高效...
这通常涉及到中断处理,确保实时响应用户的触摸操作。 再者,TFT320*240液晶显示屏是一种常见的彩色显示设备,具有较高的分辨率。在PIC32上驱动这种屏幕,需要配置适当的LCD控制器,设置时序参数,以及正确地发送...
4. **灵活的事件处理机制**:通过事件驱动的编程模型,UCGUI允许用户响应触摸屏、按键等输入事件。 5. **丰富的图形元素**:包括文本、图像、按钮、滑块、列表框等多种控件,能够构建复杂的用户界面。 6. **自定义...
5. **事件驱动机制**:ucGUI基于事件驱动的编程模型,用户交互事件(如触摸屏点击)会被转化为内部事件,通过事件处理函数进行响应。 6. **编译工具链兼容性**:ucGUI提供了Makefile和批处理脚本(如MakeLib.bat、...
这些输入设备产生的消息,如滑动操作、触摸屏输入消息(WM_TOUCH)以及按键式操作消息(WM_KEY),均需经过特定的处理机制才能被窗体正确识别和响应。UCGUI为此提供了一套完善的消息处理流程,确保无论是哪一种输入方式...
3. 事件处理:ucGUI的事件模型是基于消息队列的。虽然在这个版本中没有触摸屏,但我们可以模拟键盘输入来触发事件,例如通过按键来模拟点击事件。 4. 编译与调试:编译ucGUI源码并与STM32固件链接,然后通过调试器...
《UCGUI在Mini2440上的移植与触摸屏应用》 UCGUI,全称User Control Graphical User Interface,是一款专为嵌入式系统设计的图形用户界面库,尤其适用于资源有限的微控制器环境。本篇文章将深入探讨如何在基于...
5. **消息循环**:在主程序中设置一个消息循环,处理来自UCGUI的消息,保持界面的实时响应。 6. **销毁和释放**:当不再需要某个窗口或控件时,需要销毁并释放相关资源,防止内存泄漏。 在阅读UCGUI的中文说明手册...
6. **触摸屏支持**:ucGUI提供触摸屏输入设备的驱动框架,可适应不同类型的触摸屏。 在ads(ARM Developer Suite)环境下,ucGUI的应用实例可以帮助开发者快速上手。ads是ARM公司开发的一套针对ARM处理器的集成开发...