溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用golang語言如何開發(fā)windows界面

發(fā)布時間:2020-10-16 17:25:23 來源:億速云 閱讀:1326 作者:Leah 欄目:編程語言

使用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控件來說.

  • ui部分
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()}
  • walk部分
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都有, 例子也豐富不少.

需要注意的這個庫里面的控件是基于原生控件的, 而不是自己繪制的

walk使用

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)^^.

win使用

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è)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(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)容。

AI