2011-9-7
ucgui的一个小缺陷
通过使用ucgui发现了一个设计缺陷:创建控件和相应的回调函数之间没有共同的参数!回调函数的参数只有一个msg变量,记录当前窗口,消息发送源窗口的句柄。即创建函数和它的回调函数间没有使用一个共同的参数,这导致一个使用上的缺点,不知道是不是无法实现还是怎么的,先说说这个缺点。
void __DrawExplorer (int iFrameX0, int iFrameY0, int iFrameXsize, int iFrameYsize)
{
FRAMEWIN_Handle hFrame;
/*
* create framewin
*/
hFrame = FRAMEWIN_CreateEx (
iFrameX0,
iFrameY0,
iFrameXsize,
iFrameYsize,
NULL, WM_CF_SHOW | WM_CF_MEMDEV,
0, 0, "Explorer", __explorerFrameCallback);
}
static void __explorerFrameCallback (WM_MESSAGE *pmsgMsg)
{
/*
* 伪代码
*/
__explorerSame(); // 所有explorer共性的代码
__explorerDifferCallback(); // 根据实例的不同回调,由应用去安装
}
typedef struct {
int MsgId; /* type of message */
WM_HWIN hWin; /* Destination window */
WM_HWIN hWinSrc; /* Source window */
union {
const void* p; /* Some messages need more info ... Pointer is declared "const" because some systems (M16C) have 4 byte const, byte 2 byte default ptrs */
int v;
GUI_COLOR Color;
} Data;
} WM_MESSAGE;
如果同时创建两个explorer但是参数不同,不同的回调,但是我们却不能从 __explorerFrameCallback 中获得我们的回调函数,必须是该函数的参数有一个是和 FRAMEWIN_CreateEx 的实参是同地址的。也许你可以说应用在调用FRAMEWIN_CreateEx的时候将它的回调函数传过去不就行了,但是这样的话代表每个__explorerFrameCallback都必须重写了,实际上__explorerFrameCallback中有很大一部分是相同的,我们不希望重写这个函数,只是在__explorerFrameCallback中会调用不同的用户提供的回调,如果__explorerFrameCallback的形参有一个引用传递的结构体,那么就可以从这个结构体获得当前应用的回调函数了。
ucgui对于它提供的控件是可以做到创建多个实例,每个实例都可以安装自己的回调,以实现每个实例的共性同时有自己的特色,但是当我们把多个控件组合起来变成我们自己的一个控件的时候却不能实现创建多个实例了,因为我们的回调无法安装。
所以改进的方案是在创建控件和回调函数间有相同地址的参数,这样我们可以通过拓展参数找到自己的回调。
抽象层:initDev(pdev) ==>> func1(pdev) ==>> pdev->callbackfunc(pdev)
应用层:createDev() ==>> pdev->callbackfunc = __func1; ==>> initDev(pdev) __func1(struct dev *pdev)
我们写程序正常的调用过程如上,关键的是第三步参数中pdev,即使没有这个参数按理也可以完成调用用户回调了,但是给了这个参数就是为了拓展的,让用户回调能够获得自己定义的信息,通过结构体拓展。而ucgui的问题正是第三步中没有传入pdev这个参数,使得我们没法拓展。
总结:抽象层调用回调函数时一定要传入一个与入口函数指向同地址的指针参数!(一般为设备结构体指针,一来让回调函数有设备信息,二来方便用户拓展。设计入口函数时一个定要有一个指针参数)