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

uCGUI多对话框弹出问题解析(2)

uCGUI多对话框弹出问题解析(2)

这是一个整体的消息处理完成的过程, 这个过程是一直LOOP, 反复检测的.想想如果是新弹出一个对话框, 又进入了新的消息LOOP, 那么可以肯定的是, 在新的消息LOOP处理当中, 由于上一次消息LOOP的第5步[更新消息]没有完成, 则新消息LOOP中当中就会反复处理这个没有更新的消息了. 然且这个过程是一个嵌套的过程, 一层的消息LOOP引发下一层的消息LOOP, 但都无法完成在短时间内最后一步的消息更新.
这里我说短时间内, 是指的新的消息还没有到来的时候, 因为新的消息一到来, 就终止了不断处理旧消息弹出对话框的过程.

[2].UCGUI中详细的消息处理流程:

在最新版的UCGUI390版, 消息的处理主要分成四个部分.

----模态窗口消息分发, 检测当前窗体是否与模态窗体有关, 即是否是模态窗体本身或者其子孙窗体, 用WM__IsInModalArea()检测;这一步控制了消息的分布, 实现模态窗体的功能就是这一句代码了.

----弹起与按下状态变化的消息分发(WM_PID_STATE_CHANGED消息), 这个消息的分布在按下MOUSE或者弹起MOUSE的时刻发生.

----只要是按下状态, 以及按下与弹起状态变化的消息分发(WM_TOUCH), 这个消息在MOUSE按下或者弹起, 以及一直处于按下时发送, 比如你按下一个BUTTON, 一直不放, 当移动到另一个BUTTON时, 会看到焦点发生了切换到了新的BUTTON上, 就是这个消息导致的.另外这个消息会在消息发生的新旧窗体交界时, 会最后向原来的旧窗体发最后一个WM_TOUCH消息(状态为弹起), 发送这个消息为了让原来的旧窗体改变自己的状态(如取消息焦点框等), 正如上面你按住MOUSE滑动新的BUTTON, 则原来的BUTTON的焦点状态取消, 不再高亮显示, 就是这个最后的消息发送导致的.

----移动的消息分发(WM_MOUSEOVER),这个消息是在打开了GUI_SUPPORT_MOUSE宏配置的时候才分发, 这个消息是很大量的, 只要MOUSE移动都会产生.

三. UCGUI324与UCGUI390版本在处理多对话框上的几点不同之处.

新旧版本主要有如下几点不一样:

[1].增中了模态窗体的支持, 这个在第二点中已经描述过了.
[2].增加了WM_MOUSEOVER消息.
[3].增加了WM_PID_STATE_CHANGED消息.

但是如果仅仅这个地方一点小变化, 也不足以让UCGUI390支持在按钮点击消息中弹出对话框, 还有如下几个变化:

[1].创建对话框的变化.
具体的问题, 请用户自己查看代码.

-----UCGUI324版中, 在创建对话框时, 用一个全局的回调函数_cbDialog(), 作为每个对话框的回调函数, 用一个全局变量_cb来保存用户对话框自己指定的回调函数. 然后在_cbDialog()函数中再调用用户对话框自己的回调函数(存在_cb变量中). 这显然是有问题的, 如果创建了新的对话框, 则这些全局变量就被新的赋值取代了, 就调用不到用户原来对话框指定的回调函数了.

-----UCGUI390版中, 就不再用什么全局变量了, 直接用用户指定的回调函数, 就不存在创建新的对话框后, 用户原来对话框指定的回调函数无法调用到的问题了.

[2].BUTTON按钮的点击消息处理的变化.

-----主要的差别在于, 新版当中加上了Button是否BUTTON_STATE_PRESSED状态的判断, 即在处理按下BUTTON弹起后, 要向父窗体发送出WM_NOTIFICATION_RELEASED消息前, 调用WIDGET_AndState(hObj, BUTTON_STATE_PRESSED);来取消Button的按下状态, 就是这一点, 就使得即使有未更新的消息再次处理, 也不会导致再次给父窗体发送Button弹起的消息, 从而避免了反复陷入弹出对话框, 消息处理中消息一直无法更新的问题.

[3].除了Button控件之外, 其它控件在单击消息中弹出对话框, 会出问题.

-----比较上面Button的处理, 问题就相当容易理解了, 因为其它控件没有关于BUTTON_STATE_PRESSED这种类似状态的判断, 所以导致了未更新的消息反复的处理, 在短时间内弹出一堆的对话框出来, 并且由于反复的消息LOOP嵌套, 导致加锁的没有解锁, 从而报出"GUITASK.c: GUI_Lock() _EntranceCnt overflow "的错误提示.

四. 如何改进UCGUI390, 以使其支持在任意控件的点击消息当中弹出对话框.

[1].弹出对话框时, 如果没有什么特别的问题, 可以使用模态对话框, UCGUI390中支持模态对话框, 由于是模态对话框, 那么先前未更新的旧窗体的消息, 就无法再进行处理了, 所以不会陷入反复的弹出对话框中去.

创建模态对话框:
{
    WM_HWIN hWinDlg =MESSAGEBOX_Create("   YouWin!!!   ", "Win",GUI_MESSAGEBOX_CF_MOVEABLE);
    WM_MakeModal(hWinDlg);
    GUI_ExecCreatedDialog(hWinDlg);
}

[2].如果是不采用弹出模态对话框, 我想另外的办法就是, 改进每个控件,对于MOUSE弹起消息转发父窗体时, 加上类似BUTTON的控制, 加上一个状态的识别,就可以了, 但这要改动几乎每个控件的_OnTouch()处理.

[3].前面说过, 正是因为弹出的对话框进入了新的消息LOOP, 导致原来的对话框的消息LOOP无法再执行下去, 无法更新旧消息变量. 那么我们就可以采取不让新建的对话框开启新的消息LOOP, 这很容易, 打开对话框时如下:

MESSAGEBOX_Create(ListItemName,"sel item is", GUI_MESSAGEBOX_CF_MOVEABLE);

这里仅创建对话框, 而不执行 GUI_ExecCreatedDialog(hWin), 就不会开启新的消息LOOP; 那消息LOOP放到哪里去呢?直接放到MainTask()当中去:

    while(1) {GUI_Exec();};
继承事业,薪火相传
返回列表