2014-02-08 22:51:11 -06:00
|
|
|
// 8 february 2014
|
2014-03-12 20:55:45 -05:00
|
|
|
|
2014-02-19 10:41:10 -06:00
|
|
|
package ui
|
2014-02-08 22:51:11 -06:00
|
|
|
|
|
|
|
import (
|
2014-02-11 15:23:38 -06:00
|
|
|
"fmt"
|
2014-02-08 22:51:11 -06:00
|
|
|
// "syscall"
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2014-02-11 18:09:10 -06:00
|
|
|
hInstance _HANDLE
|
2014-02-11 15:23:38 -06:00
|
|
|
nCmdShow int
|
2014-03-24 16:01:33 -05:00
|
|
|
gdiplusToken uintptr
|
2014-02-08 22:51:11 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// TODO is this trick documented in MSDN?
|
2014-02-11 15:23:38 -06:00
|
|
|
func getWinMainhInstance() (err error) {
|
2014-02-11 18:09:10 -06:00
|
|
|
r1, _, err := kernel32.NewProc("GetModuleHandleW").Call(uintptr(_NULL))
|
2014-02-11 15:23:38 -06:00
|
|
|
if r1 == 0 { // failure
|
|
|
|
return err
|
2014-02-08 22:51:11 -06:00
|
|
|
}
|
2014-02-11 18:09:10 -06:00
|
|
|
hInstance = _HANDLE(r1)
|
2014-02-11 15:23:38 -06:00
|
|
|
return nil
|
2014-02-08 22:51:11 -06:00
|
|
|
}
|
|
|
|
|
2014-02-11 18:09:10 -06:00
|
|
|
// TODO this is what MinGW-w64's crt (svn revision TODO) does; is it best? is any of this documented anywhere on MSDN?
|
2014-02-15 13:11:54 -06:00
|
|
|
func getWinMainnCmdShow() {
|
2014-02-08 22:51:11 -06:00
|
|
|
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
|
2014-02-11 18:09:10 -06:00
|
|
|
hStdInput _HANDLE
|
|
|
|
hStdOutput _HANDLE
|
|
|
|
hStdError _HANDLE
|
2014-02-08 22:51:11 -06:00
|
|
|
}
|
2014-02-11 15:23:38 -06:00
|
|
|
const _STARTF_USESHOWWINDOW = 0x00000001
|
2014-02-08 22:51:11 -06:00
|
|
|
|
|
|
|
// does not fail according to MSDN
|
2014-02-11 15:23:38 -06:00
|
|
|
kernel32.NewProc("GetStartupInfoW").Call(uintptr(unsafe.Pointer(&info)))
|
|
|
|
if info.dwFlags & _STARTF_USESHOWWINDOW != 0 {
|
|
|
|
nCmdShow = int(info.wShowWindow)
|
2014-02-15 13:11:54 -06:00
|
|
|
} else {
|
|
|
|
nCmdShow = _SW_SHOWDEFAULT
|
2014-02-11 15:23:38 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-24 16:01:33 -05:00
|
|
|
func initGDIPlus() (err error) {
|
|
|
|
var gdiplusInit struct {
|
|
|
|
GdiplusVersion uint32
|
|
|
|
DebugEventCallback uintptr
|
|
|
|
SuppressBackgroundThread int32 // originally BOOL
|
|
|
|
SuppressExternalCodecs int32 // originally BOOL
|
|
|
|
}
|
|
|
|
|
|
|
|
gdiplusInit.GdiplusVersion = 1 // required
|
|
|
|
// TODO suppress external codecs?
|
|
|
|
r1, _, err := gdiplus.NewProc("GdiplusStartup").Call(
|
|
|
|
uintptr(unsafe.Pointer(&gdiplusToken)),
|
|
|
|
uintptr(unsafe.Pointer(&gdiplusInit)),
|
|
|
|
uintptr(0)) // we use the GDI+ thread so no need for output info
|
|
|
|
if r1 != 0 { // failure
|
|
|
|
return fmt.Errorf("error initializing GDI+ (GDI+ error code %d; windows last error %v)", r1, err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-02-11 15:23:38 -06:00
|
|
|
func doWindowsInit() (err error) {
|
|
|
|
err = getWinMainhInstance()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error getting WinMain hInstance: %v", err)
|
|
|
|
}
|
2014-02-15 13:11:54 -06:00
|
|
|
getWinMainnCmdShow()
|
2014-02-12 19:51:07 -06:00
|
|
|
err = initWndClassInfo()
|
2014-02-11 16:38:38 -06:00
|
|
|
if err != nil {
|
2014-02-12 19:51:07 -06:00
|
|
|
return fmt.Errorf("error initializing standard window class auxiliary info: %v", err)
|
2014-02-11 16:38:38 -06:00
|
|
|
}
|
2014-02-24 12:22:59 -06:00
|
|
|
err = getStandardWindowFonts()
|
2014-02-24 10:55:38 -06:00
|
|
|
if err != nil {
|
2014-02-24 12:22:59 -06:00
|
|
|
return fmt.Errorf("error getting standard window fonts: %v", err)
|
2014-02-24 10:55:38 -06:00
|
|
|
}
|
2014-02-25 07:28:10 -06:00
|
|
|
err = initCommonControls()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error initializing Common Controls (comctl32.dll): %v", err)
|
|
|
|
}
|
2014-03-24 16:01:33 -05:00
|
|
|
err = initGDIPlus()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error initializing GDI+ (gdiplus.dll): %v", err)
|
|
|
|
}
|
2014-02-11 15:23:38 -06:00
|
|
|
// TODO others
|
|
|
|
return nil // all ready to go
|
2014-02-08 22:51:11 -06:00
|
|
|
}
|
2014-03-24 16:01:33 -05:00
|
|
|
|
|
|
|
func doWindowsQuitStuff() {
|
|
|
|
gdiplus.NewProc("GdiplusShutdown").Call(gdiplusToken) // returns void according to MSDN
|
|
|
|
}
|