标题:
UCGUI窗体管理及消息处理机制分析(4)
[打印本页]
作者:
yuyang911220
时间:
2014-11-29 12:57
标题:
UCGUI窗体管理及消息处理机制分析(4)
二、发现存在的问题
-----点击OK后无论先关闭消息框还是对话框,另一个不再响应.
点击对话框的OK后弹出消息框, 会出现当按下对话框的Cancel关闭对话框后, 弹出的消息框就没有任何响应的情况. 或者是关闭掉弹出的消息框, 对话框就没有任何响应的情形:从外部粗步分析的原因是调用MainTask的线程已经退出了, 这个线程是在模拟器中开启的专门用于运行GUI任务的线程,它的线程函数是Thread, Thread函数里调用main,main中再调用MainTask,所以该线程退出后也就代表UCGUI任务已经结束了。这是从模拟器的角度来分析, 现在我们分析一下为什么MainTask的调用线程会这么早退出呢?
由我们第一节中关于GUI_ExecDialogBox所做的几件中可以分析到, 当UCGUI中有一个独立的窗体退出后_cb会被清为0, 此时退出GUI窗口LOOP. 即结束了UCGUI窗口消息处理。
其实, GUI_MessageBox弹出的消息框其实也是一种对话框, 这最终调用的还是GUI_ExecDialogBox,开始我们就分析过,进入这个函数后,会有一个全局变量记录当前对话框窗体的消息处理函数指针,但是目前的问题如下:
Ø
已经建立了两个这样的对话框窗体,这样一个全局变量来记载当前对话框的窗体消息处理函数指针显然不够,而且先前打开的对话框的的用户指定的窗体消息回调函数已经不再被调用了,此时第一个对话框的由子窗体回传到父窗体的消息均会传到第二次打开的对话框的用户指定的窗体消息回调函数中.
Ø
第二次弹出消息框再次进入GUI_ExecDialogBox中的 while循环后,先前的对话框中的while循环就被挂起了,直至第二次的GUI_ExecDialogBox中的 while循环退出,无论关闭消息框还是对话框,都会导致知退出第二次消息LOOP。第二次消息LOOP退出后返回点为弹出消息框后的下一句,直至返回到第一个对话框的while循环后退出GUI_ExecDialogBox.
但我们期待的结果是,点击对话框的OK弹出消息框, 关闭掉对话框或是消息框,其它的都要对话框继续有反应,下面我们就来分析一下如何达到这个目标,看看要做些什么具体的改动:
三、UCGUI中的消息LOOP处理分析
-----寻找问题的解决办法.
在我们发现这个问题, 我们已经粗步分析了,问题不是出在我们编写程序上, 而上UCGUI的内部,那么要解决这个问题, 我们就要进一步了解UCGUI的窗口体系。其实换一句话说,在嵌入式应用中,窗口的强大直接决定到GUI系统的体积大小,并不是所有的情况都要有这种支持,当然我们希望在下一版本可以有多个对话框的直接支持。
创建对话框:
void MainTask(void)
{
GUI_Init();
WM_SetDesktopColor(GUI_RED);
WM_SetCreateFlags(WM_CF_MEMDEV);
GUI_ExecDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
}
上面是我们创建对话框的程序,是我们编写的代码, GUI_ExecDialogBox()这个函数的作用我们已经分析过了,它所做的事用一句话来说就是创建对话框并进入窗体消息LOOP处理,下面将详细分析一下LOOP消息的处理流程:
int GUI_ExecDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget,
int NumWidgets, WM_CALLBACK* cb, WM_HWIN hParent,
int x0, int y0)
{
_cb = cb;
GUI_CreateDialogBox(paWidget, NumWidgets, _cbDialog,hParent, x0, y0);
while(_cb){
if (!GUI_Exec())
GUI_X_ExecIdle();
}
return _r;
}
这个LOOP类似我们非常熟悉的WIN下面的消息LOOP, 其原理是一致的. GUI_CreateDialogBox负责创建对话框的所有子窗体,特别注意它其中一个参数传入是Dialog.c中定义的_cbDialog,这个函数什么也没做,基本上是转而调用_cb,后面我们会提到关于它的修改。_cb是对话框的用户定义窗口消息处理函数,这里面有一个判断,就是_cb非空时,才进行消息LOOP, _cb在Dialog.c中的定义为:[static WM_CALLBACK* _cb;] _cb是一个全局变量,我们程序中创建对话框与弹出消息框时两次调用了GUI_ExecDialogBox,后一次的_cb将会把前面的值冲,它是用户自定义的窗口消息处理函数。
在while中有判断, 那么可见_cb是在GUI_Exec之中是有使用的,对话框的FrameWin子窗体消息流转调如下面的所示,窗口消息处理函数是在WM_SendMessage中通过函数指针的调用中, 注意[]内部的就是真正被调用来处理消息的函数:
GUI_Exec-->GUI_Exec1-->WM_Exec-->WM_Exec1-->WM_HandlePID-->WM_SendMessage-->(*pWin->cb)(pMsg)[_FRAMEWIN_Callback]-->_OnTouch()-->(*cb)(pMsg)[_cbDialog]--> *_cb)(pMsg)[_MESSAGEBOX_cbCallback]
Ø
WM_HandlePID()------专门处理类似MOUSE的滑动操作外设消息的函数.
Ø
WM_SendMessage()----基层的发送消息的函数,即调用相对应的窗体的消息回调函数来处理消息.
现在讲到了窗体消息LOOP,在窗体系统中最根本一点的就是对外部输入消息的处理,窗体就是靠消息驱动的,其处理代码如下:
int WM_Exec1(void){
if(WM_pfPollPID){/* Poll PID if necessary */
WM_pfPollPID();
}
if(WM_pfHandlePID){
if (WM_pfHandlePID())
return 1;
/* We have done something ... */
}
if(GUI_PollKeyMsg()){
return 1;
/* We have done something ... */
}
if(WM_IsActive && WM__NumInvalidWindows) {
WM_LOCK();
_DrawNext();
WM_UNLOCK();
return 1;
/* We have done something ... */
}
return 0;
/* There was nothing to do ... */
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0