時間過得很快,一轉眼,離上次發文章,又好久過去了,最近又忙着公司的項目,很久沒學習Go的windows開發了。趁着雙休日,再來稍微玩下。
上次,我們成功的創建了第一個窗口程序,當時,默認的創建了一個edit類型的窗口,所以,該窗口自己就是一個edit的窗口。今天,不打算這樣做了,得來點正常的了,就是創建一個原始的窗口,啥都不是,就是一個窗口,然后,再在這個窗口里面創建一個子窗口,子窗口有很多種,今天就用Button(按鈕)窗口。開始動手吧~~
一、創建原始窗口
關鍵代碼:
對比上次創建的窗口,我們發現第102行,與上次不太一樣,上次是_TEXT("edit"),這次換成了_TEXT("test"),沒錯。上次的是創建一個edit的窗口,而這次是自定義的原始窗口,你應該已經猜到了這次的窗口我們取名叫test。
既然,有了test,那么test這里只是個字符串名稱呀,所以,我們得先注冊這個窗口對象。如何注冊,我們把注冊過程封裝成了一個方法。
2 func RegisterClass() {
3 var wndProcPtr uintptr = syscall.NewCallback(WndProc)
4 hInst := GetModuleHandle(nil)
5 if hInst == 0 {
6 panic("GetModuleHandle")
7 }
8 hIcon := LoadIcon( 0, (* uint16)(unsafe.Pointer(uintptr(IDI_APPLICATION))))
9 if hIcon == 0 {
10 panic("LoadIcon")
11 }
12 hCursor := LoadCursor( 0, (* uint16)(unsafe.Pointer(uintptr(IDC_ARROW))))
13 if hCursor == 0 {
14 panic("LoadCursor")
15 }
16 var wc WNDCLASSEX
17 wc.CbSize = uint32(unsafe.Sizeof(wc))
18 wc.LpfnWndProc = wndProcPtr
19 wc.HInstance = hInst
20 wc.HIcon = hIcon
21 wc.HCursor = hCursor
22 wc.HbrBackground = COLOR_BTNFACE + 1
23 wc.LpszClassName = syscall.StringToUTF16Ptr("test")
24 if atom := RegisterClassEx(&wc); atom == 0 {
25 panic("RegisterClassEx")
26 }
27 }
第一行,我們把消息處理過程方法,轉換成了一個指針,在 18行賦值給WNDCLASSEX結構體。其余的都是一些初始化操作,例如初始化鼠標,背景,窗體大小等等。還有在第23行是不是看到了test,我們給注冊的這個窗口名字叫test,這樣在之前那個創建窗口的代碼片段中就能成功調用這個test了。其它參數具體參加win32 api。
最后,在main方法中調用這個注冊窗體方法。
二、創建子窗體
創建子窗體其實和創建窗體一個樣,沒什么特別,只不過將它的實例句柄指向父窗口。這里我們要創建一個按鈕,為了方便起見,也稍微封裝下,添加個添加按鈕的方法:
注意看21行,這里是button,明白了吧?和你想的一樣,確實這么簡單,你要創建什么窗體就指定什么。另外注意第28行,parent,是的,指定該窗體的父窗體。該變量通過方法參數傳來,是一個HWND類型的變量。那么,我們該在何時使用該方法添加按鈕呢?繼續往下看。。。。。。
三、添加按鈕
何時添加按鈕,一般的做法就是當父窗體創建的時候就添加,這里就需要用到WM_CREATE消息了,我們在消息處理方法中,監聽該消息,然后如果接受到該消息,就執行addButton方法,添加按鈕到父窗體中。
細心的同學可能會發現,這次的消息處理方法的最后和上次不太一樣,是的,這次最后調用了DefWindowProc函數,該函數調用缺省的窗口過程來為應用程序沒有處理的任何窗口消息提供缺省的處理。該函數確保每一個消息得到處理。
最后運行結果如下:
今天就到這里,下次將為按鈕添加事件處理。。。。。。