首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ucgui 中有关消息处理机制的问题

ucgui 中有关消息处理机制的问题

应该知道ucgui是应用消息驱动的,如同windows一般。只不过ucgui是一个相对于windows来说较简单的系统。因此ucgui的消息处理比较简单,并且消息类型也非常的少。在windows中最简的按钮处理事件是在WM_COMMAND消息中,通过按钮的标志ID来处理不同的按钮,当然,这种处理要求消息ID是有所不同的。在ucgui中游系统预留的ID,用户也可以按照#define GUI_ID_**  GUI_ID_USER+**来定义。
   如果要处理点击按钮这个事件,ucgui是在WM_NOTIFY_PARENT消息中处理的,这是被定义在回调函数中由用户自己编写。
   ucgui消息处理(其中有引荐他人之作,相互学习)
一,消息处理的流程.
ucgui是采用的消息驱动的. 它专门有对外的一套采集消息的接口, 我在模似器中,就是通过LCD窗口的MOUSE消息,将MOUSE移动, 点击消息传入到这个接口中, 以驱动UCGUI中的事件的..
UCGUI中的消息驱动, 其实与WINDOWS的是类似的, 几种基本的消息与WINDOWS是一样的, 但UCGUI的更简单,消息更少, 没有WINDOWS那么多的消息种类. 在WINDOWS中, 我们最简单处理按钮事件的是在WM_COMMAND消息中,通过按钮的标志ID来处理不同的按钮, 所以, 我们的按钮的标志ID都是不同的. 要不然无法区别开的.
要处理点击OK这个按钮的事件, UCGUI的处理方法有些不同, 是在WM_NOTIFY_PARENT消息中处理:
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc);
NCode = pMsg->Data.v;
switch (NCode) {
case WM_NOTIFICATION_RELEASED:
if (Id == GUI_ID_OK) {
GUI_EndDialog(hWin, 0);
}
if (Id == GUI_ID_CANCEL) {
GUI_EndDialog(hWin, 1);
}
break;
}
break;
ucgui中的消息非常的少, 只有差不多不到二十种, 其实这对于嵌入式系统来说, 已经完全足够了, 用户可以自定义消息,WM_NOTIFY_PARENT这个消息是由你窗体传送过来的, 是由函数WM_NotifyParent(hObj,Notification)实现的.
void WM_NotifyParent(WM_HWIN hWin, int Notification) {
WM_MESSAGE Msg;
Msg.MsgId = WM_NOTIFY_PARENT;
Msg.Data.v = Notification;
WM_SendToParent(hWin, &Msg);
}
这个函数相当简单, 其主要还是WM_SendToParent这个函数的调用, 这个函数又调用voidWM_SendMessage(WM_HWIN hWin, WM_MESSAGE* pMsg), 这个函数是最基本的一个消息处理函数,它的第一个参数指定了接受这个要处理的消息的句柄, 第二个指定了是哪类的消息.这个函数的主要作是,调用相应窗口的消息处理函数来处理消息.
比如说, 在这里,我们这个消息的处理过程是这样的, 首先, 你左键点击OK按钮,那么在GUI_Exec()这个窗体消息LOOP处理当中, 首先将此消息(WM_TOUCH)传给OK按钮(注意这也是一个窗体), 然后,OK按钮的消息处理函数将此消息再以WM_NOTIFY_PARENT传送到你窗体---对话框当中, 这样,对话框就可以处理到点击OK按扭这个事件了.
其实这个消息处理的流程与WINDOWS也是类似的. 原理一样.
理解了这个过程, 那么, 我们就可以这个消息中处理很多东西了, 只要是在对话框中的子控件, 一般的消息都可以如此处理.

二,发现存在的问题----两个独立的窗口并立时, 当关闭其中一个, 另外一个不再有响应.
在如下代码中处理弹出消息框, 点击对话框的OK后弹出消息框, 会出现当按对话框的Cancel关闭对话框后,弹出的消息框就没有任何响应的情况. 或者是关闭掉弹出的消息框, 对话框就没有任何响应的情形.
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc);
NCode = pMsg->Data.v;
switch (NCode) {
case WM_NOTIFICATION_RELEASED:
if (Id == GUI_ID_OK) {
/弹出消息框...
GUI_MessageBox("This text is shown\nin a message box",
"Caption/Title", GUI_MESSAGEBOX_CF_MOVEABLE);
GUI_EndDialog(hWin, 0);
}
if (Id == GUI_ID_CANCEL) {
GUI_EndDialog(hWin, 1);
}
break;
}
经分析, 粗步的原因是, 调用MainTask的主线程已经退出了, 这个主线程是在模拟器中开启的,它的主线程函数是Thread(), Thread函数里调用main, main再调用MainTask; 所以主线程退出后,消息框再也没有任何反应了.这是从模拟器的角度来分析, 现在我们分析一下, 为什么MainTask的主线程会这么早退出呢?
深入UCGUI的源码, 可以知道, 对话框的消息处理函数是在如下的函数中调用的.
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;
}
继承事业,薪火相传
返回列表