From 42229820d2a47594f68d92356f8e8a86133a29f5 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 11 Feb 2014 13:06:12 -0500 Subject: Added _windows.go extensions to all the files in preparation for the library writing. --- buttons.go | 106 -------------- buttons_windows.go | 106 ++++++++++++++ comboboxes.go | 84 ----------- comboboxes_windows.go | 84 +++++++++++ common.go | 73 ---------- common_windows.go | 73 ++++++++++ cursors.go | 41 ------ cursors_windows.go | 41 ++++++ edits.go | 94 ------------- edits_windows.go | 94 +++++++++++++ icons.go | 35 ----- icons_windows.go | 35 +++++ listboxes.go | 91 ------------ listboxes_windows.go | 91 ++++++++++++ main.go | 324 ------------------------------------------ main_windows.go | 324 ++++++++++++++++++++++++++++++++++++++++++ menus.go | 12 -- menus_windows.go | 12 ++ messagebox.go | 85 ----------- messagebox_windows.go | 85 +++++++++++ messages.go | 72 ---------- messages_windows.go | 72 ++++++++++ painting.go | 20 --- painting_windows.go | 20 +++ rectangles.go | 21 --- rectangles_windows.go | 21 +++ statics.go | 57 -------- statics_windows.go | 57 ++++++++ stdfont.go | 74 ---------- stdfont_windows.go | 74 ++++++++++ windows.go | 382 -------------------------------------------------- windows_windows.go | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++ winmain.go | 59 -------- winmain_windows.go | 59 ++++++++ wndclass.go | 64 --------- wndclass_windows.go | 64 +++++++++ wndproc.go | 24 ---- wndproc_windows.go | 24 ++++ 38 files changed, 1718 insertions(+), 1718 deletions(-) delete mode 100644 buttons.go create mode 100644 buttons_windows.go delete mode 100644 comboboxes.go create mode 100644 comboboxes_windows.go delete mode 100644 common.go create mode 100644 common_windows.go delete mode 100644 cursors.go create mode 100644 cursors_windows.go delete mode 100644 edits.go create mode 100644 edits_windows.go delete mode 100644 icons.go create mode 100644 icons_windows.go delete mode 100644 listboxes.go create mode 100644 listboxes_windows.go delete mode 100644 main.go create mode 100644 main_windows.go delete mode 100644 menus.go create mode 100644 menus_windows.go delete mode 100644 messagebox.go create mode 100644 messagebox_windows.go delete mode 100644 messages.go create mode 100644 messages_windows.go delete mode 100644 painting.go create mode 100644 painting_windows.go delete mode 100644 rectangles.go create mode 100644 rectangles_windows.go delete mode 100644 statics.go create mode 100644 statics_windows.go delete mode 100644 stdfont.go create mode 100644 stdfont_windows.go delete mode 100644 windows.go create mode 100644 windows_windows.go delete mode 100644 winmain.go create mode 100644 winmain_windows.go delete mode 100644 wndclass.go create mode 100644 wndclass_windows.go delete mode 100644 wndproc.go create mode 100644 wndproc_windows.go diff --git a/buttons.go b/buttons.go deleted file mode 100644 index b6a4f03..0000000 --- a/buttons.go +++ /dev/null @@ -1,106 +0,0 @@ -// 9 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Button styles. -const ( - // from winuser.h - BS_PUSHBUTTON = 0x00000000 - BS_DEFPUSHBUTTON = 0x00000001 - BS_CHECKBOX = 0x00000002 - BS_AUTOCHECKBOX = 0x00000003 - BS_RADIOBUTTON = 0x00000004 - BS_3STATE = 0x00000005 - BS_AUTO3STATE = 0x00000006 - BS_GROUPBOX = 0x00000007 - BS_USERBUTTON = 0x00000008 - BS_AUTORADIOBUTTON = 0x00000009 - BS_PUSHBOX = 0x0000000A - BS_OWNERDRAW = 0x0000000B - BS_TYPEMASK = 0x0000000F - BS_LEFTTEXT = 0x00000020 - BS_TEXT = 0x00000000 - BS_ICON = 0x00000040 - BS_BITMAP = 0x00000080 - BS_LEFT = 0x00000100 - BS_RIGHT = 0x00000200 - BS_CENTER = 0x00000300 - BS_TOP = 0x00000400 - BS_BOTTOM = 0x00000800 - BS_VCENTER = 0x00000C00 - BS_PUSHLIKE = 0x00001000 - BS_MULTILINE = 0x00002000 - BS_NOTIFY = 0x00004000 - BS_FLAT = 0x00008000 - BS_RIGHTBUTTON = BS_LEFTTEXT - // from commctrl.h -// BS_SPLITBUTTON = 0x0000000C // Windows Vista and newer and(/or?) comctl6 only -// BS_DEFSPLITBUTTON = 0x0000000D // Windows Vista and newer and(/or?) comctl6 only -// BS_COMMANDLINK = 0x0000000E // Windows Vista and newer and(/or?) comctl6 only -// BS_DEFCOMMANDLINK = 0x0000000F // Windows Vista and newer and(/or?) comctl6 only -) - -// Button WM_COMMAND notifications. -const ( - // from winuser.h - BN_CLICKED = 0 - BN_PAINT = 1 - BN_HILITE = 2 - BN_UNHILITE = 3 - BN_DISABLE = 4 - BN_DOUBLECLICKED = 5 - BN_PUSHED = BN_HILITE - BN_UNPUSHED = BN_UNHILITE - BN_DBLCLK = BN_DOUBLECLICKED - BN_SETFOCUS = 6 - BN_KILLFOCUS = 7 -) - -// Button check states. -const ( - // from winuser.h - BST_UNCHECKED = 0x0000 - BST_CHECKED = 0x0001 - BST_INDETERMINATE = 0x0002 -) - -var ( - checkDlgButton = user32.NewProc("CheckDlgButton") - checkRadioButton = user32.NewProc("CheckRadioButton") - isDlgButtonChecked = user32.NewProc("IsDlgButtonChecked") -) - -func CheckDlgButton(hDlg HWND, nIDButton int, uCheck uint32) (err error) { - r1, _, err := checkDlgButton.Call( - uintptr(hDlg), - uintptr(nIDButton), - uintptr(uCheck)) - if r1 == 0 { // failure - return err - } - return nil -} - -func CheckRadioButton(hDlg HWND, nIDFirstButton int, nIDLastButton int, nIDCheckButton int) (err error) { - r1, _, err := checkRadioButton.Call( - uintptr(hDlg), - uintptr(nIDFirstButton), - uintptr(nIDLastButton), - uintptr(nIDCheckButton)) - if r1 == 0 { // failure - return err - } - return nil -} - -// TODO handle errors -func IsDlgButtonChecked(hDlg HWND, nIDButton int) (state uint32, err error) { - r1, _, _ := isDlgButtonChecked.Call( - uintptr(hDlg), - uintptr(nIDButton)) - return uint32(r1), nil -} diff --git a/buttons_windows.go b/buttons_windows.go new file mode 100644 index 0000000..b6a4f03 --- /dev/null +++ b/buttons_windows.go @@ -0,0 +1,106 @@ +// 9 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Button styles. +const ( + // from winuser.h + BS_PUSHBUTTON = 0x00000000 + BS_DEFPUSHBUTTON = 0x00000001 + BS_CHECKBOX = 0x00000002 + BS_AUTOCHECKBOX = 0x00000003 + BS_RADIOBUTTON = 0x00000004 + BS_3STATE = 0x00000005 + BS_AUTO3STATE = 0x00000006 + BS_GROUPBOX = 0x00000007 + BS_USERBUTTON = 0x00000008 + BS_AUTORADIOBUTTON = 0x00000009 + BS_PUSHBOX = 0x0000000A + BS_OWNERDRAW = 0x0000000B + BS_TYPEMASK = 0x0000000F + BS_LEFTTEXT = 0x00000020 + BS_TEXT = 0x00000000 + BS_ICON = 0x00000040 + BS_BITMAP = 0x00000080 + BS_LEFT = 0x00000100 + BS_RIGHT = 0x00000200 + BS_CENTER = 0x00000300 + BS_TOP = 0x00000400 + BS_BOTTOM = 0x00000800 + BS_VCENTER = 0x00000C00 + BS_PUSHLIKE = 0x00001000 + BS_MULTILINE = 0x00002000 + BS_NOTIFY = 0x00004000 + BS_FLAT = 0x00008000 + BS_RIGHTBUTTON = BS_LEFTTEXT + // from commctrl.h +// BS_SPLITBUTTON = 0x0000000C // Windows Vista and newer and(/or?) comctl6 only +// BS_DEFSPLITBUTTON = 0x0000000D // Windows Vista and newer and(/or?) comctl6 only +// BS_COMMANDLINK = 0x0000000E // Windows Vista and newer and(/or?) comctl6 only +// BS_DEFCOMMANDLINK = 0x0000000F // Windows Vista and newer and(/or?) comctl6 only +) + +// Button WM_COMMAND notifications. +const ( + // from winuser.h + BN_CLICKED = 0 + BN_PAINT = 1 + BN_HILITE = 2 + BN_UNHILITE = 3 + BN_DISABLE = 4 + BN_DOUBLECLICKED = 5 + BN_PUSHED = BN_HILITE + BN_UNPUSHED = BN_UNHILITE + BN_DBLCLK = BN_DOUBLECLICKED + BN_SETFOCUS = 6 + BN_KILLFOCUS = 7 +) + +// Button check states. +const ( + // from winuser.h + BST_UNCHECKED = 0x0000 + BST_CHECKED = 0x0001 + BST_INDETERMINATE = 0x0002 +) + +var ( + checkDlgButton = user32.NewProc("CheckDlgButton") + checkRadioButton = user32.NewProc("CheckRadioButton") + isDlgButtonChecked = user32.NewProc("IsDlgButtonChecked") +) + +func CheckDlgButton(hDlg HWND, nIDButton int, uCheck uint32) (err error) { + r1, _, err := checkDlgButton.Call( + uintptr(hDlg), + uintptr(nIDButton), + uintptr(uCheck)) + if r1 == 0 { // failure + return err + } + return nil +} + +func CheckRadioButton(hDlg HWND, nIDFirstButton int, nIDLastButton int, nIDCheckButton int) (err error) { + r1, _, err := checkRadioButton.Call( + uintptr(hDlg), + uintptr(nIDFirstButton), + uintptr(nIDLastButton), + uintptr(nIDCheckButton)) + if r1 == 0 { // failure + return err + } + return nil +} + +// TODO handle errors +func IsDlgButtonChecked(hDlg HWND, nIDButton int) (state uint32, err error) { + r1, _, _ := isDlgButtonChecked.Call( + uintptr(hDlg), + uintptr(nIDButton)) + return uint32(r1), nil +} diff --git a/comboboxes.go b/comboboxes.go deleted file mode 100644 index ac2a715..0000000 --- a/comboboxes.go +++ /dev/null @@ -1,84 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Combobox styles. -const ( - // from winuser.h - CBS_SIMPLE = 0x0001 - CBS_DROPDOWN = 0x0002 - CBS_DROPDOWNLIST = 0x0003 - CBS_OWNERDRAWFIXED = 0x0010 - CBS_OWNERDRAWVARIABLE = 0x0020 - CBS_AUTOHSCROLL = 0x0040 - CBS_OEMCONVERT = 0x0080 - CBS_SORT = 0x0100 - CBS_HASSTRINGS = 0x0200 - CBS_NOINTEGRALHEIGHT = 0x0400 - CBS_DISABLENOSCROLL = 0x0800 - CBS_UPPERCASE = 0x2000 - CBS_LOWERCASE = 0x4000 -) - -// Combobox messages. -// TODO filter out messages not provided in windows 2000 -const ( - // from winuser.h - CB_GETEDITSEL = 0x0140 - CB_LIMITTEXT = 0x0141 - CB_SETEDITSEL = 0x0142 - CB_ADDSTRING = 0x0143 - CB_DELETESTRING = 0x0144 - CB_DIR = 0x0145 - CB_GETCOUNT = 0x0146 - CB_GETCURSEL = 0x0147 - CB_GETLBTEXT = 0x0148 - CB_GETLBTEXTLEN = 0x0149 - CB_INSERTSTRING = 0x014A - CB_RESETCONTENT = 0x014B - CB_FINDSTRING = 0x014C - CB_SELECTSTRING = 0x014D - CB_SETCURSEL = 0x014E - CB_SHOWDROPDOWN = 0x014F - CB_GETITEMDATA = 0x0150 - CB_SETITEMDATA = 0x0151 - CB_GETDROPPEDCONTROLRECT = 0x0152 - CB_SETITEMHEIGHT = 0x0153 - CB_GETITEMHEIGHT = 0x0154 - CB_SETEXTENDEDUI = 0x0155 - CB_GETEXTENDEDUI = 0x0156 - CB_GETDROPPEDSTATE = 0x0157 - CB_FINDSTRINGEXACT = 0x0158 - CB_SETLOCALE = 0x0159 - CB_GETLOCALE = 0x015A - CB_GETTOPINDEX = 0x015B - CB_SETTOPINDEX = 0x015C - CB_GETHORIZONTALEXTENT = 0x015D - CB_SETHORIZONTALEXTENT = 0x015E - CB_GETDROPPEDWIDTH = 0x015F - CB_SETDROPPEDWIDTH = 0x0160 - CB_INITSTORAGE = 0x0161 - CB_MULTIPLEADDSTRING = 0x0163 - CB_GETCOMBOBOXINFO = 0x0164 -) - -// Combobox WM_COMMAND notificaitons. -// TODO filter out notifications not provided in windows 2000 -const ( - // from winuser.h - CBN_ERRSPACE = (-1) // TODO this will blow up the Go compiler if it's used - CBN_SELCHANGE = 1 - CBN_DBLCLK = 2 - CBN_SETFOCUS = 3 - CBN_KILLFOCUS = 4 - CBN_EDITCHANGE = 5 - CBN_EDITUPDATE = 6 - CBN_DROPDOWN = 7 - CBN_CLOSEUP = 8 - CBN_SELENDOK = 9 - CBN_SELENDCANCEL = 10 -) diff --git a/comboboxes_windows.go b/comboboxes_windows.go new file mode 100644 index 0000000..ac2a715 --- /dev/null +++ b/comboboxes_windows.go @@ -0,0 +1,84 @@ +// 10 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Combobox styles. +const ( + // from winuser.h + CBS_SIMPLE = 0x0001 + CBS_DROPDOWN = 0x0002 + CBS_DROPDOWNLIST = 0x0003 + CBS_OWNERDRAWFIXED = 0x0010 + CBS_OWNERDRAWVARIABLE = 0x0020 + CBS_AUTOHSCROLL = 0x0040 + CBS_OEMCONVERT = 0x0080 + CBS_SORT = 0x0100 + CBS_HASSTRINGS = 0x0200 + CBS_NOINTEGRALHEIGHT = 0x0400 + CBS_DISABLENOSCROLL = 0x0800 + CBS_UPPERCASE = 0x2000 + CBS_LOWERCASE = 0x4000 +) + +// Combobox messages. +// TODO filter out messages not provided in windows 2000 +const ( + // from winuser.h + CB_GETEDITSEL = 0x0140 + CB_LIMITTEXT = 0x0141 + CB_SETEDITSEL = 0x0142 + CB_ADDSTRING = 0x0143 + CB_DELETESTRING = 0x0144 + CB_DIR = 0x0145 + CB_GETCOUNT = 0x0146 + CB_GETCURSEL = 0x0147 + CB_GETLBTEXT = 0x0148 + CB_GETLBTEXTLEN = 0x0149 + CB_INSERTSTRING = 0x014A + CB_RESETCONTENT = 0x014B + CB_FINDSTRING = 0x014C + CB_SELECTSTRING = 0x014D + CB_SETCURSEL = 0x014E + CB_SHOWDROPDOWN = 0x014F + CB_GETITEMDATA = 0x0150 + CB_SETITEMDATA = 0x0151 + CB_GETDROPPEDCONTROLRECT = 0x0152 + CB_SETITEMHEIGHT = 0x0153 + CB_GETITEMHEIGHT = 0x0154 + CB_SETEXTENDEDUI = 0x0155 + CB_GETEXTENDEDUI = 0x0156 + CB_GETDROPPEDSTATE = 0x0157 + CB_FINDSTRINGEXACT = 0x0158 + CB_SETLOCALE = 0x0159 + CB_GETLOCALE = 0x015A + CB_GETTOPINDEX = 0x015B + CB_SETTOPINDEX = 0x015C + CB_GETHORIZONTALEXTENT = 0x015D + CB_SETHORIZONTALEXTENT = 0x015E + CB_GETDROPPEDWIDTH = 0x015F + CB_SETDROPPEDWIDTH = 0x0160 + CB_INITSTORAGE = 0x0161 + CB_MULTIPLEADDSTRING = 0x0163 + CB_GETCOMBOBOXINFO = 0x0164 +) + +// Combobox WM_COMMAND notificaitons. +// TODO filter out notifications not provided in windows 2000 +const ( + // from winuser.h + CBN_ERRSPACE = (-1) // TODO this will blow up the Go compiler if it's used + CBN_SELCHANGE = 1 + CBN_DBLCLK = 2 + CBN_SETFOCUS = 3 + CBN_KILLFOCUS = 4 + CBN_EDITCHANGE = 5 + CBN_EDITUPDATE = 6 + CBN_DROPDOWN = 7 + CBN_CLOSEUP = 8 + CBN_SELENDOK = 9 + CBN_SELENDCANCEL = 10 +) diff --git a/common.go b/common.go deleted file mode 100644 index 79d6fc9..0000000 --- a/common.go +++ /dev/null @@ -1,73 +0,0 @@ -// 7 february 2014 -package main - -import ( - "syscall" - "unsafe" -) - -// TODO filter out commctrl.h stuff because the combobox and listbox stuff has values that differ between windows versions and bleh -// either that or switch to ComboBoxEx and ListView because they might not have that problem??? - -var ( - user32 = syscall.NewLazyDLL("user32.dll") - kernel32 = syscall.NewLazyDLL("kernel32.dll") - gdi32 = syscall.NewLazyDLL("gdi32.dll") -) - -type HANDLE uintptr -type HWND HANDLE -type HBRUSH HANDLE -type HMENU HANDLE - -const ( - NULL = 0 - FALSE = 0 // from windef.h - TRUE = 1 // from windef.h -) - -type ATOM uint16 - -// TODO pull the thanks for these three from the old wingo source -// TODO put these in windows.go -type WPARAM uintptr -type LPARAM uintptr -type LRESULT uintptr - -func (w WPARAM) LOWORD() uint16 { - // according to windef.h - return uint16(w & 0xFFFF) -} - -func (w WPARAM) HIWORD() uint16 { - // according to windef.h - return uint16((w >> 16) & 0xFFFF) -} - -func LPARAMFromString(str string) LPARAM { - return LPARAM(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) -} - -// microsoft's header files do this -func MAKEINTRESOURCE(what uint16) uintptr { - return uintptr(what) -} - -// TODO adorn error messages with which step failed? -func getText(hwnd HWND) (text string, err error) { - var tc []uint16 - - length, err := SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0) - if err != nil { - return "", err - } - tc = make([]uint16, length + 1) - _, err = SendMessage(hwnd, - WM_GETTEXT, - WPARAM(length + 1), - LPARAM(unsafe.Pointer(&tc[0]))) - if err != nil { - return "", err - } - return syscall.UTF16ToString(tc), nil -} diff --git a/common_windows.go b/common_windows.go new file mode 100644 index 0000000..79d6fc9 --- /dev/null +++ b/common_windows.go @@ -0,0 +1,73 @@ +// 7 february 2014 +package main + +import ( + "syscall" + "unsafe" +) + +// TODO filter out commctrl.h stuff because the combobox and listbox stuff has values that differ between windows versions and bleh +// either that or switch to ComboBoxEx and ListView because they might not have that problem??? + +var ( + user32 = syscall.NewLazyDLL("user32.dll") + kernel32 = syscall.NewLazyDLL("kernel32.dll") + gdi32 = syscall.NewLazyDLL("gdi32.dll") +) + +type HANDLE uintptr +type HWND HANDLE +type HBRUSH HANDLE +type HMENU HANDLE + +const ( + NULL = 0 + FALSE = 0 // from windef.h + TRUE = 1 // from windef.h +) + +type ATOM uint16 + +// TODO pull the thanks for these three from the old wingo source +// TODO put these in windows.go +type WPARAM uintptr +type LPARAM uintptr +type LRESULT uintptr + +func (w WPARAM) LOWORD() uint16 { + // according to windef.h + return uint16(w & 0xFFFF) +} + +func (w WPARAM) HIWORD() uint16 { + // according to windef.h + return uint16((w >> 16) & 0xFFFF) +} + +func LPARAMFromString(str string) LPARAM { + return LPARAM(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) +} + +// microsoft's header files do this +func MAKEINTRESOURCE(what uint16) uintptr { + return uintptr(what) +} + +// TODO adorn error messages with which step failed? +func getText(hwnd HWND) (text string, err error) { + var tc []uint16 + + length, err := SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0) + if err != nil { + return "", err + } + tc = make([]uint16, length + 1) + _, err = SendMessage(hwnd, + WM_GETTEXT, + WPARAM(length + 1), + LPARAM(unsafe.Pointer(&tc[0]))) + if err != nil { + return "", err + } + return syscall.UTF16ToString(tc), nil +} diff --git a/cursors.go b/cursors.go deleted file mode 100644 index 78fb1f8..0000000 --- a/cursors.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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/cursors_windows.go b/cursors_windows.go new file mode 100644 index 0000000..78fb1f8 --- /dev/null +++ b/cursors_windows.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/edits.go b/edits.go deleted file mode 100644 index 5aaeeac..0000000 --- a/edits.go +++ /dev/null @@ -1,94 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Edit control styles. -const ( - // from winuser.h - ES_LEFT = 0x0000 - ES_CENTER = 0x0001 - ES_RIGHT = 0x0002 - ES_MULTILINE = 0x0004 - ES_UPPERCASE = 0x0008 - ES_LOWERCASE = 0x0010 - ES_PASSWORD = 0x0020 - ES_AUTOVSCROLL = 0x0040 - ES_AUTOHSCROLL = 0x0080 - ES_NOHIDESEL = 0x0100 - ES_OEMCONVERT = 0x0400 - ES_READONLY = 0x0800 - ES_WANTRETURN = 0x1000 - ES_NUMBER = 0x2000 -) - -// Edit control messages. -// TODO filter out messages not provided in windows 2000 -const ( - // from winuser.h - EM_GETSEL = 0x00B0 - EM_SETSEL = 0x00B1 - EM_GETRECT = 0x00B2 - EM_SETRECT = 0x00B3 - EM_SETRECTNP = 0x00B4 - EM_SCROLL = 0x00B5 - EM_LINESCROLL = 0x00B6 - EM_SCROLLCARET = 0x00B7 - EM_GETMODIFY = 0x00B8 - EM_SETMODIFY = 0x00B9 - EM_GETLINECOUNT = 0x00BA - EM_LINEINDEX = 0x00BB - EM_SETHANDLE = 0x00BC - EM_GETHANDLE = 0x00BD - EM_GETTHUMB = 0x00BE - EM_LINELENGTH = 0x00C1 - EM_REPLACESEL = 0x00C2 - EM_GETLINE = 0x00C4 - EM_LIMITTEXT = 0x00C5 - EM_CANUNDO = 0x00C6 - EM_UNDO = 0x00C7 - EM_FMTLINES = 0x00C8 - EM_LINEFROMCHAR = 0x00C9 - EM_SETTABSTOPS = 0x00CB - EM_SETPASSWORDCHAR = 0x00CC - EM_EMPTYUNDOBUFFER = 0x00CD - EM_GETFIRSTVISIBLELINE = 0x00CE - EM_SETREADONLY = 0x00CF - EM_SETWORDBREAKPROC = 0x00D0 - EM_GETWORDBREAKPROC = 0x00D1 - EM_GETPASSWORDCHAR = 0x00D2 - EM_SETMARGINS = 0x00D3 - EM_GETMARGINS = 0x00D4 - EM_SETLIMITTEXT = EM_LIMITTEXT // [;win40 Name change] - EM_GETLIMITTEXT = 0x00D5 - EM_POSFROMCHAR = 0x00D6 - EM_CHARFROMPOS = 0x00D7 - EM_SETIMESTATUS = 0x00D8 - EM_GETIMESTATUS = 0x00D9 -) - -// Edit control WM_COMMAND notifications. -// TODO filter out notifications not provided in windows 2000 -const ( - // from winuser.h - EN_SETFOCUS = 0x0100 - EN_KILLFOCUS = 0x0200 - EN_CHANGE = 0x0300 - EN_UPDATE = 0x0400 - EN_ERRSPACE = 0x0500 - EN_MAXTEXT = 0x0501 - EN_HSCROLL = 0x0601 - EN_VSCROLL = 0x0602 - EN_ALIGN_LTR_EC = 0x0700 - EN_ALIGN_RTL_EC = 0x0701 - EC_LEFTMARGIN = 0x0001 - EC_RIGHTMARGIN = 0x0002 - EC_USEFONTINFO = 0xFFFF - EMSIS_COMPOSITIONSTRING = 0x0001 - EIMES_GETCOMPSTRATONCE = 0x0001 - EIMES_CANCELCOMPSTRINFOCUS = 0x0002 - EIMES_COMPLETECOMPSTRKILLFOCUS = 0x0004 -) diff --git a/edits_windows.go b/edits_windows.go new file mode 100644 index 0000000..5aaeeac --- /dev/null +++ b/edits_windows.go @@ -0,0 +1,94 @@ +// 10 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Edit control styles. +const ( + // from winuser.h + ES_LEFT = 0x0000 + ES_CENTER = 0x0001 + ES_RIGHT = 0x0002 + ES_MULTILINE = 0x0004 + ES_UPPERCASE = 0x0008 + ES_LOWERCASE = 0x0010 + ES_PASSWORD = 0x0020 + ES_AUTOVSCROLL = 0x0040 + ES_AUTOHSCROLL = 0x0080 + ES_NOHIDESEL = 0x0100 + ES_OEMCONVERT = 0x0400 + ES_READONLY = 0x0800 + ES_WANTRETURN = 0x1000 + ES_NUMBER = 0x2000 +) + +// Edit control messages. +// TODO filter out messages not provided in windows 2000 +const ( + // from winuser.h + EM_GETSEL = 0x00B0 + EM_SETSEL = 0x00B1 + EM_GETRECT = 0x00B2 + EM_SETRECT = 0x00B3 + EM_SETRECTNP = 0x00B4 + EM_SCROLL = 0x00B5 + EM_LINESCROLL = 0x00B6 + EM_SCROLLCARET = 0x00B7 + EM_GETMODIFY = 0x00B8 + EM_SETMODIFY = 0x00B9 + EM_GETLINECOUNT = 0x00BA + EM_LINEINDEX = 0x00BB + EM_SETHANDLE = 0x00BC + EM_GETHANDLE = 0x00BD + EM_GETTHUMB = 0x00BE + EM_LINELENGTH = 0x00C1 + EM_REPLACESEL = 0x00C2 + EM_GETLINE = 0x00C4 + EM_LIMITTEXT = 0x00C5 + EM_CANUNDO = 0x00C6 + EM_UNDO = 0x00C7 + EM_FMTLINES = 0x00C8 + EM_LINEFROMCHAR = 0x00C9 + EM_SETTABSTOPS = 0x00CB + EM_SETPASSWORDCHAR = 0x00CC + EM_EMPTYUNDOBUFFER = 0x00CD + EM_GETFIRSTVISIBLELINE = 0x00CE + EM_SETREADONLY = 0x00CF + EM_SETWORDBREAKPROC = 0x00D0 + EM_GETWORDBREAKPROC = 0x00D1 + EM_GETPASSWORDCHAR = 0x00D2 + EM_SETMARGINS = 0x00D3 + EM_GETMARGINS = 0x00D4 + EM_SETLIMITTEXT = EM_LIMITTEXT // [;win40 Name change] + EM_GETLIMITTEXT = 0x00D5 + EM_POSFROMCHAR = 0x00D6 + EM_CHARFROMPOS = 0x00D7 + EM_SETIMESTATUS = 0x00D8 + EM_GETIMESTATUS = 0x00D9 +) + +// Edit control WM_COMMAND notifications. +// TODO filter out notifications not provided in windows 2000 +const ( + // from winuser.h + EN_SETFOCUS = 0x0100 + EN_KILLFOCUS = 0x0200 + EN_CHANGE = 0x0300 + EN_UPDATE = 0x0400 + EN_ERRSPACE = 0x0500 + EN_MAXTEXT = 0x0501 + EN_HSCROLL = 0x0601 + EN_VSCROLL = 0x0602 + EN_ALIGN_LTR_EC = 0x0700 + EN_ALIGN_RTL_EC = 0x0701 + EC_LEFTMARGIN = 0x0001 + EC_RIGHTMARGIN = 0x0002 + EC_USEFONTINFO = 0xFFFF + EMSIS_COMPOSITIONSTRING = 0x0001 + EIMES_GETCOMPSTRATONCE = 0x0001 + EIMES_CANCELCOMPSTRINFOCUS = 0x0002 + EIMES_COMPLETECOMPSTRKILLFOCUS = 0x0004 +) diff --git a/icons.go b/icons.go deleted file mode 100644 index c28f158..0000000 --- a/icons.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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/icons_windows.go b/icons_windows.go new file mode 100644 index 0000000..c28f158 --- /dev/null +++ b/icons_windows.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/listboxes.go b/listboxes.go deleted file mode 100644 index 294cd96..0000000 --- a/listboxes.go +++ /dev/null @@ -1,91 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Listbox styles. -const ( - // from winuser.h - LBS_NOTIFY = 0x0001 - LBS_SORT = 0x0002 - LBS_NOREDRAW = 0x0004 - LBS_MULTIPLESEL = 0x0008 - LBS_OWNERDRAWFIXED = 0x0010 - LBS_OWNERDRAWVARIABLE = 0x0020 - LBS_HASSTRINGS = 0x0040 - LBS_USETABSTOPS = 0x0080 - LBS_NOINTEGRALHEIGHT = 0x0100 - LBS_MULTICOLUMN = 0x0200 - LBS_WANTKEYBOARDINPUT = 0x0400 - LBS_EXTENDEDSEL = 0x0800 - LBS_DISABLENOSCROLL = 0x1000 - LBS_NODATA = 0x2000 - LBS_NOSEL = 0x4000 - LBS_COMBOBOX = 0x8000 - LBS_STANDARD = (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER) -) - -// Listbox messages. -// TODO filter out messages not provided in windows 2000 -const ( - // from winuser.h - LB_ADDSTRING = 0x0180 - LB_INSERTSTRING = 0x0181 - LB_DELETESTRING = 0x0182 - LB_SELITEMRANGEEX = 0x0183 - LB_RESETCONTENT = 0x0184 - LB_SETSEL = 0x0185 - LB_SETCURSEL = 0x0186 - LB_GETSEL = 0x0187 - LB_GETCURSEL = 0x0188 - LB_GETTEXT = 0x0189 - LB_GETTEXTLEN = 0x018A - LB_GETCOUNT = 0x018B - LB_SELECTSTRING = 0x018C - LB_DIR = 0x018D - LB_GETTOPINDEX = 0x018E - LB_FINDSTRING = 0x018F - LB_GETSELCOUNT = 0x0190 - LB_GETSELITEMS = 0x0191 - LB_SETTABSTOPS = 0x0192 - LB_GETHORIZONTALEXTENT = 0x0193 - LB_SETHORIZONTALEXTENT = 0x0194 - LB_SETCOLUMNWIDTH = 0x0195 - LB_ADDFILE = 0x0196 - LB_SETTOPINDEX = 0x0197 - LB_GETITEMRECT = 0x0198 - LB_GETITEMDATA = 0x0199 - LB_SETITEMDATA = 0x019A - LB_SELITEMRANGE = 0x019B - LB_SETANCHORINDEX = 0x019C - LB_GETANCHORINDEX = 0x019D - LB_SETCARETINDEX = 0x019E - LB_GETCARETINDEX = 0x019F - LB_SETITEMHEIGHT = 0x01A0 - LB_GETITEMHEIGHT = 0x01A1 - LB_FINDSTRINGEXACT = 0x01A2 - LB_SETLOCALE = 0x01A5 - LB_GETLOCALE = 0x01A6 - LB_SETCOUNT = 0x01A7 - LB_INITSTORAGE = 0x01A8 - LB_ITEMFROMPOINT = 0x01A9 - LB_MULTIPLEADDSTRING = 0x01B1 - LB_GETLISTBOXINFO = 0x01B2 -) - -// Listbox WM_COMMAND notifications and message returns. -// TODO filter out notifications not provided in windows 2000 -const ( - // from winuser.h - LB_OKAY = 0 - LB_ERR = (-1) // TODO this will blow up the Go compiler if it's used - LBN_ERRSPACE = (-2) // TODO this will blow up the Go compiler if it's used - LBN_SELCHANGE = 1 - LBN_DBLCLK = 2 - LBN_SELCANCEL = 3 - LBN_SETFOCUS = 4 - LBN_KILLFOCUS = 5 -) diff --git a/listboxes_windows.go b/listboxes_windows.go new file mode 100644 index 0000000..294cd96 --- /dev/null +++ b/listboxes_windows.go @@ -0,0 +1,91 @@ +// 10 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Listbox styles. +const ( + // from winuser.h + LBS_NOTIFY = 0x0001 + LBS_SORT = 0x0002 + LBS_NOREDRAW = 0x0004 + LBS_MULTIPLESEL = 0x0008 + LBS_OWNERDRAWFIXED = 0x0010 + LBS_OWNERDRAWVARIABLE = 0x0020 + LBS_HASSTRINGS = 0x0040 + LBS_USETABSTOPS = 0x0080 + LBS_NOINTEGRALHEIGHT = 0x0100 + LBS_MULTICOLUMN = 0x0200 + LBS_WANTKEYBOARDINPUT = 0x0400 + LBS_EXTENDEDSEL = 0x0800 + LBS_DISABLENOSCROLL = 0x1000 + LBS_NODATA = 0x2000 + LBS_NOSEL = 0x4000 + LBS_COMBOBOX = 0x8000 + LBS_STANDARD = (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER) +) + +// Listbox messages. +// TODO filter out messages not provided in windows 2000 +const ( + // from winuser.h + LB_ADDSTRING = 0x0180 + LB_INSERTSTRING = 0x0181 + LB_DELETESTRING = 0x0182 + LB_SELITEMRANGEEX = 0x0183 + LB_RESETCONTENT = 0x0184 + LB_SETSEL = 0x0185 + LB_SETCURSEL = 0x0186 + LB_GETSEL = 0x0187 + LB_GETCURSEL = 0x0188 + LB_GETTEXT = 0x0189 + LB_GETTEXTLEN = 0x018A + LB_GETCOUNT = 0x018B + LB_SELECTSTRING = 0x018C + LB_DIR = 0x018D + LB_GETTOPINDEX = 0x018E + LB_FINDSTRING = 0x018F + LB_GETSELCOUNT = 0x0190 + LB_GETSELITEMS = 0x0191 + LB_SETTABSTOPS = 0x0192 + LB_GETHORIZONTALEXTENT = 0x0193 + LB_SETHORIZONTALEXTENT = 0x0194 + LB_SETCOLUMNWIDTH = 0x0195 + LB_ADDFILE = 0x0196 + LB_SETTOPINDEX = 0x0197 + LB_GETITEMRECT = 0x0198 + LB_GETITEMDATA = 0x0199 + LB_SETITEMDATA = 0x019A + LB_SELITEMRANGE = 0x019B + LB_SETANCHORINDEX = 0x019C + LB_GETANCHORINDEX = 0x019D + LB_SETCARETINDEX = 0x019E + LB_GETCARETINDEX = 0x019F + LB_SETITEMHEIGHT = 0x01A0 + LB_GETITEMHEIGHT = 0x01A1 + LB_FINDSTRINGEXACT = 0x01A2 + LB_SETLOCALE = 0x01A5 + LB_GETLOCALE = 0x01A6 + LB_SETCOUNT = 0x01A7 + LB_INITSTORAGE = 0x01A8 + LB_ITEMFROMPOINT = 0x01A9 + LB_MULTIPLEADDSTRING = 0x01B1 + LB_GETLISTBOXINFO = 0x01B2 +) + +// Listbox WM_COMMAND notifications and message returns. +// TODO filter out notifications not provided in windows 2000 +const ( + // from winuser.h + LB_OKAY = 0 + LB_ERR = (-1) // TODO this will blow up the Go compiler if it's used + LBN_ERRSPACE = (-2) // TODO this will blow up the Go compiler if it's used + LBN_SELCHANGE = 1 + LBN_DBLCLK = 2 + LBN_SELCANCEL = 3 + LBN_SETFOCUS = 4 + LBN_KILLFOCUS = 5 +) diff --git a/main.go b/main.go deleted file mode 100644 index 93aa4a1..0000000 --- a/main.go +++ /dev/null @@ -1,324 +0,0 @@ -// 7 february 2014 -package main - -import ( - "fmt" - "os" - "runtime" -) - -func fatalf(format string, args ...interface{}) { - s := fmt.Sprintf(format, args...) - _, err := MessageBox(NULL, - "An internal error has occured:\n" + s, - os.Args[0], - MB_OK | MB_ICONERROR) - if err == nil { - os.Exit(1) - } - panic(fmt.Sprintf("error trying to warn user of internal error: %v\ninternal error:\n%s", err, s)) -} - -const ( - IDC_BUTTON = 100 + iota - IDC_VARCOMBO - IDC_FIXCOMBO - IDC_EDIT - IDC_LIST - IDC_LABEL - IDC_CHECK -) - -var varCombo, fixCombo, edit, list HWND - -func wndProc(hwnd HWND, msg uint32, wParam WPARAM, lParam LPARAM) LRESULT { - switch msg { - case WM_COMMAND: - if wParam.LOWORD() == IDC_BUTTON { - buttonclick := "neither clicked nor double clicked (somehow)" - if wParam.HIWORD() == BN_CLICKED { - buttonclick = "clicked" - } else if wParam.HIWORD() == BN_DOUBLECLICKED { - buttonclick = "double clicked" - } - - varText, err := getText(varCombo) - if err != nil { - fatalf("error getting variable combo box text: %v", err) - } - - fixTextWM, err := getText(fixCombo) - if err != nil { - fatalf("error getting fixed combo box text with WM_GETTEXT: %v", err) - } - - fixTextIndex, err := SendMessage(fixCombo, CB_GETCURSEL, 0, 0) - if err != nil { - fatalf("error getting fixed combo box current selection: %v", err) - } - // TODO get text from index - - editText, err := getText(edit) - if err != nil { - fatalf("error getting edit field text: %v", err) - } - - listIndex, err := SendMessage(list, LB_GETCURSEL, 0, 0) - if err != nil { - fatalf("error getting fixed list box current selection: %v", err) - } - // TODO get text from index - - checkState, err := IsDlgButtonChecked(hwnd, IDC_CHECK) - if err != nil { - fatalf("error getting checkbox check state: %v", err) - } - - MessageBox(hwnd, - fmt.Sprintf("button state: %s\n" + - "variable combo box text: %s\n" + - "fixed combo box text with WM_GETTEXT: %s\n" + - "fixed combo box current index: %d\n" + - "edit field text: %s\n" + - "list box current index: %d\n" + - "check box checked: %v\n", - buttonclick, varText, fixTextWM, fixTextIndex, editText, listIndex, checkState == BST_CHECKED), - "note", - MB_OK) - } - return 0 - case WM_GETMINMAXINFO: - mm := lParam.MINMAXINFO() - mm.PtMinTrackSize.X = 320 - mm.PtMinTrackSize.Y = 240 - return 0 - case WM_SIZE: - if wParam != SIZE_MINIMIZED { - resize(hwnd) - } - return 0 - case WM_CLOSE: - err := DestroyWindow(hwnd) - if err != nil { - fatalf("error destroying window: %v", err) - } - return 0 - case WM_DESTROY: - err := PostQuitMessage(0) - if err != nil { - fatalf("error posting quit message: %v", err) - } - return 0 - default: - return DefWindowProc(hwnd, msg, wParam, lParam) - } - fatalf("major bug: forgot a return on wndProc for message %d", msg) - panic("unreachable") -} - -func setFontAll(hwnd HWND, lParam LPARAM) (cont bool) { - _, err := SendMessage(hwnd, WM_SETFONT, WPARAM(lParam), LPARAM(TRUE)) - if err != nil { - fatalf("error setting window font: %v", err) - } - return true -} - -func resize(hwnd HWND) { - cr, err := GetClientRect(hwnd) - if err != nil { - fatalf("error getting window client rect: %v", err) - } - cr.Bottom -= 80 // Y position of listbox - cr.Bottom -= 20 // amount of pixels to leave behind - err = SetWindowPos(list, - HWND_TOP, - 20, 80, 100, int(cr.Bottom), - 0) - if err != nil { - fatalf("error resizing listbox: %v", err) - } -} - -const className = "mainwin" - -func main() { - runtime.LockOSThread() - - hInstance, err := getWinMainhInstance() - if err != nil { - fatalf("error getting WinMain hInstance: %v", err) - } - nCmdShow, err := getWinMainnCmdShow() - if err != nil { - fatalf("error getting WinMain nCmdShow: %v", err) - } - font, err := getStandardWindowFont() - if err != nil { - fatalf("error getting standard window font: %v", err) - } - - icon, err := LoadIcon_ResourceID(NULL, IDI_APPLICATION) - if err != nil { - fatalf("error getting window icon: %v", err) - } - cursor, err := LoadCursor_ResourceID(NULL, IDC_ARROW) - if err != nil { - fatalf("error getting window cursor: %v", err) - } - - wc := &WNDCLASS{ - LpszClassName: className, - LpfnWndProc: wndProc, - HInstance: hInstance, - HIcon: icon, - HCursor: cursor, - HbrBackground: HBRUSH(COLOR_BTNFACE + 1), - } - _, err = RegisterClass(wc) - if err != nil { - fatalf("error registering window class: %v", err) - } - - hwnd, err := CreateWindowEx( - 0, - className, "Main Window", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, 320, 240, - NULL, NULL, hInstance, NULL) - if err != nil { - fatalf("error creating window: %v", err) - } - - const controlStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP - - _, err = CreateWindowEx( - 0, - "BUTTON", "Click Me", - BS_PUSHBUTTON | controlStyle, - 20, 20, 100, 20, - hwnd, HMENU(IDC_BUTTON), hInstance, NULL) - if err != nil { - fatalf("error creating button: %v", err) - } - - varCombo, err = CreateWindowEx( - 0, - "COMBOBOX", "", - CBS_DROPDOWN | CBS_AUTOHSCROLL | controlStyle, - 140, 20, 100, 20, - hwnd, HMENU(IDC_VARCOMBO), hInstance, NULL) - if err != nil { - fatalf("error creating variable combo box: %v", err) - } - vcItems := []string{"a", "b", "c", "d"} - for _, v := range vcItems { - _, err := SendMessage(varCombo, CB_ADDSTRING, 0, - LPARAMFromString(v)) - if err != nil { - fatalf("error adding %q to variable combo box: %v", v, err) - } - } - - fixCombo, err = CreateWindowEx( - 0, - "COMBOBOX", "", - CBS_DROPDOWNLIST | controlStyle, - 140, 50, 100, 20, - hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) - if err != nil { - fatalf("error creating fixed combo box: %v", err) - } - fcItems := []string{"e", "f", "g", "h"} - for _, v := range fcItems { - _, err := SendMessage(fixCombo, CB_ADDSTRING, 0, - LPARAMFromString(v)) - if err != nil { - fatalf("error adding %q to fixed combo box: %v", v, err) - } - } - - edit, err = CreateWindowEx( - 0, - "EDIT", "", - ES_AUTOHSCROLL | ES_NOHIDESEL | WS_BORDER | controlStyle, - 20, 50, 100, 20, - hwnd, HMENU(IDC_EDIT), hInstance, NULL) - if err != nil { - fatalf("error creating edit field: %v", err) - } - - list, err = CreateWindowEx( - 0, - "LISTBOX", "", - LBS_STANDARD | controlStyle, - 20, 80, 100, 100, - hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) - if err != nil { - fatalf("error creating list box: %v", err) - } - lItems := []string{"i", "j", "k", "l"} - for _, v := range lItems { - _, err := SendMessage(list, LB_ADDSTRING, 0, - LPARAMFromString(v)) - if err != nil { - fatalf("error adding %q to list box: %v", v, err) - } - // TODO check actual return value as THAT indicates an error - } - - _, err = CreateWindowEx( - 0, - "STATIC", "Label", - SS_NOPREFIX | controlStyle, - 140, 80, 100, 20, - hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) - if err != nil { - fatalf("error creating label: %v", err) - } - - _, err = CreateWindowEx( - 0, - "BUTTON", "Checkbox", - BS_AUTOCHECKBOX | controlStyle, - 140, 110, 100, 20, - hwnd, HMENU(IDC_CHECK), hInstance, NULL) - if err != nil { - fatalf("error creating checkbox: %v", err) - } - - setFontAll(hwnd, LPARAM(font)) - err = EnumChildWindows(hwnd, setFontAll, LPARAM(font)) - if err != nil { - fatalf("error setting font on controls: %v", err) - } - resize(hwnd) - - _, err = ShowWindow(hwnd, nCmdShow) - if err != nil { - fatalf("error showing window: %v", err) - } - err = UpdateWindow(hwnd) - if err != nil { - fatalf("error updating window: %v", err) - } - - for { - msg, done, err := GetMessage(NULL, 0, 0) - if err != nil { - fatalf("error getting message: %v", err) - } - if done { - break - } - _, err = TranslateMessage(msg) - if err != nil { - fatalf("error translating message: %v", err) - } - _, err = DispatchMessage(msg) - if err != nil { - fatalf("error dispatching message: %v", err) - } - } -} - diff --git a/main_windows.go b/main_windows.go new file mode 100644 index 0000000..93aa4a1 --- /dev/null +++ b/main_windows.go @@ -0,0 +1,324 @@ +// 7 february 2014 +package main + +import ( + "fmt" + "os" + "runtime" +) + +func fatalf(format string, args ...interface{}) { + s := fmt.Sprintf(format, args...) + _, err := MessageBox(NULL, + "An internal error has occured:\n" + s, + os.Args[0], + MB_OK | MB_ICONERROR) + if err == nil { + os.Exit(1) + } + panic(fmt.Sprintf("error trying to warn user of internal error: %v\ninternal error:\n%s", err, s)) +} + +const ( + IDC_BUTTON = 100 + iota + IDC_VARCOMBO + IDC_FIXCOMBO + IDC_EDIT + IDC_LIST + IDC_LABEL + IDC_CHECK +) + +var varCombo, fixCombo, edit, list HWND + +func wndProc(hwnd HWND, msg uint32, wParam WPARAM, lParam LPARAM) LRESULT { + switch msg { + case WM_COMMAND: + if wParam.LOWORD() == IDC_BUTTON { + buttonclick := "neither clicked nor double clicked (somehow)" + if wParam.HIWORD() == BN_CLICKED { + buttonclick = "clicked" + } else if wParam.HIWORD() == BN_DOUBLECLICKED { + buttonclick = "double clicked" + } + + varText, err := getText(varCombo) + if err != nil { + fatalf("error getting variable combo box text: %v", err) + } + + fixTextWM, err := getText(fixCombo) + if err != nil { + fatalf("error getting fixed combo box text with WM_GETTEXT: %v", err) + } + + fixTextIndex, err := SendMessage(fixCombo, CB_GETCURSEL, 0, 0) + if err != nil { + fatalf("error getting fixed combo box current selection: %v", err) + } + // TODO get text from index + + editText, err := getText(edit) + if err != nil { + fatalf("error getting edit field text: %v", err) + } + + listIndex, err := SendMessage(list, LB_GETCURSEL, 0, 0) + if err != nil { + fatalf("error getting fixed list box current selection: %v", err) + } + // TODO get text from index + + checkState, err := IsDlgButtonChecked(hwnd, IDC_CHECK) + if err != nil { + fatalf("error getting checkbox check state: %v", err) + } + + MessageBox(hwnd, + fmt.Sprintf("button state: %s\n" + + "variable combo box text: %s\n" + + "fixed combo box text with WM_GETTEXT: %s\n" + + "fixed combo box current index: %d\n" + + "edit field text: %s\n" + + "list box current index: %d\n" + + "check box checked: %v\n", + buttonclick, varText, fixTextWM, fixTextIndex, editText, listIndex, checkState == BST_CHECKED), + "note", + MB_OK) + } + return 0 + case WM_GETMINMAXINFO: + mm := lParam.MINMAXINFO() + mm.PtMinTrackSize.X = 320 + mm.PtMinTrackSize.Y = 240 + return 0 + case WM_SIZE: + if wParam != SIZE_MINIMIZED { + resize(hwnd) + } + return 0 + case WM_CLOSE: + err := DestroyWindow(hwnd) + if err != nil { + fatalf("error destroying window: %v", err) + } + return 0 + case WM_DESTROY: + err := PostQuitMessage(0) + if err != nil { + fatalf("error posting quit message: %v", err) + } + return 0 + default: + return DefWindowProc(hwnd, msg, wParam, lParam) + } + fatalf("major bug: forgot a return on wndProc for message %d", msg) + panic("unreachable") +} + +func setFontAll(hwnd HWND, lParam LPARAM) (cont bool) { + _, err := SendMessage(hwnd, WM_SETFONT, WPARAM(lParam), LPARAM(TRUE)) + if err != nil { + fatalf("error setting window font: %v", err) + } + return true +} + +func resize(hwnd HWND) { + cr, err := GetClientRect(hwnd) + if err != nil { + fatalf("error getting window client rect: %v", err) + } + cr.Bottom -= 80 // Y position of listbox + cr.Bottom -= 20 // amount of pixels to leave behind + err = SetWindowPos(list, + HWND_TOP, + 20, 80, 100, int(cr.Bottom), + 0) + if err != nil { + fatalf("error resizing listbox: %v", err) + } +} + +const className = "mainwin" + +func main() { + runtime.LockOSThread() + + hInstance, err := getWinMainhInstance() + if err != nil { + fatalf("error getting WinMain hInstance: %v", err) + } + nCmdShow, err := getWinMainnCmdShow() + if err != nil { + fatalf("error getting WinMain nCmdShow: %v", err) + } + font, err := getStandardWindowFont() + if err != nil { + fatalf("error getting standard window font: %v", err) + } + + icon, err := LoadIcon_ResourceID(NULL, IDI_APPLICATION) + if err != nil { + fatalf("error getting window icon: %v", err) + } + cursor, err := LoadCursor_ResourceID(NULL, IDC_ARROW) + if err != nil { + fatalf("error getting window cursor: %v", err) + } + + wc := &WNDCLASS{ + LpszClassName: className, + LpfnWndProc: wndProc, + HInstance: hInstance, + HIcon: icon, + HCursor: cursor, + HbrBackground: HBRUSH(COLOR_BTNFACE + 1), + } + _, err = RegisterClass(wc) + if err != nil { + fatalf("error registering window class: %v", err) + } + + hwnd, err := CreateWindowEx( + 0, + className, "Main Window", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 320, 240, + NULL, NULL, hInstance, NULL) + if err != nil { + fatalf("error creating window: %v", err) + } + + const controlStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP + + _, err = CreateWindowEx( + 0, + "BUTTON", "Click Me", + BS_PUSHBUTTON | controlStyle, + 20, 20, 100, 20, + hwnd, HMENU(IDC_BUTTON), hInstance, NULL) + if err != nil { + fatalf("error creating button: %v", err) + } + + varCombo, err = CreateWindowEx( + 0, + "COMBOBOX", "", + CBS_DROPDOWN | CBS_AUTOHSCROLL | controlStyle, + 140, 20, 100, 20, + hwnd, HMENU(IDC_VARCOMBO), hInstance, NULL) + if err != nil { + fatalf("error creating variable combo box: %v", err) + } + vcItems := []string{"a", "b", "c", "d"} + for _, v := range vcItems { + _, err := SendMessage(varCombo, CB_ADDSTRING, 0, + LPARAMFromString(v)) + if err != nil { + fatalf("error adding %q to variable combo box: %v", v, err) + } + } + + fixCombo, err = CreateWindowEx( + 0, + "COMBOBOX", "", + CBS_DROPDOWNLIST | controlStyle, + 140, 50, 100, 20, + hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) + if err != nil { + fatalf("error creating fixed combo box: %v", err) + } + fcItems := []string{"e", "f", "g", "h"} + for _, v := range fcItems { + _, err := SendMessage(fixCombo, CB_ADDSTRING, 0, + LPARAMFromString(v)) + if err != nil { + fatalf("error adding %q to fixed combo box: %v", v, err) + } + } + + edit, err = CreateWindowEx( + 0, + "EDIT", "", + ES_AUTOHSCROLL | ES_NOHIDESEL | WS_BORDER | controlStyle, + 20, 50, 100, 20, + hwnd, HMENU(IDC_EDIT), hInstance, NULL) + if err != nil { + fatalf("error creating edit field: %v", err) + } + + list, err = CreateWindowEx( + 0, + "LISTBOX", "", + LBS_STANDARD | controlStyle, + 20, 80, 100, 100, + hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) + if err != nil { + fatalf("error creating list box: %v", err) + } + lItems := []string{"i", "j", "k", "l"} + for _, v := range lItems { + _, err := SendMessage(list, LB_ADDSTRING, 0, + LPARAMFromString(v)) + if err != nil { + fatalf("error adding %q to list box: %v", v, err) + } + // TODO check actual return value as THAT indicates an error + } + + _, err = CreateWindowEx( + 0, + "STATIC", "Label", + SS_NOPREFIX | controlStyle, + 140, 80, 100, 20, + hwnd, HMENU(IDC_FIXCOMBO), hInstance, NULL) + if err != nil { + fatalf("error creating label: %v", err) + } + + _, err = CreateWindowEx( + 0, + "BUTTON", "Checkbox", + BS_AUTOCHECKBOX | controlStyle, + 140, 110, 100, 20, + hwnd, HMENU(IDC_CHECK), hInstance, NULL) + if err != nil { + fatalf("error creating checkbox: %v", err) + } + + setFontAll(hwnd, LPARAM(font)) + err = EnumChildWindows(hwnd, setFontAll, LPARAM(font)) + if err != nil { + fatalf("error setting font on controls: %v", err) + } + resize(hwnd) + + _, err = ShowWindow(hwnd, nCmdShow) + if err != nil { + fatalf("error showing window: %v", err) + } + err = UpdateWindow(hwnd) + if err != nil { + fatalf("error updating window: %v", err) + } + + for { + msg, done, err := GetMessage(NULL, 0, 0) + if err != nil { + fatalf("error getting message: %v", err) + } + if done { + break + } + _, err = TranslateMessage(msg) + if err != nil { + fatalf("error translating message: %v", err) + } + _, err = DispatchMessage(msg) + if err != nil { + fatalf("error dispatching message: %v", err) + } + } +} + diff --git a/menus.go b/menus.go deleted file mode 100644 index 4f6c059..0000000 --- a/menus.go +++ /dev/null @@ -1,12 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Menu notifications. -const ( - WM_COMMAND = 0x0111 -) diff --git a/menus_windows.go b/menus_windows.go new file mode 100644 index 0000000..4f6c059 --- /dev/null +++ b/menus_windows.go @@ -0,0 +1,12 @@ +// 10 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Menu notifications. +const ( + WM_COMMAND = 0x0111 +) diff --git a/messagebox.go b/messagebox.go deleted file mode 100644 index ba50f61..0000000 --- a/messagebox.go +++ /dev/null @@ -1,85 +0,0 @@ -// 7 february 2014 -package main - -import ( - "syscall" - "unsafe" -) - -// MessageBox button types. -const ( - MB_ABORTRETRYIGNORE = 0x00000002 - MB_CANCELTRYCONTINUE = 0x00000006 - MB_HELP = 0x00004000 - MB_OK = 0x00000000 - MB_OKCANCEL = 0x00000001 - MB_RETRYCANCEL = 0x00000005 - MB_YESNO = 0x00000004 - MB_YESNOCANCEL = 0x00000003 -) - -// MessageBox icon types. -const ( - MB_ICONEXCLAMATION = 0x00000030 - MB_ICONWARNING = 0x00000030 - MB_ICONINFORMATION = 0x00000040 - MB_ICONASTERISK = 0x00000040 - MB_ICONQUESTION = 0x00000020 - MB_ICONSTOP = 0x00000010 - MB_ICONERROR = 0x00000010 - MB_ICONHAND = 0x00000010 -) - -// MessageBox default button types. -const ( - MB_DEFBUTTON1 = 0x00000000 - MB_DEFBUTTON2 = 0x00000100 - MB_DEFBUTTON3 = 0x00000200 - MB_DEFBUTTON4 = 0x00000300 -) - -// MessageBox modality types. -const ( - MB_APPLMODAL = 0x00000000 - MB_SYSTEMMODAL = 0x00001000 - MB_TASKMODAL = 0x00002000 -) - -// MessageBox miscellaneous types. -const ( - MB_DEFAULT_DESKTOP_ONLY = 0x00020000 - MB_RIGHT = 0x00080000 - MB_RTLREADING = 0x00100000 - MB_SETFOREGROUND = 0x00010000 - MB_TOPMOST = 0x00040000 - MB_SERVICE_NOTIFICATION = 0x00200000 -) - -// MessageBox return values. -const ( - IDABORT = 3 - IDCANCEL = 2 - IDCONTINUE = 11 - IDIGNORE = 5 - IDNO = 7 - IDOK = 1 - IDRETRY = 4 - IDTRYAGAIN = 10 - IDYES = 6 -) - -var ( - messageBox = user32.NewProc("MessageBoxW") -) - -func MessageBox(hWnd HWND, lpText string, lpCaption string, uType uint32) (result int, err error) { - r1, _, err := messageBox.Call( - uintptr(unsafe.Pointer(hWnd)), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpText))), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCaption))), - uintptr(uType)) - if r1 == 0 { // failure - return 0, err - } - return int(r1), nil -} diff --git a/messagebox_windows.go b/messagebox_windows.go new file mode 100644 index 0000000..ba50f61 --- /dev/null +++ b/messagebox_windows.go @@ -0,0 +1,85 @@ +// 7 february 2014 +package main + +import ( + "syscall" + "unsafe" +) + +// MessageBox button types. +const ( + MB_ABORTRETRYIGNORE = 0x00000002 + MB_CANCELTRYCONTINUE = 0x00000006 + MB_HELP = 0x00004000 + MB_OK = 0x00000000 + MB_OKCANCEL = 0x00000001 + MB_RETRYCANCEL = 0x00000005 + MB_YESNO = 0x00000004 + MB_YESNOCANCEL = 0x00000003 +) + +// MessageBox icon types. +const ( + MB_ICONEXCLAMATION = 0x00000030 + MB_ICONWARNING = 0x00000030 + MB_ICONINFORMATION = 0x00000040 + MB_ICONASTERISK = 0x00000040 + MB_ICONQUESTION = 0x00000020 + MB_ICONSTOP = 0x00000010 + MB_ICONERROR = 0x00000010 + MB_ICONHAND = 0x00000010 +) + +// MessageBox default button types. +const ( + MB_DEFBUTTON1 = 0x00000000 + MB_DEFBUTTON2 = 0x00000100 + MB_DEFBUTTON3 = 0x00000200 + MB_DEFBUTTON4 = 0x00000300 +) + +// MessageBox modality types. +const ( + MB_APPLMODAL = 0x00000000 + MB_SYSTEMMODAL = 0x00001000 + MB_TASKMODAL = 0x00002000 +) + +// MessageBox miscellaneous types. +const ( + MB_DEFAULT_DESKTOP_ONLY = 0x00020000 + MB_RIGHT = 0x00080000 + MB_RTLREADING = 0x00100000 + MB_SETFOREGROUND = 0x00010000 + MB_TOPMOST = 0x00040000 + MB_SERVICE_NOTIFICATION = 0x00200000 +) + +// MessageBox return values. +const ( + IDABORT = 3 + IDCANCEL = 2 + IDCONTINUE = 11 + IDIGNORE = 5 + IDNO = 7 + IDOK = 1 + IDRETRY = 4 + IDTRYAGAIN = 10 + IDYES = 6 +) + +var ( + messageBox = user32.NewProc("MessageBoxW") +) + +func MessageBox(hWnd HWND, lpText string, lpCaption string, uType uint32) (result int, err error) { + r1, _, err := messageBox.Call( + uintptr(unsafe.Pointer(hWnd)), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpText))), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCaption))), + uintptr(uType)) + if r1 == 0 { // failure + return 0, err + } + return int(r1), nil +} diff --git a/messages.go b/messages.go deleted file mode 100644 index e74b9fa..0000000 --- a/messages.go +++ /dev/null @@ -1,72 +0,0 @@ -// 9 february 2014 -package main - -import ( -// "syscall" - "unsafe" -) - -// SendMessage constants. -const ( - HWND_BROADCAST = HWND(0xFFFF) -) - -type MSG struct { - Hwnd HWND - Message uint32 - WParam WPARAM - LParam LPARAM - Time uint32 - Pt POINT -} - -var ( - dispatchMessage = user32.NewProc("DispatchMessageW") - getMessage = user32.NewProc("GetMessageW") - postQuitMessage = user32.NewProc("PostQuitMessage") - sendMessage = user32.NewProc("SendMessageW") - translateMessage = user32.NewProc("TranslateMessage") -) - -// TODO handle errors -func DispatchMessage(lpmsg *MSG) (result LRESULT, err error) { - r1, _, _ := dispatchMessage.Call(uintptr(unsafe.Pointer(lpmsg))) - return LRESULT(r1), nil -} - -var getMessageFail = -1 // because Go doesn't let me - -func GetMessage(hWnd HWND, wMsgFilterMin uint32, wMsgFilterMax uint32) (lpMsg *MSG, quit bool, err error) { - lpMsg = new(MSG) - r1, _, err := getMessage.Call( - uintptr(unsafe.Pointer(lpMsg)), - uintptr(hWnd), - uintptr(wMsgFilterMin), - uintptr(wMsgFilterMax)) - if r1 == uintptr(getMessageFail) { // failure - return nil, false, err - } - return lpMsg, r1 == 0, nil -} - -// TODO handle errors -func PostQuitMessage(nExitCode int) (err error) { - postQuitMessage.Call(uintptr(nExitCode)) - return nil -} - -// TODO handle errors -func SendMessage(hWnd HWND, Msg uint32, wParam WPARAM, lParam LPARAM) (result LRESULT, err error) { - r1, _, _ := sendMessage.Call( - uintptr(hWnd), - uintptr(Msg), - uintptr(wParam), - uintptr(lParam)) - return LRESULT(r1), nil -} - -// TODO handle errors -func TranslateMessage(lpMsg *MSG) (translated bool, err error) { - r1, _, _ := translateMessage.Call(uintptr(unsafe.Pointer(lpMsg))) - return r1 != 0, nil -} diff --git a/messages_windows.go b/messages_windows.go new file mode 100644 index 0000000..e74b9fa --- /dev/null +++ b/messages_windows.go @@ -0,0 +1,72 @@ +// 9 february 2014 +package main + +import ( +// "syscall" + "unsafe" +) + +// SendMessage constants. +const ( + HWND_BROADCAST = HWND(0xFFFF) +) + +type MSG struct { + Hwnd HWND + Message uint32 + WParam WPARAM + LParam LPARAM + Time uint32 + Pt POINT +} + +var ( + dispatchMessage = user32.NewProc("DispatchMessageW") + getMessage = user32.NewProc("GetMessageW") + postQuitMessage = user32.NewProc("PostQuitMessage") + sendMessage = user32.NewProc("SendMessageW") + translateMessage = user32.NewProc("TranslateMessage") +) + +// TODO handle errors +func DispatchMessage(lpmsg *MSG) (result LRESULT, err error) { + r1, _, _ := dispatchMessage.Call(uintptr(unsafe.Pointer(lpmsg))) + return LRESULT(r1), nil +} + +var getMessageFail = -1 // because Go doesn't let me + +func GetMessage(hWnd HWND, wMsgFilterMin uint32, wMsgFilterMax uint32) (lpMsg *MSG, quit bool, err error) { + lpMsg = new(MSG) + r1, _, err := getMessage.Call( + uintptr(unsafe.Pointer(lpMsg)), + uintptr(hWnd), + uintptr(wMsgFilterMin), + uintptr(wMsgFilterMax)) + if r1 == uintptr(getMessageFail) { // failure + return nil, false, err + } + return lpMsg, r1 == 0, nil +} + +// TODO handle errors +func PostQuitMessage(nExitCode int) (err error) { + postQuitMessage.Call(uintptr(nExitCode)) + return nil +} + +// TODO handle errors +func SendMessage(hWnd HWND, Msg uint32, wParam WPARAM, lParam LPARAM) (result LRESULT, err error) { + r1, _, _ := sendMessage.Call( + uintptr(hWnd), + uintptr(Msg), + uintptr(wParam), + uintptr(lParam)) + return LRESULT(r1), nil +} + +// TODO handle errors +func TranslateMessage(lpMsg *MSG) (translated bool, err error) { + r1, _, _ := translateMessage.Call(uintptr(unsafe.Pointer(lpMsg))) + return r1 != 0, nil +} diff --git a/painting.go b/painting.go deleted file mode 100644 index 069fd2d..0000000 --- a/painting.go +++ /dev/null @@ -1,20 +0,0 @@ -// 9 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -var ( - updateWindow = user32.NewProc("UpdateWindow") -) - -// TODO is error handling valid here? MSDN just says zero on failure; syscall.LazyProc.Call() always returns non-nil -func UpdateWindow(hWnd HWND) (err error) { - r1, _, err := updateWindow.Call(uintptr(hWnd)) - if r1 == 0 { // failure - return err - } - return nil -} diff --git a/painting_windows.go b/painting_windows.go new file mode 100644 index 0000000..069fd2d --- /dev/null +++ b/painting_windows.go @@ -0,0 +1,20 @@ +// 9 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +var ( + updateWindow = user32.NewProc("UpdateWindow") +) + +// TODO is error handling valid here? MSDN just says zero on failure; syscall.LazyProc.Call() always returns non-nil +func UpdateWindow(hWnd HWND) (err error) { + r1, _, err := updateWindow.Call(uintptr(hWnd)) + if r1 == 0 { // failure + return err + } + return nil +} diff --git a/rectangles.go b/rectangles.go deleted file mode 100644 index c0c29d5..0000000 --- a/rectangles.go +++ /dev/null @@ -1,21 +0,0 @@ -// 9 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// TODO merge with common.go? - -type POINT struct { - X int32 - Y int32 -} - -type RECT struct { - Left int32 - Top int32 - Right int32 - Bottom int32 -} diff --git a/rectangles_windows.go b/rectangles_windows.go new file mode 100644 index 0000000..c0c29d5 --- /dev/null +++ b/rectangles_windows.go @@ -0,0 +1,21 @@ +// 9 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// TODO merge with common.go? + +type POINT struct { + X int32 + Y int32 +} + +type RECT struct { + Left int32 + Top int32 + Right int32 + Bottom int32 +} diff --git a/statics.go b/statics.go deleted file mode 100644 index ec62a13..0000000 --- a/statics.go +++ /dev/null @@ -1,57 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" -// "unsafe" -) - -// Static control styles. -const ( - // from winuser.h - SS_LEFT = 0x00000000 - SS_CENTER = 0x00000001 - SS_RIGHT = 0x00000002 - SS_ICON = 0x00000003 - SS_BLACKRECT = 0x00000004 - SS_GRAYRECT = 0x00000005 - SS_WHITERECT = 0x00000006 - SS_BLACKFRAME = 0x00000007 - SS_GRAYFRAME = 0x00000008 - SS_WHITEFRAME = 0x00000009 - SS_USERITEM = 0x0000000A - SS_SIMPLE = 0x0000000B - SS_LEFTNOWORDWRAP = 0x0000000C - SS_OWNERDRAW = 0x0000000D - SS_BITMAP = 0x0000000E - SS_ENHMETAFILE = 0x0000000F - SS_ETCHEDHORZ = 0x00000010 - SS_ETCHEDVERT = 0x00000011 - SS_ETCHEDFRAME = 0x00000012 - SS_TYPEMASK = 0x0000001F - SS_REALSIZECONTROL = 0x00000040 - SS_NOPREFIX = 0x00000080 - SS_NOTIFY = 0x00000100 - SS_CENTERIMAGE = 0x00000200 - SS_RIGHTJUST = 0x00000400 - SS_REALSIZEIMAGE = 0x00000800 - SS_SUNKEN = 0x00001000 - SS_EDITCONTROL = 0x00002000 - SS_ENDELLIPSIS = 0x00004000 - SS_PATHELLIPSIS = 0x00008000 - SS_WORDELLIPSIS = 0x0000C000 - SS_ELLIPSISMASK = 0x0000C000 -) - -// Static control messages and WM_COMMAND notifications. -const ( - // from winuser.h - STM_SETICON = 0x0170 - STM_GETICON = 0x0171 - STM_SETIMAGE = 0x0172 - STM_GETIMAGE = 0x0173 - STN_CLICKED = 0 - STN_DBLCLK = 1 - STN_ENABLE = 2 - STN_DISABLE = 3 -) diff --git a/statics_windows.go b/statics_windows.go new file mode 100644 index 0000000..ec62a13 --- /dev/null +++ b/statics_windows.go @@ -0,0 +1,57 @@ +// 10 february 2014 +package main + +import ( +// "syscall" +// "unsafe" +) + +// Static control styles. +const ( + // from winuser.h + SS_LEFT = 0x00000000 + SS_CENTER = 0x00000001 + SS_RIGHT = 0x00000002 + SS_ICON = 0x00000003 + SS_BLACKRECT = 0x00000004 + SS_GRAYRECT = 0x00000005 + SS_WHITERECT = 0x00000006 + SS_BLACKFRAME = 0x00000007 + SS_GRAYFRAME = 0x00000008 + SS_WHITEFRAME = 0x00000009 + SS_USERITEM = 0x0000000A + SS_SIMPLE = 0x0000000B + SS_LEFTNOWORDWRAP = 0x0000000C + SS_OWNERDRAW = 0x0000000D + SS_BITMAP = 0x0000000E + SS_ENHMETAFILE = 0x0000000F + SS_ETCHEDHORZ = 0x00000010 + SS_ETCHEDVERT = 0x00000011 + SS_ETCHEDFRAME = 0x00000012 + SS_TYPEMASK = 0x0000001F + SS_REALSIZECONTROL = 0x00000040 + SS_NOPREFIX = 0x00000080 + SS_NOTIFY = 0x00000100 + SS_CENTERIMAGE = 0x00000200 + SS_RIGHTJUST = 0x00000400 + SS_REALSIZEIMAGE = 0x00000800 + SS_SUNKEN = 0x00001000 + SS_EDITCONTROL = 0x00002000 + SS_ENDELLIPSIS = 0x00004000 + SS_PATHELLIPSIS = 0x00008000 + SS_WORDELLIPSIS = 0x0000C000 + SS_ELLIPSISMASK = 0x0000C000 +) + +// Static control messages and WM_COMMAND notifications. +const ( + // from winuser.h + STM_SETICON = 0x0170 + STM_GETICON = 0x0171 + STM_SETIMAGE = 0x0172 + STM_GETIMAGE = 0x0173 + STN_CLICKED = 0 + STN_DBLCLK = 1 + STN_ENABLE = 2 + STN_DISABLE = 3 +) diff --git a/stdfont.go b/stdfont.go deleted file mode 100644 index 8dcba9f..0000000 --- a/stdfont.go +++ /dev/null @@ -1,74 +0,0 @@ -// 10 february 2014 -package main - -import ( -// "syscall" - "unsafe" -) - -const ( - SPI_GETNONCLIENTMETRICS = 0x0029 - LF_FACESIZE = 32 // from wingdi.h -) - -type LOGFONT struct { - lfHeight int32 - lfWidth int32 - lfEscapement int32 - lfOrientation int32 - lfWeight int32 - lfItalic byte - lfUnderline byte - lfStrikeOut byte - lfCharSet byte - lfOutPrecision byte - lfClipPrecision byte - lfQuality byte - lfPitchAndFamily byte - lfFaceName [LF_FACESIZE]uint16 -} - -type NONCLIENTMETRICS struct { - cbSize uint32 - iBorderWidth int - iScrollWidth int - iScrollHeight int - iCaptionWidth int - iCaptionHeight int - lfCaptionFont LOGFONT - iSmCaptionWidth int - iSmCaptionHeight int - lfSmCaptionFont LOGFONT - iMenuWidth int - iMenuHeight int - lfMenuFont LOGFONT - lfStatusFont LOGFONT - lfMessageFont LOGFONT -} - -var ( - systemParametersInfo = user32.NewProc("SystemParametersInfoW") - createFontIndirect = gdi32.NewProc("CreateFontIndirectW") -) - -// TODO adorn errors with which step failed? -// TODO this specific font doesn't seem like the right one but that's all I could find for what people actually use; also I need to return the other ones and check HWND types to make sure I apply the right font to the right thing... -func getStandardWindowFont() (hfont HANDLE, err error) { - var ncm NONCLIENTMETRICS - - ncm.cbSize = uint32(unsafe.Sizeof(ncm)) - r1, _, err := systemParametersInfo.Call( - uintptr(SPI_GETNONCLIENTMETRICS), - uintptr(unsafe.Sizeof(ncm)), - uintptr(unsafe.Pointer(&ncm)), - 0) - if r1 == 0 { // failure - return NULL, err - } - // TODO does this specify an error? - r1, _, err = createFontIndirect.Call(uintptr(unsafe.Pointer(&ncm.lfMessageFont))) - if r1 == 0 { // failure - return NULL, err - } - return HANDLE(r1), nil -} diff --git a/stdfont_windows.go b/stdfont_windows.go new file mode 100644 index 0000000..8dcba9f --- /dev/null +++ b/stdfont_windows.go @@ -0,0 +1,74 @@ +// 10 february 2014 +package main + +import ( +// "syscall" + "unsafe" +) + +const ( + SPI_GETNONCLIENTMETRICS = 0x0029 + LF_FACESIZE = 32 // from wingdi.h +) + +type LOGFONT struct { + lfHeight int32 + lfWidth int32 + lfEscapement int32 + lfOrientation int32 + lfWeight int32 + lfItalic byte + lfUnderline byte + lfStrikeOut byte + lfCharSet byte + lfOutPrecision byte + lfClipPrecision byte + lfQuality byte + lfPitchAndFamily byte + lfFaceName [LF_FACESIZE]uint16 +} + +type NONCLIENTMETRICS struct { + cbSize uint32 + iBorderWidth int + iScrollWidth int + iScrollHeight int + iCaptionWidth int + iCaptionHeight int + lfCaptionFont LOGFONT + iSmCaptionWidth int + iSmCaptionHeight int + lfSmCaptionFont LOGFONT + iMenuWidth int + iMenuHeight int + lfMenuFont LOGFONT + lfStatusFont LOGFONT + lfMessageFont LOGFONT +} + +var ( + systemParametersInfo = user32.NewProc("SystemParametersInfoW") + createFontIndirect = gdi32.NewProc("CreateFontIndirectW") +) + +// TODO adorn errors with which step failed? +// TODO this specific font doesn't seem like the right one but that's all I could find for what people actually use; also I need to return the other ones and check HWND types to make sure I apply the right font to the right thing... +func getStandardWindowFont() (hfont HANDLE, err error) { + var ncm NONCLIENTMETRICS + + ncm.cbSize = uint32(unsafe.Sizeof(ncm)) + r1, _, err := systemParametersInfo.Call( + uintptr(SPI_GETNONCLIENTMETRICS), + uintptr(unsafe.Sizeof(ncm)), + uintptr(unsafe.Pointer(&ncm)), + 0) + if r1 == 0 { // failure + return NULL, err + } + // TODO does this specify an error? + r1, _, err = createFontIndirect.Call(uintptr(unsafe.Pointer(&ncm.lfMessageFont))) + if r1 == 0 { // failure + return NULL, err + } + return HANDLE(r1), nil +} diff --git a/windows.go b/windows.go deleted file mode 100644 index 2378aba..0000000 --- a/windows.go +++ /dev/null @@ -1,382 +0,0 @@ -// 8 february 2014 -package main - -import ( - "syscall" - "unsafe" -) - -// Window styles. -const ( - WS_BORDER = 0x00800000 - WS_CAPTION = 0x00C00000 - WS_CHILD = 0x40000000 - WS_CHILDWINDOW = 0x40000000 - WS_CLIPCHILDREN = 0x02000000 - WS_CLIPSIBLINGS = 0x04000000 - WS_DISABLED = 0x08000000 - WS_DLGFRAME = 0x00400000 - WS_GROUP = 0x00020000 - WS_HSCROLL = 0x00100000 - WS_ICONIC = 0x20000000 - WS_MAXIMIZE = 0x01000000 - WS_MAXIMIZEBOX = 0x00010000 - WS_MINIMIZE = 0x20000000 - WS_MINIMIZEBOX = 0x00020000 - WS_OVERLAPPED = 0x00000000 - WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) - WS_POPUP = 0x80000000 - WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU) - WS_SIZEBOX = 0x00040000 - WS_SYSMENU = 0x00080000 - WS_TABSTOP = 0x00010000 - WS_THICKFRAME = 0x00040000 - WS_TILED = 0x00000000 - WS_TILEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) - WS_VISIBLE = 0x10000000 - WS_VSCROLL = 0x00200000 -) - -// 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 -) - -// bizarrely, this value is given on the page for CreateMDIWindow, but not CreateWindow or CreateWindowEx -// I do it this way because Go won't let me shove the exact value into an int -var ( - _uCW_USEDEFAULT uint = 0x80000000 - CW_USEDEFAULT = int(_uCW_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 -) - -// SetWindowPos hWndInsertAfter values. -const ( - HWND_BOTTOM = HWND(1) - HWND_TOP = HWND(0) -) - -// SetWindowPos hWndInsertAfter values that Go won't allow as constants. -var ( - _HWND_NOTOPMOST = -2 - HWND_NOTOPMOST = HWND(_HWND_NOTOPMOST) - _HWND_TOPMOST = -1 - HWND_TOPMOST = HWND(_HWND_TOPMOST) -) - -// SetWindowPos uFlags values. -const ( - SWP_DRAWFRAME = 0x0020 - SWP_FRAMECHANGED = 0x0020 - SWP_HIDEWINDOW = 0x0080 - SWP_NOACTIVATE = 0x0010 - SWP_NOCOPYBITS = 0x0100 - SWP_NOMOVE = 0x0002 - SWP_NOOWNERZORDER = 0x0200 - SWP_NOREDRAW = 0x0008 - SWP_NOREPOSITION = 0x0200 - SWP_NOSENDCHANGING = 0x0400 - SWP_NOSIZE = 0x0001 - SWP_NOZORDER = 0x0004 - SWP_SHOWWINDOW = 0x0040 - SWP_ASYNCWINDOWPOS = 0x4000 - SWP_DEFERERASE = 0x2000 -) - -// ShowWindow settings. -const ( - SW_FORCEMINIMIZE = 11 - SW_HIDE = 0 - SW_MAXIMIZE = 3 - SW_MINIMIZE = 6 - SW_RESTORE = 9 - SW_SHOW = 5 - SW_SHOWDEFAULT = 10 - SW_SHOWMAXIMIZED = 3 - SW_SHOWMINIMIZED = 2 - SW_SHOWMINNOACTIVE = 7 - SW_SHOWNA = 8 - SW_SHOWNOACTIVATE = 4 - SW_SHOWNORMAL = 1 -) - -var ( - createWindowEx = user32.NewProc("CreateWindowExW") - destroyWindow = user32.NewProc("DestroyWindow") - getClientRect = user32.NewProc("GetClientRect") - enumChildWindows = user32.NewProc("EnumChildWindows") - setWindowPos = user32.NewProc("SetWindowPos") - showWindow = user32.NewProc("ShowWindow") -) - -// TODO use lpParam -func CreateWindowEx(dwExStyle uint32, lpClassName string, lpWindowName string, dwStyle uint32, x int, y int, nWidth int, nHeight int, hwndParent HWND, hMenu HMENU, 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 -} - -func DestroyWindow(hWnd HWND) (err error) { - r1, _, err := destroyWindow.Call(uintptr(hWnd)) - if r1 == 0 { // failure - return err - } - return nil -} - -type WNDENUMPROC func(hwnd HWND, lParam LPARAM) (cont bool) -type _WNDENUMPROC func(hwnd HWND, lParam LPARAM) int - -func enumChildProc(p WNDENUMPROC) _WNDENUMPROC { - return func(hwnd HWND, lParam LPARAM) int { - if p(hwnd, lParam) { - return TRUE - } - return FALSE - } -} - -// TODO figure out how to handle errors -func EnumChildWindows(hWndParent HWND, lpEnumFunc WNDENUMPROC, lParam LPARAM) (err error) { - enumChildWindows.Call( - uintptr(hWndParent), - syscall.NewCallback(enumChildProc(lpEnumFunc)), - uintptr(lParam)) - return nil -} - -// TODO return the rect itself? -func GetClientRect(hWnd HWND) (lpRect *RECT, err error) { - lpRect = new(RECT) - r1, _, err := getClientRect.Call( - uintptr(hWnd), - uintptr(unsafe.Pointer(lpRect))) - if r1 == 0 { // failure - return nil, err - } - return lpRect, nil -} - -func SetWindowPos(hWnd HWND, hWndInsertAfter HWND, X int, Y int, cx int, cy int, uFlags uint32) (err error) { - r1, _, err := setWindowPos.Call( - uintptr(hWnd), - uintptr(hWndInsertAfter), - uintptr(X), - uintptr(Y), - uintptr(cx), - uintptr(cy), - uintptr(uFlags)) - if r1 == 0 { // failure - return err - } - return nil -} - -// TODO figure out how to handle errors -func ShowWindow(hWnd HWND, nCmdShow int) (previouslyVisible bool, err error) { - r1, _, _ := showWindow.Call( - uintptr(hWnd), - uintptr(nCmdShow)) - return r1 != 0, nil -} - -// WM_SETICON and WM_GETICON values. -const ( - ICON_BIG = 1 - ICON_SMALL = 0 - ICON_SMALL2 = 2 // WM_GETICON only? -) - -// Window messages. -const ( - MN_GETHMENU = 0x01E1 - WM_ERASEBKGND = 0x0014 - WM_GETFONT = 0x0031 - WM_GETTEXT = 0x000D - WM_GETTEXTLENGTH = 0x000E - WM_SETFONT = 0x0030 - WM_SETICON = 0x0080 - WM_SETTEXT = 0x000C -) - -// WM_INPUTLANGCHANGEREQUEST values. -const ( - INPUTLANGCHANGE_BACKWARD = 0x0004 - INPUTLANGCHANGE_FORWARD = 0x0002 - INPUTLANGCHANGE_SYSCHARSET = 0x0001 -) - -// WM_NCCALCSIZE return values. -const ( - WVR_ALIGNTOP = 0x0010 - WVR_ALIGNRIGHT = 0x0080 - WVR_ALIGNLEFT = 0x0020 - WVR_ALIGNBOTTOM = 0x0040 - WVR_HREDRAW = 0x0100 - WVR_VREDRAW = 0x0200 - WVR_REDRAW = 0x0300 - WVR_VALIDRECTS = 0x0400 -) - -// WM_SHOWWINDOW reasons (lParam). -const ( - SW_OTHERUNZOOM = 4 - SW_OTHERZOOM = 2 - SW_PARENTCLOSING = 1 - SW_PARENTOPENING = 3 -) - -// WM_SIZE values. -const ( - SIZE_MAXHIDE = 4 - SIZE_MAXIMIZED = 2 - SIZE_MAXSHOW = 3 - SIZE_MINIMIZED = 1 - SIZE_RESTORED = 0 -) - -// WM_SIZING edge values (wParam). -const ( - WMSZ_BOTTOM = 6 - WMSZ_BOTTOMLEFT = 7 - WMSZ_BOTTOMRIGHT = 8 - WMSZ_LEFT = 1 - WMSZ_RIGHT = 2 - WMSZ_TOP = 3 - WMSZ_TOPLEFT = 4 - WMSZ_TOPRIGHT = 5 -) - -// WM_STYLECHANGED and WM_STYLECHANGING values (wParam). -const ( - GWL_EXSTYLE = -20 - GWL_STYLE = -16 -) - -// Window notifications. -const ( - WM_ACTIVATEAPP = 0x001C - WM_CANCELMODE = 0x001F - WM_CHILDACTIVATE = 0x0022 - WM_CLOSE = 0x0010 - WM_COMPACTING = 0x0041 - WM_CREATE = 0x0001 - WM_DESTROY = 0x0002 -// WM_DPICHANGED = 0x02E0 // Windows 8.1 and newer only - WM_ENABLE = 0x000A - WM_ENTERSIZEMOVE = 0x0231 - WM_EXITSIZEMOVE = 0x0232 - WM_GETICON = 0x007F - WM_GETMINMAXINFO = 0x0024 - WM_INPUTLANGCHANGE = 0x0051 - WM_INPUTLANGCHANGEREQUEST = 0x0050 - WM_MOVE = 0x0003 - WM_MOVING = 0x0216 - WM_NCACTIVATE = 0x0086 - WM_NCCALCSIZE = 0x0083 - WM_NCCREATE = 0x0081 - WM_NCDESTROY = 0x0082 - WM_NULL = 0x0000 - WM_QUERYDRAGICON = 0x0037 - WM_QUERYOPEN = 0x0013 - WM_QUIT = 0x0012 - WM_SHOWWINDOW = 0x0018 - WM_SIZE = 0x0005 - WM_SIZING = 0x0214 - WM_STYLECHANGED = 0x007D - WM_STYLECHANGING = 0x007C -// WM_THEMECHANGED = 0x031A // Windows XP and newer only -// WM_USERCHANGED = 0x0054 // Windows XP only: [Note This message is not supported as of Windows Vista.; also listed as not supported by server Windows] - WM_WINDOWPOSCHANGED = 0x0047 - WM_WINDOWPOSCHANGING = 0x0046 -) - -type MINMAXINFO struct { - PtReserved POINT - PtMaxSize POINT - PtMaxPosition POINT - PtMinTrackSize POINT - PtMaxTrackSize POINT -} - -func (l LPARAM) MINMAXINFO() *MINMAXINFO { - return (*MINMAXINFO)(unsafe.Pointer(l)) -} diff --git a/windows_windows.go b/windows_windows.go new file mode 100644 index 0000000..2378aba --- /dev/null +++ b/windows_windows.go @@ -0,0 +1,382 @@ +// 8 february 2014 +package main + +import ( + "syscall" + "unsafe" +) + +// Window styles. +const ( + WS_BORDER = 0x00800000 + WS_CAPTION = 0x00C00000 + WS_CHILD = 0x40000000 + WS_CHILDWINDOW = 0x40000000 + WS_CLIPCHILDREN = 0x02000000 + WS_CLIPSIBLINGS = 0x04000000 + WS_DISABLED = 0x08000000 + WS_DLGFRAME = 0x00400000 + WS_GROUP = 0x00020000 + WS_HSCROLL = 0x00100000 + WS_ICONIC = 0x20000000 + WS_MAXIMIZE = 0x01000000 + WS_MAXIMIZEBOX = 0x00010000 + WS_MINIMIZE = 0x20000000 + WS_MINIMIZEBOX = 0x00020000 + WS_OVERLAPPED = 0x00000000 + WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) + WS_POPUP = 0x80000000 + WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU) + WS_SIZEBOX = 0x00040000 + WS_SYSMENU = 0x00080000 + WS_TABSTOP = 0x00010000 + WS_THICKFRAME = 0x00040000 + WS_TILED = 0x00000000 + WS_TILEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) + WS_VISIBLE = 0x10000000 + WS_VSCROLL = 0x00200000 +) + +// 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 +) + +// bizarrely, this value is given on the page for CreateMDIWindow, but not CreateWindow or CreateWindowEx +// I do it this way because Go won't let me shove the exact value into an int +var ( + _uCW_USEDEFAULT uint = 0x80000000 + CW_USEDEFAULT = int(_uCW_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 +) + +// SetWindowPos hWndInsertAfter values. +const ( + HWND_BOTTOM = HWND(1) + HWND_TOP = HWND(0) +) + +// SetWindowPos hWndInsertAfter values that Go won't allow as constants. +var ( + _HWND_NOTOPMOST = -2 + HWND_NOTOPMOST = HWND(_HWND_NOTOPMOST) + _HWND_TOPMOST = -1 + HWND_TOPMOST = HWND(_HWND_TOPMOST) +) + +// SetWindowPos uFlags values. +const ( + SWP_DRAWFRAME = 0x0020 + SWP_FRAMECHANGED = 0x0020 + SWP_HIDEWINDOW = 0x0080 + SWP_NOACTIVATE = 0x0010 + SWP_NOCOPYBITS = 0x0100 + SWP_NOMOVE = 0x0002 + SWP_NOOWNERZORDER = 0x0200 + SWP_NOREDRAW = 0x0008 + SWP_NOREPOSITION = 0x0200 + SWP_NOSENDCHANGING = 0x0400 + SWP_NOSIZE = 0x0001 + SWP_NOZORDER = 0x0004 + SWP_SHOWWINDOW = 0x0040 + SWP_ASYNCWINDOWPOS = 0x4000 + SWP_DEFERERASE = 0x2000 +) + +// ShowWindow settings. +const ( + SW_FORCEMINIMIZE = 11 + SW_HIDE = 0 + SW_MAXIMIZE = 3 + SW_MINIMIZE = 6 + SW_RESTORE = 9 + SW_SHOW = 5 + SW_SHOWDEFAULT = 10 + SW_SHOWMAXIMIZED = 3 + SW_SHOWMINIMIZED = 2 + SW_SHOWMINNOACTIVE = 7 + SW_SHOWNA = 8 + SW_SHOWNOACTIVATE = 4 + SW_SHOWNORMAL = 1 +) + +var ( + createWindowEx = user32.NewProc("CreateWindowExW") + destroyWindow = user32.NewProc("DestroyWindow") + getClientRect = user32.NewProc("GetClientRect") + enumChildWindows = user32.NewProc("EnumChildWindows") + setWindowPos = user32.NewProc("SetWindowPos") + showWindow = user32.NewProc("ShowWindow") +) + +// TODO use lpParam +func CreateWindowEx(dwExStyle uint32, lpClassName string, lpWindowName string, dwStyle uint32, x int, y int, nWidth int, nHeight int, hwndParent HWND, hMenu HMENU, 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 +} + +func DestroyWindow(hWnd HWND) (err error) { + r1, _, err := destroyWindow.Call(uintptr(hWnd)) + if r1 == 0 { // failure + return err + } + return nil +} + +type WNDENUMPROC func(hwnd HWND, lParam LPARAM) (cont bool) +type _WNDENUMPROC func(hwnd HWND, lParam LPARAM) int + +func enumChildProc(p WNDENUMPROC) _WNDENUMPROC { + return func(hwnd HWND, lParam LPARAM) int { + if p(hwnd, lParam) { + return TRUE + } + return FALSE + } +} + +// TODO figure out how to handle errors +func EnumChildWindows(hWndParent HWND, lpEnumFunc WNDENUMPROC, lParam LPARAM) (err error) { + enumChildWindows.Call( + uintptr(hWndParent), + syscall.NewCallback(enumChildProc(lpEnumFunc)), + uintptr(lParam)) + return nil +} + +// TODO return the rect itself? +func GetClientRect(hWnd HWND) (lpRect *RECT, err error) { + lpRect = new(RECT) + r1, _, err := getClientRect.Call( + uintptr(hWnd), + uintptr(unsafe.Pointer(lpRect))) + if r1 == 0 { // failure + return nil, err + } + return lpRect, nil +} + +func SetWindowPos(hWnd HWND, hWndInsertAfter HWND, X int, Y int, cx int, cy int, uFlags uint32) (err error) { + r1, _, err := setWindowPos.Call( + uintptr(hWnd), + uintptr(hWndInsertAfter), + uintptr(X), + uintptr(Y), + uintptr(cx), + uintptr(cy), + uintptr(uFlags)) + if r1 == 0 { // failure + return err + } + return nil +} + +// TODO figure out how to handle errors +func ShowWindow(hWnd HWND, nCmdShow int) (previouslyVisible bool, err error) { + r1, _, _ := showWindow.Call( + uintptr(hWnd), + uintptr(nCmdShow)) + return r1 != 0, nil +} + +// WM_SETICON and WM_GETICON values. +const ( + ICON_BIG = 1 + ICON_SMALL = 0 + ICON_SMALL2 = 2 // WM_GETICON only? +) + +// Window messages. +const ( + MN_GETHMENU = 0x01E1 + WM_ERASEBKGND = 0x0014 + WM_GETFONT = 0x0031 + WM_GETTEXT = 0x000D + WM_GETTEXTLENGTH = 0x000E + WM_SETFONT = 0x0030 + WM_SETICON = 0x0080 + WM_SETTEXT = 0x000C +) + +// WM_INPUTLANGCHANGEREQUEST values. +const ( + INPUTLANGCHANGE_BACKWARD = 0x0004 + INPUTLANGCHANGE_FORWARD = 0x0002 + INPUTLANGCHANGE_SYSCHARSET = 0x0001 +) + +// WM_NCCALCSIZE return values. +const ( + WVR_ALIGNTOP = 0x0010 + WVR_ALIGNRIGHT = 0x0080 + WVR_ALIGNLEFT = 0x0020 + WVR_ALIGNBOTTOM = 0x0040 + WVR_HREDRAW = 0x0100 + WVR_VREDRAW = 0x0200 + WVR_REDRAW = 0x0300 + WVR_VALIDRECTS = 0x0400 +) + +// WM_SHOWWINDOW reasons (lParam). +const ( + SW_OTHERUNZOOM = 4 + SW_OTHERZOOM = 2 + SW_PARENTCLOSING = 1 + SW_PARENTOPENING = 3 +) + +// WM_SIZE values. +const ( + SIZE_MAXHIDE = 4 + SIZE_MAXIMIZED = 2 + SIZE_MAXSHOW = 3 + SIZE_MINIMIZED = 1 + SIZE_RESTORED = 0 +) + +// WM_SIZING edge values (wParam). +const ( + WMSZ_BOTTOM = 6 + WMSZ_BOTTOMLEFT = 7 + WMSZ_BOTTOMRIGHT = 8 + WMSZ_LEFT = 1 + WMSZ_RIGHT = 2 + WMSZ_TOP = 3 + WMSZ_TOPLEFT = 4 + WMSZ_TOPRIGHT = 5 +) + +// WM_STYLECHANGED and WM_STYLECHANGING values (wParam). +const ( + GWL_EXSTYLE = -20 + GWL_STYLE = -16 +) + +// Window notifications. +const ( + WM_ACTIVATEAPP = 0x001C + WM_CANCELMODE = 0x001F + WM_CHILDACTIVATE = 0x0022 + WM_CLOSE = 0x0010 + WM_COMPACTING = 0x0041 + WM_CREATE = 0x0001 + WM_DESTROY = 0x0002 +// WM_DPICHANGED = 0x02E0 // Windows 8.1 and newer only + WM_ENABLE = 0x000A + WM_ENTERSIZEMOVE = 0x0231 + WM_EXITSIZEMOVE = 0x0232 + WM_GETICON = 0x007F + WM_GETMINMAXINFO = 0x0024 + WM_INPUTLANGCHANGE = 0x0051 + WM_INPUTLANGCHANGEREQUEST = 0x0050 + WM_MOVE = 0x0003 + WM_MOVING = 0x0216 + WM_NCACTIVATE = 0x0086 + WM_NCCALCSIZE = 0x0083 + WM_NCCREATE = 0x0081 + WM_NCDESTROY = 0x0082 + WM_NULL = 0x0000 + WM_QUERYDRAGICON = 0x0037 + WM_QUERYOPEN = 0x0013 + WM_QUIT = 0x0012 + WM_SHOWWINDOW = 0x0018 + WM_SIZE = 0x0005 + WM_SIZING = 0x0214 + WM_STYLECHANGED = 0x007D + WM_STYLECHANGING = 0x007C +// WM_THEMECHANGED = 0x031A // Windows XP and newer only +// WM_USERCHANGED = 0x0054 // Windows XP only: [Note This message is not supported as of Windows Vista.; also listed as not supported by server Windows] + WM_WINDOWPOSCHANGED = 0x0047 + WM_WINDOWPOSCHANGING = 0x0046 +) + +type MINMAXINFO struct { + PtReserved POINT + PtMaxSize POINT + PtMaxPosition POINT + PtMinTrackSize POINT + PtMaxTrackSize POINT +} + +func (l LPARAM) MINMAXINFO() *MINMAXINFO { + return (*MINMAXINFO)(unsafe.Pointer(l)) +} diff --git a/winmain.go b/winmain.go deleted file mode 100644 index b79ad81..0000000 --- a/winmain.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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/winmain_windows.go b/winmain_windows.go new file mode 100644 index 0000000..b79ad81 --- /dev/null +++ b/winmain_windows.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 deleted file mode 100644 index 38ff4ae..0000000 --- a/wndclass.go +++ /dev/null @@ -1,64 +0,0 @@ -// 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 uintptr - 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: syscall.NewCallback(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/wndclass_windows.go b/wndclass_windows.go new file mode 100644 index 0000000..38ff4ae --- /dev/null +++ b/wndclass_windows.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 uintptr + 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: syscall.NewCallback(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 deleted file mode 100644 index b9c13f2..0000000 --- a/wndproc.go +++ /dev/null @@ -1,24 +0,0 @@ -// 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) -} diff --git a/wndproc_windows.go b/wndproc_windows.go new file mode 100644 index 0000000..b9c13f2 --- /dev/null +++ b/wndproc_windows.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) +} -- cgit v1.2.3