File: main_windows.go

package info (click to toggle)
golang-github-ebitengine-purego 0.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,452 kB
  • sloc: asm: 31,862; ansic: 1,001; cpp: 8; makefile: 3
file content (154 lines) | stat: -rw-r--r-- 3,903 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors

package main

import (
	"runtime"
	"syscall"
	"unsafe"

	"github.com/ebitengine/purego"
)

const (
	WS_OVERLAPPEDWINDOW = 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000 | 0x00020000 | 0x00010000
	CW_USEDEFAULT       = ^0x7fffffff
	SW_SHOW             = 5
	WM_DESTROY          = 2
)

type (
	ATOM      uint16
	HANDLE    uintptr
	HINSTANCE HANDLE
	HICON     HANDLE
	HCURSOR   HANDLE
	HBRUSH    HANDLE
	HWND      HANDLE
	HMENU     HANDLE
)

type WNDCLASSEX struct {
	Size       uint32
	Style      uint32
	WndProc    uintptr
	ClsExtra   int32
	WndExtra   int32
	Instance   HINSTANCE
	Icon       HICON
	Cursor     HCURSOR
	Background HBRUSH
	MenuName   *uint16
	ClassName  *uint16
	IconSm     HICON
}

type RECT struct {
	Left, Top, Right, Bottom int32
}

type POINT struct {
	X, Y int32
}

type MSG struct {
	Hwnd    HWND
	Message uint32
	WParam  uintptr
	LParam  uintptr
	Time    uint32
	Pt      POINT
}

var (
	GetModuleHandle func(modulename *uint16) HINSTANCE
	RegisterClassEx func(w *WNDCLASSEX) ATOM
	CreateWindowEx  func(exStyle uint, className, windowName *uint16,
		style uint, x, y, width, height int, parent HWND, menu HMENU,
		instance HINSTANCE, param unsafe.Pointer) HWND
	AdjustWindowRect func(rect *RECT, style uint, menu bool) bool
	ShowWindow       func(hwnd HWND, cmdshow int) bool
	GetMessage       func(msg *MSG, hwnd HWND, msgFilterMin, msgFilterMax uint32) int
	TranslateMessage func(msg *MSG) bool
	DispatchMessage  func(msg *MSG) uintptr
	DefWindowProc    func(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr
	PostQuitMessage  func(exitCode int)
)

func init() {
	// Use [syscall.NewLazyDLL] here to avoid external dependencies (#270).
	// For actual use cases, [golang.org/x/sys/windows.NewLazySystemDLL] is recommended.
	kernel32 := syscall.NewLazyDLL("kernel32.dll").Handle()
	purego.RegisterLibFunc(&GetModuleHandle, kernel32, "GetModuleHandleW")

	// Use [syscall.NewLazyDLL] here to avoid external dependencies (#270).
	// For actual use cases, [golang.org/x/sys/windows.NewLazySystemDLL] is recommended.
	user32 := syscall.NewLazyDLL("user32.dll").Handle()
	purego.RegisterLibFunc(&RegisterClassEx, user32, "RegisterClassExW")
	purego.RegisterLibFunc(&CreateWindowEx, user32, "CreateWindowExW")
	purego.RegisterLibFunc(&AdjustWindowRect, user32, "AdjustWindowRect")
	purego.RegisterLibFunc(&ShowWindow, user32, "ShowWindow")
	purego.RegisterLibFunc(&GetMessage, user32, "GetMessageW")
	purego.RegisterLibFunc(&TranslateMessage, user32, "TranslateMessage")
	purego.RegisterLibFunc(&DispatchMessage, user32, "DispatchMessageW")
	purego.RegisterLibFunc(&DefWindowProc, user32, "DefWindowProcW")
	purego.RegisterLibFunc(&PostQuitMessage, user32, "PostQuitMessage")

	runtime.LockOSThread()
}

func main() {
	className, err := syscall.UTF16PtrFromString("Sample Window Class")
	if err != nil {
		panic(err)
	}
	inst := GetModuleHandle(className)

	wc := WNDCLASSEX{
		Size:      uint32(unsafe.Sizeof(WNDCLASSEX{})),
		WndProc:   syscall.NewCallback(wndProc),
		Instance:  inst,
		ClassName: className,
	}

	RegisterClassEx(&wc)

	wr := RECT{
		Left:   0,
		Top:    0,
		Right:  320,
		Bottom: 240,
	}
	title, err := syscall.UTF16PtrFromString("My Title")
	if err != nil {
		panic(err)
	}
	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, false)
	hwnd := CreateWindowEx(
		0, className,
		title,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, int(wr.Right-wr.Left), int(wr.Bottom-wr.Top),
		0, 0, inst, nil,
	)
	if hwnd == 0 {
		panic(syscall.GetLastError())
	}

	ShowWindow(hwnd, SW_SHOW)

	var msg MSG
	for GetMessage(&msg, 0, 0, 0) != 0 {
		TranslateMessage(&msg)
		DispatchMessage(&msg)
	}
}

func wndProc(hwnd HWND, msg uint32, wparam, lparam uintptr) uintptr {
	switch msg {
	case WM_DESTROY:
		PostQuitMessage(0)
	}
	return DefWindowProc(hwnd, msg, wparam, lparam)
}