summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.go16
-rw-r--r--cursors.go41
-rw-r--r--icons.go35
-rw-r--r--windows.go104
-rw-r--r--winmain.go59
-rw-r--r--wndclass.go64
-rw-r--r--wndproc.go24
7 files changed, 342 insertions, 1 deletions
diff --git a/common.go b/common.go
index 8b4daa5..f4c769e 100644
--- a/common.go
+++ b/common.go
@@ -7,11 +7,25 @@ import (
var (
user32 = syscall.NewLazyDLL("user32.dll")
+ kernel32 = syscall.NewLazyDLL("kernel32.dll")
)
-type HWND uintptr
+type HANDLE uintptr
+type HWND HANDLE
+type HBRUSH HANDLE
const (
NULL = 0
)
+type ATOM uint16
+
+// TODO pull the thanks for these three from the old wingo source
+type WPARAM uintptr
+type LPARAM uintptr
+type LRESULT uintptr
+
+// microsoft's header files do this
+func MAKEINTRESOURCE(what uint16) uintptr {
+ return uintptr(what)
+}
diff --git a/cursors.go b/cursors.go
new file mode 100644
index 0000000..78fb1f8
--- /dev/null
+++ b/cursors.go
@@ -0,0 +1,41 @@
+// 8 february 2014
+package main
+
+import (
+// "syscall"
+// "unsafe"
+)
+
+// Predefined cursor resource IDs.
+const (
+ IDC_APPSTARTING = 32650
+ IDC_ARROW = 32512
+ IDC_CROSS = 32515
+ IDC_HAND = 32649
+ IDC_HELP = 32651
+ IDC_IBEAM = 32513
+// IDC_ICON = 32641 // [Obsolete for applications marked version 4.0 or later.]
+ IDC_NO = 32648
+// IDC_SIZE = 32640 // [Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.]
+ IDC_SIZEALL = 32646
+ IDC_SIZENESW = 32643
+ IDC_SIZENS = 32645
+ IDC_SIZENWSE = 32642
+ IDC_SIZEWE = 32644
+ IDC_UPARROW = 32516
+ IDC_WAIT = 32514
+)
+
+var (
+ loadCursor = user32.NewProc("LoadCursorW")
+)
+
+func LoadCursor_ResourceID(hInstance HANDLE, lpCursorName uint16) (cursor HANDLE, err error) {
+ r1, _, err := loadCursor.Call(
+ uintptr(hInstance),
+ MAKEINTRESOURCE(lpCursorName))
+ if r1 == 0 { // failure
+ return NULL, err
+ }
+ return HANDLE(r1), nil
+}
diff --git a/icons.go b/icons.go
new file mode 100644
index 0000000..c28f158
--- /dev/null
+++ b/icons.go
@@ -0,0 +1,35 @@
+// 8 february 2014
+package main
+
+import (
+// "syscall"
+// "unsafe"
+)
+
+// Predefined icon resource IDs.
+const (
+ IDI_APPLICATION = 32512
+ IDI_ASTERISK = 32516
+ IDI_ERROR = 32513
+ IDI_EXCLAMATION = 32515
+ IDI_HAND = 32513
+ IDI_INFORMATION = 32516
+ IDI_QUESTION = 32514
+ IDI_SHIELD = 32518
+ IDI_WARNING = 32515
+ IDI_WINLOGO = 32517
+)
+
+var (
+ loadIcon = user32.NewProc("LoadIconW")
+)
+
+func LoadIcon_ResourceID(hInstance HANDLE, lpIconName uint16) (icon HANDLE, err error) {
+ r1, _, err := loadIcon.Call(
+ uintptr(hInstance),
+ MAKEINTRESOURCE(lpIconName))
+ if r1 == 0 { // failure
+ return NULL, err
+ }
+ return HANDLE(r1), nil
+}
diff --git a/windows.go b/windows.go
new file mode 100644
index 0000000..5cfa53d
--- /dev/null
+++ b/windows.go
@@ -0,0 +1,104 @@
+// 8 february 2014
+package main
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// Extended window styles.
+const (
+ WS_EX_ACCEPTFILES = 0x00000010
+ WS_EX_APPWINDOW = 0x00040000
+ WS_EX_CLIENTEDGE = 0x00000200
+// WS_EX_COMPOSITED = 0x02000000 // [Windows 2000:This style is not supported.]
+ WS_EX_CONTEXTHELP = 0x00000400
+ WS_EX_CONTROLPARENT = 0x00010000
+ WS_EX_DLGMODALFRAME = 0x00000001
+ WS_EX_LAYERED = 0x00080000
+ WS_EX_LAYOUTRTL = 0x00400000
+ WS_EX_LEFT = 0x00000000
+ WS_EX_LEFTSCROLLBAR = 0x00004000
+ WS_EX_LTRREADING = 0x00000000
+ WS_EX_MDICHILD = 0x00000040
+ WS_EX_NOACTIVATE = 0x08000000
+ WS_EX_NOINHERITLAYOUT = 0x00100000
+ WS_EX_NOPARENTNOTIFY = 0x00000004
+ WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)
+ WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
+ WS_EX_RIGHT = 0x00001000
+ WS_EX_RIGHTSCROLLBAR = 0x00000000
+ WS_EX_RTLREADING = 0x00002000
+ WS_EX_STATICEDGE = 0x00020000
+ WS_EX_TOOLWINDOW = 0x00000080
+ WS_EX_TOPMOST = 0x00000008
+ WS_EX_TRANSPARENT = 0x00000020
+ WS_EX_WINDOWEDGE = 0x00000100
+)
+
+// TODO CW_USEDEFAULT
+
+// GetSysColor values. These can be cast to HBRUSH (after adding 1) for WNDCLASS as well.
+const (
+ COLOR_3DDKSHADOW = 21
+ COLOR_3DFACE = 15
+ COLOR_3DHIGHLIGHT = 20
+ COLOR_3DHILIGHT = 20
+ COLOR_3DLIGHT = 22
+ COLOR_3DSHADOW = 16
+ COLOR_ACTIVEBORDER = 10
+ COLOR_ACTIVECAPTION = 2
+ COLOR_APPWORKSPACE = 12
+ COLOR_BACKGROUND = 1
+ COLOR_BTNFACE = 15
+ COLOR_BTNHIGHLIGHT = 20
+ COLOR_BTNHILIGHT = 20
+ COLOR_BTNSHADOW = 16
+ COLOR_BTNTEXT = 18
+ COLOR_CAPTIONTEXT = 9
+ COLOR_DESKTOP = 1
+ COLOR_GRADIENTACTIVECAPTION = 27
+ COLOR_GRADIENTINACTIVECAPTION = 28
+ COLOR_GRAYTEXT = 17
+ COLOR_HIGHLIGHT = 13
+ COLOR_HIGHLIGHTTEXT = 14
+ COLOR_HOTLIGHT = 26
+ COLOR_INACTIVEBORDER = 11
+ COLOR_INACTIVECAPTION = 3
+ COLOR_INACTIVECAPTIONTEXT = 19
+ COLOR_INFOBK = 24
+ COLOR_INFOTEXT = 23
+ COLOR_MENU = 4
+// COLOR_MENUHILIGHT = 29 // [Windows 2000:This value is not supported.]
+// COLOR_MENUBAR = 30 // [Windows 2000:This value is not supported.]
+ COLOR_MENUTEXT = 7
+ COLOR_SCROLLBAR = 0
+ COLOR_WINDOW = 5
+ COLOR_WINDOWFRAME = 6
+ COLOR_WINDOWTEXT = 8
+)
+
+var (
+ createWindowEx = user32.NewProc("CreateWindowExW")
+)
+
+// TODO use lpParam
+func CreateWindowEx(dwExStyle uint32, lpClassName string, lpWindowName string, dwStyle uint32, x int, y int, nWidth int, nHeight int, hwndParent HWND, hMenu HANDLE, hInstance HANDLE, lpParam interface{}) (hwnd HWND, err error) {
+ r1, _, err := createWindowEx.Call(
+ uintptr(dwExStyle),
+ uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpClassName))),
+ uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpWindowName))),
+ uintptr(dwStyle),
+ uintptr(x),
+ uintptr(y),
+ uintptr(nWidth),
+ uintptr(nHeight),
+ uintptr(hwndParent),
+ uintptr(hMenu),
+ uintptr(hInstance),
+ uintptr(0))
+ if r1 == 0 { // failure
+ return NULL, err
+ }
+ return HWND(r1), nil
+}
diff --git a/winmain.go b/winmain.go
new file mode 100644
index 0000000..b79ad81
--- /dev/null
+++ b/winmain.go
@@ -0,0 +1,59 @@
+// 8 february 2014
+package main
+
+import (
+// "syscall"
+ "unsafe"
+)
+
+// this provides the hInstance and nCmdShow that are normally passed to WinMain()
+
+const (
+ STARTF_USESHOWWINDOW = 0x00000001
+)
+
+var (
+ getModuleHandle = kernel32.NewProc("GetModuleHandleW")
+ getStartupInfo = kernel32.NewProc("GetStartupInfoW")
+)
+
+// TODO is this trick documented in MSDN?
+func getWinMainhInstance() (hInstance HANDLE, err error) {
+ r1, _, err := getModuleHandle.Call(uintptr(NULL))
+ if r1 == 0 {
+ return NULL, err
+ }
+ return HANDLE(r1), nil
+}
+
+// TODO this is what MinGW-w64's crt (svn revision xxx) does; is it best? is any of this documented anywhere on MSDN?
+// TODO I highly doubt Windows API functions ever not fail, so figure out what to do should an error actually occur
+func getWinMainnCmdShow() (nCmdShow int, err error) {
+ var info struct {
+ cb uint32
+ lpReserved *uint16
+ lpDesktop *uint16
+ lpTitle *uint16
+ dwX uint32
+ dwY uint32
+ dwXSize uint32
+ dwYSzie uint32
+ dwXCountChars uint32
+ dwYCountChars uint32
+ dwFillAttribute uint32
+ dwFlags uint32
+ wShowWindow uint16
+ cbReserved2 uint16
+ lpReserved2 *byte
+ hStdInput HANDLE
+ hStdOutput HANDLE
+ hStdError HANDLE
+ }
+
+ // does not fail according to MSDN
+ getStartupInfo.Call(uintptr(unsafe.Pointer(&info)))
+ if info.dwFlags & STARTF_USESHOWWINDOW != 0 {
+ return int(info.wShowWindow), nil
+ }
+ return SW_SHOWDEFAULT, nil
+}
diff --git a/wndclass.go b/wndclass.go
new file mode 100644
index 0000000..7296369
--- /dev/null
+++ b/wndclass.go
@@ -0,0 +1,64 @@
+// 8 february 2014
+package main
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+type WNDCLASS struct {
+ Style uint32
+ LpfnWndProc WNDPROC
+ CbClsExtra int // TODO exact Go type for C int? MSDN says C int
+ CbWndExtra int // TODO exact Go type for C int? MSDN says C int
+ HInstance HANDLE // actually HINSTANCE
+ HIcon HANDLE // actually HICON
+ HCursor HANDLE // actually HCURSOR
+ HbrBackground HBRUSH
+ LpszMenuName *string // TODO this should probably just be a regular string with "" indicating no name but MSDN doesn't say if that's legal or not
+ LpszClassName string
+}
+
+type _WNDCLASSW struct {
+ style uint32
+ lpfnWndProc WNDPROC
+ cbClsExtra int
+ cbWndExtra int
+ hInstance HANDLE
+ hIcon HANDLE
+ hCursor HANDLE
+ hbrBackground HBRUSH
+ lpszMenuName *uint16
+ lpszClassName *uint16
+}
+
+func (w *WNDCLASS) toNative() *_WNDCLASSW {
+ menuName := (*uint16)(nil)
+ if w.LpszMenuName != nil {
+ menuName = syscall.StringToUTF16Ptr(*w.LpszMenuName)
+ }
+ return &_WNDCLASSW{
+ style: w.Style,
+ lpfnWndProc: w.LpfnWndProc,
+ cbClsExtra: w.CbClsExtra,
+ cbWndExtra: w.CbWndExtra,
+ hInstance: w.HInstance,
+ hIcon: w.HIcon,
+ hCursor: w.HCursor,
+ hbrBackground: w.HbrBackground,
+ lpszMenuName: menuName,
+ lpszClassName: syscall.StringToUTF16Ptr(w.LpszClassName),
+ }
+}
+
+var (
+ registerClass = user32.NewProc("RegisterClassW")
+)
+
+func RegisterClass(lpWndClass *WNDCLASS) (class ATOM, err error) {
+ r1, _, err := registerClass.Call(uintptr(unsafe.Pointer(lpWndClass.toNative())))
+ if r1 == 0 { // failure
+ return 0, err
+ }
+ return ATOM(r1), nil
+}
diff --git a/wndproc.go b/wndproc.go
new file mode 100644
index 0000000..b9c13f2
--- /dev/null
+++ b/wndproc.go
@@ -0,0 +1,24 @@
+// 8 february 2014
+package main
+
+import (
+// "syscall"
+// "unsafe"
+)
+
+// TODO error handling
+type WNDPROC func(hwnd HWND, uMsg uint32, wParam WPARAM, lParam LPARAM) LRESULT
+
+var (
+ defWindowProc = user32.NewProc("DefWindowProcW")
+)
+
+// TODO error handling
+func DefWindowProc(hwnd HWND, uMsg uint32, wParam WPARAM, lParam LPARAM) LRESULT {
+ r1, _, _ := defWindowProc.Call(
+ uintptr(hwnd),
+ uintptr(uMsg),
+ uintptr(wParam),
+ uintptr(lParam))
+ return LRESULT(r1)
+}