您好,登錄后才能下訂單哦!
使用golang語言如何開發(fā)windows界面?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
在 awesome-go 節(jié)點下有不少開發(fā)界面的庫, 大部分是基于web, gtk, qt跨平臺的, 也有基于sciter go綁定的go-sciter, 基于原生包裝的跨平臺的庫ui, 只支持Windows桌面端的walk
個人傾向于后2個, 適合個人的技術(shù)棧, 試用了下ui這個庫, demo比較 少就4個, 運行起來有點卡, 而且生成的可執(zhí)行文件很大. 最重要的是不支持設(shè)置控件坐標(biāo)(沒找到), 而且開放的接口比較少.
下面對比下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這個庫, 該有的都有了, 接口非常豐富. 實現(xiàn)的控件非常多, 甚至連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中的申明式構(gòu)建界面, 但是沒有提供代碼初始化的回調(diào)^^.
walk內(nèi)部調(diào)用了win, 而win就干了一件事, 把win32 api幾乎所有相關(guān)的聲明都導(dǎo)成了go.
比如win32里面的ShowWindow, 是這么導(dǎo)出的:
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來調(diào)用win32 api, 跟c基本沒差別, 除了語法上的略微差別. 我試用了下, 還是有個把方法沒有導(dǎo)出. 可以按照這個方式自己導(dǎo)出.
既然該有的win32接口都有了, 那么就用go創(chuàng)建一個最簡單的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++一樣開發(fā)windows界面, 只用稍微切換下語法.
而walk雖然把傳統(tǒng)win32 api和控件封裝成了對象, 把基于消息的事件包裝成了回調(diào), 封裝出了canvs, 也有布局容器BoxLayout, 做做簡單的界面還是很方便的, 但是其本質(zhì)還是基于windows原有控件, 想自由布局, 定制界面, 性能方面還是很受限.
看完上述內(nèi)容,你們掌握使用golang語言開發(fā)windows界面的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。