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



浙公網(wǎng)安備 33010602011771號