讓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);
當然上面的宏沒有針對原始的表單訊息進行設計,有興趣的朋友可以改進改進。希望大家工作的更順利。