summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comboboxes.go83
-rw-r--r--common.go26
-rw-r--r--main.go72
-rw-r--r--messages.go16
4 files changed, 194 insertions, 3 deletions
diff --git a/comboboxes.go b/comboboxes.go
new file mode 100644
index 0000000..77b7046
--- /dev/null
+++ b/comboboxes.go
@@ -0,0 +1,83 @@
+// 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.
+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
index 4505397..a51583d 100644
--- a/common.go
+++ b/common.go
@@ -3,8 +3,11 @@ package main
import (
"syscall"
+ "unsafe"
)
+// TODO filter out commctrl.h stuff because the combobox stuff has values that differ between windows versions and bleh
+
var (
user32 = syscall.NewLazyDLL("user32.dll")
kernel32 = syscall.NewLazyDLL("kernel32.dll")
@@ -37,7 +40,30 @@ func (w WPARAM) HIWORD() uint16 {
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/main.go b/main.go
index dd82c13..b551b40 100644
--- a/main.go
+++ b/main.go
@@ -21,17 +21,47 @@ func fatalf(format string, args ...interface{}) {
const (
IDC_BUTTON = 100
+ IDC_VARCOMBO = 101
+ IDC_FIXCOMBO = 102
)
+var varCombo, fixCombo 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 {
- MessageBox(hwnd, "clicked", "", MB_OK)
+ buttonclick = "clicked"
} else if wParam.HIWORD() == BN_DOUBLECLICKED {
- MessageBox(hwnd, "double clicked", "", MB_OK)
+ 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
+
+ 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",
+ buttonclick, varText, fixTextWM, fixTextIndex),
+ "note",
+ MB_OK)
}
return 0
case WM_CLOSE:
@@ -103,12 +133,48 @@ func main() {
0,
"BUTTON", "Click Me",
BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
- 20, 20, 100, 100,
+ 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 | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ 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 | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ 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)
+ }
+ }
+
_, err = ShowWindow(hwnd, nCmdShow)
if err != nil {
fatalf("error showing window: %v", err)
diff --git a/messages.go b/messages.go
index 4459035..e74b9fa 100644
--- a/messages.go
+++ b/messages.go
@@ -6,6 +6,11 @@ import (
"unsafe"
)
+// SendMessage constants.
+const (
+ HWND_BROADCAST = HWND(0xFFFF)
+)
+
type MSG struct {
Hwnd HWND
Message uint32
@@ -19,6 +24,7 @@ var (
dispatchMessage = user32.NewProc("DispatchMessageW")
getMessage = user32.NewProc("GetMessageW")
postQuitMessage = user32.NewProc("PostQuitMessage")
+ sendMessage = user32.NewProc("SendMessageW")
translateMessage = user32.NewProc("TranslateMessage")
)
@@ -50,6 +56,16 @@ func PostQuitMessage(nExitCode int) (err error) {
}
// 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