您好,登錄后才能下訂單哦!
使用golang語言如何開發windows界面?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
在 awesome-go 節點下有不少開發界面的庫, 大部分是基于web, gtk, qt跨平臺的, 也有基于sciter go綁定的go-sciter, 基于原生包裝的跨平臺的庫ui, 只支持Windows桌面端的walk
個人傾向于后2個, 適合個人的技術棧, 試用了下ui這個庫, demo比較 少就4個, 運行起來有點卡, 而且生成的可執行文件很大. 最重要的是不支持設置控件坐標(沒找到), 而且開放的接口比較少.
下面對比下ui和walk代碼, 就拿button控件來說.
type Button struct {
ControlBase
b *C.uiButton
onClicked func(*Button)}type ControlBase struct {
iface Control
c *C.uiControl}type Control interface {
LibuiControl() uintptr
Destroy()
Handle() uintptr
Visible() bool
Show()
Hide()
Enabled() bool
Enable()
Disable()}
type Button struct {
WidgetBase
checkedChangedPublisher EventPublisher
clickedPublisher EventPublisher
textChangedPublisher EventPublisher
imageChangedPublisher EventPublisher
image Image
persistent bool}type WidgetBase struct {
WindowBase
parent Container
toolTipTextProperty Property
toolTipTextChangedPublisher EventPublisher
graphicsEffects *WidgetGraphicsEffectList
alwaysConsumeSpace bool}type WindowBase struct {
window Window
hWnd win.HWND
origWndProcPtr uintptr
name string
font *Font
contextMenu *Menu
disposables []Disposable
disposingPublisher EventPublisher
dropFilesPublisher DropFilesEventPublisher
keyDownPublisher KeyEventPublisher
keyPressPublisher KeyEventPublisher
keyUpPublisher KeyEventPublisher
mouseDownPublisher MouseEventPublisher
mouseUpPublisher MouseEventPublisher
mouseMovePublisher MouseEventPublisher
mouseWheelPublisher MouseEventPublisher
boundsChangedPublisher EventPublisher
sizeChangedPublisher EventPublisher
maxSize Size
minSize Size
background Brush
cursor Cursor
suspended bool
visible bool
enabled bool
name2Property map[string]Property
enabledProperty Property
enabledChangedPublisher EventPublisher
visibleProperty Property
visibleChangedPublisher EventPublisher
focusedProperty Property
focusedChangedPublisher EventPublisher
calcTextSizeInfoPrev *calcTextSizeInfo}
只列出了屬性, 沒有列出方法. 但也可以看出來ui這個庫開放的接口非常少. 而walk這個庫, 該有的都有了, 接口非常豐富. 實現的控件非常多, 甚至連webview都有, 例子也豐富不少.
需要注意的這個庫里面的控件是基于原生控件的, 而不是自己繪制的
func main() {
var label1, label2 *walk.Label
mv := MainWindow{
Title: "go window",
Size: Size{Width:800, Height:600},
Layout: VBox{MarginsZero: true},
Children: []Widget{
Label{Text: "Hello World", AssignTo: &label1,
Background: SolidColorBrush{walk.RGB(255, 0, 0)},
OnSizeChanged: func() {
label1.SetBounds(walk.Rectangle{100, 100, 100, 100})
}},
Label{Text: "Hello World", AssignTo: &label2,
Background: SolidColorBrush{walk.RGB(0, 255, 0)},
OnSizeChanged: func() {
label2.SetBounds(walk.Rectangle{100, 200, 100, 100})
}},
},
}
mv.Run()}
有點類似flutter中的申明式構建界面, 但是沒有提供代碼初始化的回調^^.
walk內部調用了win, 而win就干了一件事, 把win32 api幾乎所有相關的聲明都導成了go.
比如win32里面的ShowWindow, 是這么導出的:
func init() {
libuser32 = MustLoadLibrary("user32.dll")
....
showWindow = MustGetProcAddress(libuser32, "ShowWindow")}func ShowWindow(hWnd HWND, nCmdShow int32) bool {
ret, _, _ := syscall.Syscall(showWindow, 2,
uintptr(hWnd),
uintptr(nCmdShow),
0)
return ret != 0}
這樣我們用go來調用win32 api, 跟c基本沒差別, 除了語法上的略微差別. 我試用了下, 還是有個把方法沒有導出. 可以按照這個方式自己導出.
既然該有的win32接口都有了, 那么就用go創建一個最簡單的windows窗口吧
func main() {
hInst := GetModuleHandle(nil)
hIcon := LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION))
hCursor := LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW))
var wc WNDCLASSEX
wc.CbSize = uint32(unsafe.Sizeof(wc))
wc.LpfnWndProc = syscall.NewCallback(wndProc)
wc.HInstance = hInst
wc.HIcon = hIcon
wc.HCursor = hCursor
wc.HbrBackground = COLOR_WINDOW + 1
wc.LpszClassName = syscall.StringToUTF16Ptr("go windwow")
wc.Style = CS_HREDRAW | CS_VREDRAW RegisterClassEx(&wc)
hWnd := CreateWindowEx(
0,
syscall.StringToUTF16Ptr("go windwow"),
syscall.StringToUTF16Ptr("go windwow"),
WS_OVERLAPPEDWINDOW,
400,
200,
640,
480,
0,
0,
hInst,
nil)
ShowWindow(hWnd, SW_SHOW)
UpdateWindow(hWnd)
var msg MSG for {
if (GetMessage(&msg, 0, 0, 0) == TRUE) {
TranslateMessage(&msg)
DispatchMessage(&msg)
} else {
break
}
}}func wndProc(hwnd HWND, msg uint32, wParam, lParam uintptr) (result uintptr) {
var ps PAINTSTRUCT switch msg {
case WM_PAINT:
hdc := BeginPaint(hwnd, &ps)
var lb LOGBRUSH
lb.LbStyle = BS_SOLID
lb.LbColor = 0xff000
lb.LbHatch = 0
hPen := HGDIOBJ(ExtCreatePen(PS_SOLID, 2, &lb, 0, nil))
hOldOpen := SelectObject(hdc, hPen)
var pt POINT MoveToEx(hdc, 0, 0, &pt)
LineTo(hdc, 100, 100)
EndPaint(hwnd, &ps)
SelectObject(hdc, hOldOpen)
DeleteObject(hPen)
break
case WM_DESTROY:
PostQuitMessage(0)
break
default:
return DefWindowProc(hwnd, msg, wParam, lParam)
}
return 0}
是不是基本與c的寫法一模一樣, 包括命名. 因此用go(win), 也能像c/c++一樣開發windows界面, 只用稍微切換下語法.
而walk雖然把傳統win32 api和控件封裝成了對象, 把基于消息的事件包裝成了回調, 封裝出了canvs, 也有布局容器BoxLayout, 做做簡單的界面還是很方便的, 但是其本質還是基于windows原有控件, 想自由布局, 定制界面, 性能方面還是很受限.
看完上述內容,你們掌握使用golang語言開發windows界面的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。