win32.go

Simple Windows GUI application written in Go

1

Votes

package main

import (
    "log"
    "syscall"
    "unsafe"
)

var (
    kernel32 = syscall.NewLazyDLL("kernel32.dll")

    pGetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
)

func getModuleHandle() (syscall.Handle, error) {
    ret, _, err := pGetModuleHandleW.Call(uintptr(0))
    if ret == 0 {
        return 0, err
    }
    return syscall.Handle(ret), nil
}

var (
    user32 = syscall.NewLazyDLL("user32.dll")

    pCreateWindowExW  = user32.NewProc("CreateWindowExW")
    pDefWindowProcW   = user32.NewProc("DefWindowProcW")
    pDestroyWindow    = user32.NewProc("DestroyWindow")
    pDispatchMessageW = user32.NewProc("DispatchMessageW")
    pGetMessageW      = user32.NewProc("GetMessageW")
    pLoadCursorW      = user32.NewProc("LoadCursorW")
    pPostQuitMessage  = user32.NewProc("PostQuitMessage")
    pRegisterClassExW = user32.NewProc("RegisterClassExW")
    pTranslateMessage = user32.NewProc("TranslateMessage")
)

const (
    cSW_SHOW        = 5
    cSW_USE_DEFAULT = 0x80000000
)

const (
    cWS_MAXIMIZE_BOX = 0x00010000
    cWS_MINIMIZEBOX  = 0x00020000
    cWS_THICKFRAME   = 0x00040000
    cWS_SYSMENU      = 0x00080000
    cWS_CAPTION      = 0x00C00000
    cWS_VISIBLE      = 0x10000000

    cWS_OVERLAPPEDWINDOW = 0x00CF0000
)

func createWindow(className, windowName string, style uint32, x, y, width, height int32, parent, menu, instance syscall.Handle) (syscall.Handle, error) {
    ret, _, err := pCreateWindowExW.Call(
        uintptr(0),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(className))),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(windowName))),
        uintptr(style),
        uintptr(x),
        uintptr(y),
        uintptr(width),
        uintptr(height),
        uintptr(parent),
        uintptr(menu),
        uintptr(instance),
        uintptr(0),
    )
    if ret == 0 {
        return 0, err
    }
    return syscall.Handle(ret), nil
}

const (
    cWM_DESTROY = 0x0002
    cWM_CLOSE   = 0x0010
)

func defWindowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
    ret, _, _ := pDefWindowProcW.Call(
        uintptr(hwnd),
        uintptr(msg),
        uintptr(wparam),
        uintptr(lparam),
    )
    return uintptr(ret)
}

func destroyWindow(hwnd syscall.Handle) error {
    ret, _, err := pDestroyWindow.Call(uintptr(hwnd))
    if ret == 0 {
        return err
    }
    return nil
}

type tPOINT struct {
    x, y int32
}

type tMSG struct {
    hwnd    syscall.Handle
    message uint32
    wParam  uintptr
    lParam  uintptr
    time    uint32
    pt      tPOINT
}

func dispatchMessage(msg *tMSG) {
    pDispatchMessageW.Call(uintptr(unsafe.Pointer(msg)))
}

func getMessage(msg *tMSG, hwnd syscall.Handle, msgFilterMin, msgFilterMax uint32) (bool, error) {
    ret, _, err := pGetMessageW.Call(
        uintptr(unsafe.Pointer(msg)),
        uintptr(hwnd),
        uintptr(msgFilterMin),
        uintptr(msgFilterMax),
    )
    if int32(ret) == -1 {
        return false, err
    }
    return int32(ret) != 0, nil
}

const (
    cIDC_ARROW = 32512
)

func loadCursorResource(cursorName uint32) (syscall.Handle, error) {
    ret, _, err := pLoadCursorW.Call(
        uintptr(0),
        uintptr(uint16(cursorName)),
    )
    if ret == 0 {
        return 0, err
    }
    return syscall.Handle(ret), nil
}

func postQuitMessage(exitCode int32) {
    pPostQuitMessage.Call(uintptr(exitCode))
}

const (
    cCOLOR_WINDOW = 5
)

type tWNDCLASSEXW struct {
    size       uint32
    style      uint32
    wndProc    uintptr
    clsExtra   int32
    wndExtra   int32
    instance   syscall.Handle
    icon       syscall.Handle
    cursor     syscall.Handle
    background syscall.Handle
    menuName   *uint16
    className  *uint16
    iconSm     syscall.Handle
}

func registerClassEx(wcx *tWNDCLASSEXW) (uint16, error) {
    ret, _, err := pRegisterClassExW.Call(
        uintptr(unsafe.Pointer(wcx)),
    )
    if ret == 0 {
        return 0, err
    }
    return uint16(ret), nil
}

func translateMessage(msg *tMSG) {
    pTranslateMessage.Call(uintptr(unsafe.Pointer(msg)))
}

func main() {
    className := "testClass"

    instance, err := getModuleHandle()
    if err != nil {
        log.Println(err)
        return
    }

    cursor, err := loadCursorResource(cIDC_ARROW)
    if err != nil {
        log.Println(err)
        return
    }

    fn := func(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
        switch msg {
        case cWM_CLOSE:
            destroyWindow(hwnd)
        case cWM_DESTROY:
            postQuitMessage(0)
        default:
            ret := defWindowProc(hwnd, msg, wparam, lparam)
            return ret
        }
        return 0
    }

    wcx := tWNDCLASSEXW{
        wndProc:    syscall.NewCallback(fn),
        instance:   instance,
        cursor:     cursor,
        background: cCOLOR_WINDOW + 1,
        className:  syscall.StringToUTF16Ptr(className),
    }
    wcx.size = uint32(unsafe.Sizeof(wcx))

    if _, err = registerClassEx(&wcx); err != nil {
        log.Println(err)
        return
    }

    _, err = createWindow(
        className,
        "Test Window",
        cWS_VISIBLE|cWS_OVERLAPPEDWINDOW,
        cSW_USE_DEFAULT,
        cSW_USE_DEFAULT,
        cSW_USE_DEFAULT,
        cSW_USE_DEFAULT,
        0,
        0,
        instance,
    )
    if err != nil {
        log.Println(err)
        return
    }

    for {
        msg := tMSG{}
        gotMessage, err := getMessage(&msg, 0, 0, 0)
        if err != nil {
            log.Println(err)
            return
        }

        if gotMessage {
            translateMessage(&msg)
            dispatchMessage(&msg)
        } else {
            break
        }
    }
}

Vote Here

You must earn at least 1 vote on your snippets to be allowed to vote

Terms Of Use

Privacy Policy

Featured snippets are MIT license

Gears & Masters

Advertise

DevOpsnipp.com © 2020

medium.png