让minigui的代码更像MFC

         所有windows下的程序员应该多有使用过MFC的经历,虽然MFC可能不是最好GUI库,但是不可否认microsoft在MFC上作的工作使得MFC的代码更易于维护和阅读,特别是在大型项目下,你拥有大量的界面控件代码的时候。在目前的嵌入式应用开发领域拥有众多的GUI库,minigui作为嵌入式领域中国产的GUI库得到了广泛的应用。目前minigui有两大缺点需要解决的是一、如何让界面开发更加可视化;二、当在开发一个大型工程时如何时代码结构更易于维护。虽然,飞漫公司还没有在这方面提供更好的支持,那么身为程序员的我们就应该来尝试解决这样的问题,呵呵!方便他人也就等于方便自己嘛!

        首先我想说的是控件数组的排布问题,比较主流的两种方式是一、以窗体对应文件方式来分控件数组,即把当前窗体的所有控件数组代码放置到窗体文件中;二、将所有的控件放到一个.c文件中,我个人比较提倡使用后者的方式,以这种方式来处理控件便于在程序在不同的显示屏下的移植和修改工作,而且更容易查找对应的控件数组。我一般将所有的控件数组放置到resources.c文件中,把控件的id定义放置到resources.h文件中,只要加入适当的注释就可以很容易的定位和修改控件代码了。

       其次是控件编程中的代码风格,首先说注释,由于minigui是用c写的所以我们一般也使用c来进行开发,所以我比较提倡用c风格的注释/* */。其实注释并没有太大的问题,只要风格统一就可以。注释也可以使我们更好的理解别人的思想,而/* */来处理块注释是比较容易得的。写过minigui程序的朋友们可能清楚,在minigui的代码中所有的事件和行为都是通过消息来处理,而处理消息就用到了大量的case工作这样当一个项目大到一定的时候你会发现,你根本就不想多看一眼那个由四十个控件组成的窗体文件的代码,大量的case会让你很头疼,如果下一个程序员来修改你的代码的时候他也会先发一顿牢骚的。那么,为了使这样的代码跟容易阅读我们还需要做一些额外的工作。我在工作中通常使用宏的方式来解决这样得到问题,比较下面的两段代码你会发现第二段代码更想MFC:

1.
static int DialogProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case MSG_INITDIALOG:
            /* 初始化处理代码 */
            break;
        case MSG_COMMAND:
            switch(wParam)
            {
                case IDC_BUTTON_BTN:
                /* 按钮处理代码 */
                break;
            }
            break;
    }
    return DefaultDialogProc(hWnd, message, wParam, lParam);
}


2.
static void Dlg_Initialize(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
    /* 初始化处理代码 */
}


 static void Btn_Clicked(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
 {
    /* 按钮处理代码 */
 }

static int DialogProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
      SETUP_DIALOG_PROC()
           RETURN_MESSAGE_EVENT(MSG_INITDIALOG, Dlg_Initialize, 1)
           SETUP_CONTROL_MAP
                  MAP_CONTROL_TO(IDC_BUTTON_BTN, Btn_Clicked)
           END_CONTROL_MAP
      END_DIALOG_PROC()
 }

这段代码看起来很怪,不过其实是上一段代码的改进而已,我使用了下面的宏
#define SETUP_CONTROL_PROC(ctrl_id) case (ctrl_id):\
                                                                                          switch (message) {
#define END_CONTROL_PROC(default_proc)  default: \
                                                                                       return (*default_proc)(hWnd, message, wParam, lParam); \
                                                                             } \
                                                                              break;
#define DO_MESSAGE_EVENT(msg_type, do_func) case (msg_type): \
                                                                                            (*do_func)(hWnd,message, wParam, lParam); \
                                                                                     break;
#define RETURN_MESSAGE_EVENT(msg_type, do_func, reval) case (msg_type): \
                                                                                                               (*do_func)(hWnd,message, wParam, lParam); \
                                                                                                       return (reval);
#define SETUP_DIALOG_PROC()  switch (message) {
#define END_DIALOG_PROC()    default: \
                                                                 return DefaultDialogProc(hWnd, message, wParam, lParam); \
                                                         }
#define SETUP_CONTROL_MAP   case MSG_COMMAND: \
                                 switch (wParam) {
#define END_CONTROL_MAP          default: \
                                                                       break; \
                                                            } \
                                                            break;
#define MAP_CONTROL_TO(ctrl_id, event_func) DO_MESSAGE_EVENT((ctrl_id), (event_func))
使用这种小技巧就可以使得minigui代码在变的庞大的时候,也比较容易阅读,使用上面的宏需要注意的是如果对话框消息需要默认处理时,需要在对应的函数尾部加上DefaultDialogProc(hWnd, message, wParam, lParam);
        当然上面的宏没有针对原始的窗体消息进行设计,有兴趣的朋友可以改进改进。希望大家工作的更顺利。

posted @ 2006-10-22 23:07  moonz-wu  阅读(917)  评论(0编辑  收藏  举报