分类: 其他UNIX
2019-02-23 22:19:33
windMl应用开发
在windMl的模板库基础上,来实现应用开发。因为模板库的模式相对简单,大量的工作需要在后期实现,因此在应用开发上就显得相对繁琐,目前还未找到更简单、更容易实现的方式。
7.1 启动窗体的主入口实现
此步骤主要用来生成整个背景窗口及状态条,时间窗等。通过调用函数createGUI()来实现此过程,相对简单。函数的参数为一个结构,存放了主菜单下各项对应的入口函数及参数。示例:(具体格式请查阅相关头文件)
UGL_LOCAL APP_ITEM apps [] =
{
{ "电表设置", (void (* ) (void *)) DMParamSet, UGL_NULL },
{ "主站通讯设置", (void (* ) (void *)) HostSet, UGL_NULL },
{ "数据清除", (void (* ) (void *)) DataClear, UGL_NULL },
{ "数据查看", (void (* ) (void *)) DataBrowse, UGL_NULL },
{ "通讯监视", (void (* ) (void *)) CommWatch, UGL_NULL },
{ "版本……", (void (* ) (void *)) ShowEdition, UGL_NULL },
{ UGL_NULL, UGL_NULL, UGL_NULL }
};
void gui(void)
{
if (bHMI) return ;
bHMI = TRUE ;
createGUI(apps);
}
注意事项:
1、 注意图形界面的重新启动,在gui函数的头部放置一个bool型的表征已经启动的变量,每次启动时首先判断此变量是否为真,为真时表明有一个gui已经启动,此时不能再启动其他gui。
2、 窗体参数的传入,一般窗体的数据需要用结构传入,在gui启动后需要对各窗体的参数结构进行初始化。
3、 缺省工作路径的定义,在进入gui后可能需要进行参数传递等工作,此时就需要用到缺省的工作路径,未定义情况下,缺省工作路径为系统文件(“vxworks”文件)所在目录,如需修改使用函数ioDefPathSet("/ata0a");定义即可。
4、 一些特定处理函数需要用户另行输入,如系统重启函数、系统关闭函数等,创建方式如SetCloseSystem(ExitMpe5); SetExitGui(ExitGui); SetReStartFunc(SysReStart);,分别对应设置系统关闭函数,设置系统退出函数,设置系统重启函数,这些要求在启动gui前完成。
此步骤完成后,启动后运行gui函数即可看到系统下拉菜单,空背景,及时间框,如果有鼠标的话,将鼠标移至时间框上,还可看到日期框。
弹出下拉菜单,如果上述示例种apps为空(NULL),则在菜单条中会存在“系统设置”,“用户权限管理”,“登录/注销”,“退出图形界面”,“关闭终端”等菜单项,这些都是有模板库提供的。点击其中一项即可打开相应的页面(可能还需要权限),系统设置中包括了系统时间设置,IP地址设置,以及桌面背景,屏保选择等,其他各项很简单,不再累述。
7.2 窗体实现
窗体实现为模板库应用最多的地方,也是构建一个图形界面主题的大部分工作,目前模板库支持的全部为对话框模式,所以做界面工作就象VC中的对话框一样,需要拼接各个控件在一个主窗体上。
目前模板库依靠C语言建立,并没有形成图形模式的控件拼接助手,因此所有的拼接工作都依靠代码来实现。
7.2.1 生成主窗体
生成主窗体依靠函数:main_Create_Close或者main_Create,两个函数区别在于是否在窗体左上角添加关闭按钮。比如:
winId = (WIN_ID)main_Create_Close (appText, 0, 300, 280, sizeof (DATA_CLEAR));
其中appText为窗体生成后的标题栏和任务栏显示的内容,即窗口的标题,可用字符串直接带入,第二个参数为窗体占用堆栈大小,0表示使用缺省值10000,一般使用缺省即可,也可以手动赋值,随后的两个数字为窗体的宽和高,可先赋值,后根据实际显示确定,最后一个参数为窗体创建时附带创建参数区域的大小,可利用此区域来传递数据。一般窗体数据的用法是,创建一个结构,然后将窗体数据区大小赋值为该结构的大小,之后利用此结构的一个指针来引用窗体数据,获取指针地址的函数为GetData(winId),参数即为上述主窗体生成函数返回的窗体ID号,例如:
DATA_CLEAR *wData ;// DATA_CLEAR即为上述示例中创建的窗体数据大小的结构
wData = GetData(winId);
窗体数据结构中一般包括:准备在此主窗体上创建的控件ID,此窗体编辑的参数区域的地址等信息。
7.2.2 放置控件
各个控件放置时,同样需要依靠代码来完成,目前模板库中完成的控件包括:button、textbox、lable、checkbox、radiobox、comBox、listBox、richtextbox、Schedule、TabControl、TimeSetBox、textlistbox。
部分控件作用如下:
comBox,其基础是文本框,增加了下拉式表单为用户提供可选的缺省文字,操作方式与textbox基本相同,仅增加初始化时的缺省文字列表。
Schedule,进度条,用来表征一项工作的进度情况。
TabControl,作用相当VC中tab控件,左侧为tab项,右侧为该tab项的窗体。
TimeSetBox,如字面意思,时间控件。
Textlistbox,为组合框,在下拉式表单中选择一项作为选择,不能手动输入。
其他各控件如字面意思,不再重述。
以button示例,说明控件的使用方式。
wData->ExitId=( WIN_ID ) winButtonCreate(winId," 退 出 ", 175, 240, 60,22,(WIN_CB*)cbDefaultDeny, UGL_NULL);
此函数在主窗体winId上创建一个button,button上面文字为“退出”,175, 240, 60,22表示位置和长宽,最后两个表示回调函数,即点击该按钮后引发的动作。
(WIN_CB*)cbDefaultDeny为一个窗体回调函数,用来作为响应用户的某一动作,或者系统的某一消息,参见下文。
详细请参阅模板库手册。
7.2.3 窗体回调函数
格式:UGL_LOCAL UGL_STATUS cbFunc(WIN_ID winId, WIN_MSG *pMsg, void *pData, void *pParam);
窗体回调函数表示在窗体获取某一种或者某一个消息时,所使用的处理函数,其参数格式固定,不能修改,最后一项pParam为可传参数项,即此项参数可直接传入。
上述示例中winButtonCreate最后一项参数UGL_NULL就是cbDefaultDeny回调函数的参数项pParam,依靠此用法,可将窗体数据传入每个操作用回调函数,可直接操作窗体上的其他各控件。
前三项参数分别解释:
WIN_ID winId,窗体ID,是当前控件的控件的ID而不是主窗体,如果需要使用主窗体ID可使用winParent(winId)来获取。
WIN_MSG *pMsg为当前系统窗体给当前控件的消息结构,可参阅WIN_MSG结构声明获取消息信息。
void *pData为当前控件的数据区,类似与前述的窗体数据,每个控件也有各自的数据区域,但要注意,如果没有该区域的参数类型及结构定义,不要使用该区域的任何空间,否则可能造成wwm死锁。
7.2.3 窗体参数
如上述所的,窗体参数即窗体数据一般都包括窗体上各控件的ID和窗体需处理的参数区域的指针,并且可通过各种控件创建时传入各控件的处理函数。这样在每个控件的处理中就可以直接获取或者直接设置窗体上其他控件的状态。
如在上述示例中,结构DATA_CLEAR包含两个ID,一个sure(button类型),另一个为TextBoxId(textbox,利用其创建函数创建),其创建函数如下,其中wData为DATA_CLEAR*型数据指针:
wData ->TextBoxId= winTextBoxCreate(winId,"",100,20,150,20,0,0);
wData ->sure = winButtonCreate(winId,"确定",73,70,44,20,cbLineSure,wData);
如此,则在button的回调cbLineSure中,就可以直接获取和设置TextBoxId中的文本内容了,如下:
UGL_LOCAL UGL_STATUS cbLineSure(WIN_ID winId,
WIN_MSG *pMsg,void *pData,void *pParam)
{
Char sText[60];
GetTextBoxText(pParam-> TextBoxId, sText);
Printf(“%s”, sText);
SetTextBoxText(pParam-> TextBoxId, “Test Text”);
Return OK;
}
同样,普通参数也可以如此使用,其作用相似于在窗体内的全局变量,作用范围在每个包含了其指针的回调函数中。
7.2.4 快捷键
快捷键主要针对button,对一个窗体来说,一般都会有类似于确认和取消这样的按钮(象保存退出和不保存退出),模板库提供了两个键盘按钮与之对应,Enter和Esc,使用方式为
Add_Key_ESC(winId, deny);//按下ESC键则相当于按下deny对应的button
Add_Key_Enter(winId, sure); //按下Enter键则相当于按下sure对应的button
当然,您也可以不添加这样的东西,此时按下这两个按钮没有任何作用的。
7.2.5注意事项
1、 并非所有的控件都有回调函数,使用时注意查看其创建函数声明。
2、 回调函数中使用传入参数时,注意类型的强制转换,因为缺省情况下pParam类型是void*,一个简单的方式是,在写回调函数时直接简单的将函数定义的参数部分中将void*改为所需的参数类型极了。
3、 部分特定按钮的回调已经提供,如退出按钮的cbDefaultDeny回调函数,如不需要特殊的退出动作,直接使用即可。
7.3 图形调试说明
图形界面在调试过程中比较繁琐,因为没有所见即所得的拼接控件技术,所以需要不断的编译后启动才能看到之前定义的图形,再修改,再编译,直到达到设计的目的为准。
由于使用了模板库,因此当单步跟踪时,会出现断线的问题,所以调试中用的最多的方式还是过程打印,即利用printf函数来判断程序处理结果。另外模板库内通过了singlemassage或者messagebox等函数,可用来在图形界面上输出一些信息。
模板库同时提供如命令行、闪烁文本等控件和调试手段,详细请查阅模板库函数列表。
7.4 其他注意事项
1、 在编辑参数过程中,当用户未确认或者未保存时,用户在界面所有修改均不能带入系统正常参数地址内。也就是说,创建窗体时所有的参数内容均为临时创建,只有当用户保存确认后才能真正存入系统参数内,确保系统的正确运行。
2、 为保证wwm初时任务堆栈不被冲垮,所有的主窗体创建时利用任务创建,如taskSpawn("DataClear", 100, VX_FP_TASK, 1000000, (FUNCPTR)DataClear0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);,这样用独立的空间来启动该窗体,而不是直接在wwm中启动该窗体。
3、 对用户权限的处理,模板库提供了用户权限的控制和处理,因此在每个窗体创建时需要引入此控制,保证每个页面操作员都有相应的权限,添加方式如:if (check_popedom(AUTHORITY_ADMIN,appText)!=UGL_STATUS_OK) return;其中函数的第一个参数表示本窗体所需要的权限,而第二个参数是本窗体标题,用来确认本窗体没有启动。
4、 在一些特殊处理中,如遥控下发时,每一次动作都需要用户重输密码,确保用户的误操作而造成的损失。
5、 完善出错控制,如添加listbox项时已经超过listbox最大范围,此时虽然模板库会报告错误,如果用户不处理仍进行下一步操作的话,则会出现严重错误。
6、 一些控件的回调函数在创建时会缺省执行一次,如radiobutton,如果其要处理的控件还没有创建,则会出错,修改办法一是将需要处理的控件创建前提至radiobutton创建之前,另一种方案是,在创建radiobutton不加入回调函数,而在所有的控件添加完成后,利用wincbadd往控件radiobutton上添加函数,具体操作浏览模板库手册。