目前來說,用Go寫Windows應用還沒有非常成熟的設計器,習慣了C#那種強大的IDE,再過來看會覺得一朝回到解放前。而且gform現在的設計思路需要使用者對win32 api非常熟悉,否則用起來會非常難受。 這也是我一直在想改善方案的地方,畢竟一個類庫要以好用為目標,只是我充滿了OO思想的頭腦還沒有完全適應Go的設計方式,很多以前信手拈來的思路用到Go上就會出現問題,或者就算套上去了也會覺得與語言格格不入。最明顯就是在努力了兩周之後,我突然發現竟然在類比類的繼承,天!當時就感覺真的需要停下來了,否則按照現在的慣性做出來的東西肯定一塌糊塗。
關於gform這個架構我的思考還在繼續進行,在弄清楚到底怎樣才是Go的設計模式之後,我相信會對它進行一次大的重構。
好了,現在進入正題,用表單設計器做介面。原理是還是MFC的老方法,在資源檔中做好對話方塊設計,然後在運行時attach上去。
開啟ResEdit,添加一個對話方塊,然後在上面放好各種控制項。中是一個我做的小工具的實際例子。
其中,為每個控制項都設定一個有意義的ID。比如,中“過濾”右邊的文字框,ID為“IDC_FILTER”。
儲存之後會發現,ResEdit自動產生了一個與資源檔同名的標頭檔,如下所示。
開啟這個標頭檔,發現裡面其實只是簡單的定義了控制項ID的值,如下所示。
我們現在建立一個go檔案,叫做app.go,把標頭檔中的常量定義全都複製進來,變成Go的常量定義,比如:
const (
IDD_DIALOG1 = 104
IDC_CLOSE= 1006
)
可以看到,對話方塊的ID是IDD_DIALOG1,好,我們現在可以用gform.NewDialogFromResId來把這個對話方塊讀取出來。
func main() {
gform.Init()
mainform := gform.NewDialogFromResId(nil, IDD_DIALOG1)
mainform.Show()
gform.RunMainLoop()
}
運行一下看看,怎麼樣?看到表單了吧。現在來試試相應按鈕的事件,使用gform.AttachPushButton,之後相應OnLBUp(On Left Button Up即當滑鼠左鍵彈起時)。
btnClose = gform.AttachPushButton(mainform, IDC_CLOSE)
btnClose.OnLBUp().Attach(btnClose_OnLBUp)
func btnClose_OnLBUp(arg *gform.EventArg) {
//事件響應代碼寫在這裡
}
gform中的事件響應函數很想C#中的委託,每個事件都可以Attach多個事件處理函數,事件激發是會單線程依次調用。而事件響應函數只有一個參數,讓我們來看看gform.EventArg的定義。
type EventArg struct {
sender Controller
data interface{}
}
sender顧名思義,代表激發事件的控制項。data裡面附帶的就是事件資訊,比如,滑鼠按鍵事件,data就是MouseEventData類型,定義如下。
type MouseEventData struct {
X, Y int
Button int
Wheel int
}
其他的事件都有自己的事件數目據,這裡就不一一例舉了。Go的interface{}挺好用的,加上它的靜態類型檢查,很安全、高效。
這樣就完成了,目前gform支援Label、Button、Combobox、Edit、ListView、ProgressBar(因為我寫的小工具僅用到了這幾個控制項)。之後支援的控制項會慢慢變多。
下一篇會講到如何自訂控制項,先秀一下近期正在做的小軟體的介面,還遠遠沒有完工,但我自己挺滿意的。呵呵