時間過得很快,一轉眼,離上次發文章,又好久過去了,最近又忙著公司的項目,很久沒學習Go的windows開發了。趁著雙休日,再來稍微玩下。
上次,我們成功的建立了第一個視窗程序,當時,預設的建立了一個edit類型的視窗,所以,該視窗自己就是一個edit的視窗。今天,不打算這樣做了,得來點正常的了,就是建立一個原始的視窗,啥都不是,就是一個視窗,然後,再在這個視窗裡面建立一個子視窗,子視窗有很多種,今天就用Button(按鈕)視窗。開始動手吧~~
一、建立原始視窗
關鍵代碼:
對比上次建立的視窗,我們發現第102行,與上次不太一樣,上次是_TEXT("edit"),這次換成了_TEXT("test"),沒錯。上次的是建立一個edit的視窗,而這次是自訂的原始視窗,你應該已經猜到了這次的視窗我們取名叫test。
既然,有了test,那麼test這裡只是個字串名稱呀,所以,我們得先註冊這個視窗對象。如何註冊,我們把註冊過程封裝成了一個方法。
1 //Register WndClass
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函數,該函數調用預設的視窗過程來為應用程式沒有處理的任何視窗訊息提供預設的處理。該函數確保每一個訊息得到處理。
最後運行結果如下:
今天就到這裡,下次將為按鈕添加事件處理。。。。。。