summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-17 22:16:32 -0400
committerPietro Gagliardi <[email protected]>2014-07-17 22:16:32 -0400
commit7e40e9fe28f2349b06bf81a32e75183da1f48d56 (patch)
tree4c361c82c7d881249f3b04e47b75602e025d406a
parent8fee588a1da781c8823dcb7d0538cf1ec7022b39 (diff)
Migrated controls_windows.go to C.
-rw-r--r--redo/controls_windows.c71
-rw-r--r--redo/controls_windows.go87
-rw-r--r--redo/winapi_windows.h6
3 files changed, 96 insertions, 68 deletions
diff --git a/redo/controls_windows.c b/redo/controls_windows.c
new file mode 100644
index 0000000..dadce75
--- /dev/null
+++ b/redo/controls_windows.c
@@ -0,0 +1,71 @@
+/* 17 july 2014 */
+
+#include "winapi_windows.h"
+
+HWND newWidget(LPCWSTR class, DWORD style, DWORD extstyle)
+{
+ HWND hwnd;
+
+ hwnd = CreateWindowExW(
+ extstyle,
+ class, L"",
+ style | WS_CHILD | WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ /*
+ the following has the consequence of making the control message-only at first
+ this shouldn't cause any problems... hopefully not
+ but see the msgwndproc() for caveat info
+ also don't use low control IDs as they will conflict with dialog boxes (IDCANCEL, etc.)
+ */
+ msgwin, (HMENU) 100, hInstance, NULL);
+ if (hwnd == NULL) {
+ xpanic("error creating control", GetLastError());
+ return hwnd;
+}
+
+void controlSetParent(HWND control, HWND parent)
+{
+ if (SetParent(control, parent) == NULL)
+ xpanic("error changing control parent", GetLastError());
+}
+
+/*
+all controls that have events receive the events themselves through subclasses
+to do this, all windows (including the message-only window; see http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q104069) forward WM_COMMAND to each control with this function
+*/
+LRESULT forwardCommand(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HWND control = (HWND) lParam;
+
+ /* don't generate an event if the control (if there is one) is unparented (a child of the message-only window) */
+ if (control != NULL && IsChild(msgwin, control) == 0)
+ return SendMessageW(control, msgCOMMAND, wParam, lParam);
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+}
+
+static LRESULT CALLBACK buttonSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data)
+{
+ switch (uMsg) {
+ case msgCOMMAND:
+ if (HIWORD(wParam) == BN_CLICKED) {
+ buttonClicked(data);
+ return 0;
+ }
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ case WM_NCDESTROY:
+ if ((*fv_RemoveWindowSubclass)(hwnd, buttonSubProc, id) == FALSE)
+ xpanic("error removing Button subclass (which was for its own event handler)", GetLastError());
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ default:
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ }
+ xmissedmsg("Button", "buttonSubProc()", uMsg);
+ return 0; /* unreached */
+}
+
+void setButtonSubclass(HWND hwnd, void *data)
+{
+ if ((*fv_SetWindowSubclass)(hwnd, buttonSubProc, 0, (DWORD_PTR) data) == FALSE)
+ xpanic("error subclassing Button to give it its own event handler", GetLastError());
+}
diff --git a/redo/controls_windows.go b/redo/controls_windows.go
index 299ce99..8f82eac 100644
--- a/redo/controls_windows.go
+++ b/redo/controls_windows.go
@@ -8,47 +8,27 @@ import (
"unsafe"
)
+// #include "winapi_windows.h"
+import "C"
+
type widgetbase struct {
- hwnd uintptr
+ hwnd C.HWND
}
-var emptystr = syscall.StringToUTF16Ptr("")
-
-func newWidget(class *uint16, style uintptr, extstyle uintptr) *widgetbase {
- hwnd, err := f_CreateWindowExW(
- extstyle,
- class, emptystr,
- style | c_WS_CHILD | c_WS_VISIBLE,
- c_CW_USEDEFAULT, c_CW_USEDEFAULT,
-// c_CW_USEDEFAULT, c_CW_USEDEFAULT,
-100,100,
- // the following has the consequence of making the control message-only at first
- // this shouldn't cause any problems... hopefully not
- // but see the msgwndproc() for caveat info
- // also don't use low control IDs as they will conflict with dialog boxes (IDCANCEL, etc.)
- msgwin, 100, hInstance, nil)
- if hwnd == hNULL {
- panic(fmt.Errorf("creating control of class %q failed: %v", class, err))
- }
+func newWidget(class C.LPCWSTR, style uintptr, extstyle uintptr) *widgetbase {
return &widgetbase{
- hwnd: hwnd,
+ hwnd: C.newWidget(class, style, extstyle),
}
}
// these few methods are embedded by all the various Controls since they all will do the same thing
func (w *widgetbase) unparent() {
- res, err := f_SetParent(w.hwnd, msgwin)
- if res == hNULL { // result type is HWND
- panic(fmt.Errorf("error unparenting control: %v", err))
- }
+ C.controlSetParent(w.hwnd, C.msgwin)
}
func (w *widgetbase) parent(win *window) {
- res, err := f_SetParent(w.hwnd, win.hwnd)
- if res == hNULL { // result type is HWND
- panic(fmt.Errorf("error parenting control: %v", err))
- }
+ C.controlSetParent(w.hwnd, win.hwnd)
}
// don't embed these as exported; let each Control decide if it should
@@ -57,7 +37,7 @@ func (w *widgetbase) text() *Request {
c := make(chan interface{})
return &Request{
op: func() {
- c <- getWindowText(w.hwnd)
+ c <- C.GoString(C.getWindowText(w.hwnd))
},
resp: c,
}
@@ -67,47 +47,33 @@ func (w *widgetbase) settext(text string, results ...t_LRESULT) *Request {
c := make(chan interface{})
return &Request{
op: func() {
- setWindowText(w.hwnd, text, append([]t_LRESULT{c_FALSE}, results...))
+ C.setWindowText(w.hwnd, toUTF16(text))
c <- struct{}{}
},
resp: c,
}
}
-// all controls that have events receive the events themselves through subclasses
-// to do this, all windows (including the message-only window; see http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q104069) forward WM_COMMAND to each control with this function
-func forwardCommand(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
- control := uintptr(lParam)
- // don't generate an event if the control (if there is one) is unparented (a child of the message-only window)
- if control != hNULL && f_IsChild(msgwin, control) == 0 {
- return f_SendMessageW(control, msgCOMMAND, wParam, lParam)
- }
- return f_DefWindowProcW(hwnd, uMsg, wParam, lParam)
-}
-
type button struct {
*widgetbase
clicked *event
}
-var buttonclass = syscall.StringToUTF16Ptr("BUTTON")
+var buttonclass = toUTF16("BUTTON")
func newButton(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w := newWidget(buttonclass,
- c_BS_PUSHBUTTON | c_WS_TABSTOP,
+ C.BS_PUSHBUTTON | C.WS_TABSTOP,
0)
- setWindowText(w.hwnd, text, []t_LRESULT{c_FALSE})
+ C.setWindowText(w.hwnd, toUTF16(text))
b := &button{
widgetbase: w,
clicked: newEvent(),
}
- res, err := f_SetWindowSubclass(w.hwnd, buttonsubprocptr, 0, t_DWORD_PTR(uintptr(unsafe.Pointer(b))))
- if res == c_FALSE {
- panic(fmt.Errorf("error subclassing Button to give it its own event handler: %v", err))
- }
+ C.setButtonSubclass(w.hwnd, unsafe.Pointer(b))
c <- b
},
resp: c,
@@ -140,24 +106,9 @@ func init() {
buttonsubprocptr = syscall.NewCallback(buttonSubProc)
}
-func buttonSubProc(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM, id t_UINT_PTR, data t_DWORD_PTR) t_LRESULT {
- b := (*button)(unsafe.Pointer(uintptr(data)))
- switch uMsg {
- case msgCOMMAND:
- if wParam.HIWORD() == c_BN_CLICKED {
- b.clicked.fire()
- println("button clicked")
- return 0
- }
- return f_DefSubclassProc(hwnd, uMsg, wParam, lParam)
- case c_WM_NCDESTROY:
- res, err := f_RemoveWindowSubclass(b.hwnd, buttonsubprocptr, id)
- if res == c_FALSE {
- panic(fmt.Errorf("error removing Button subclass (which was for its own event handler): %v", err))
- }
- return f_DefSubclassProc(hwnd, uMsg, wParam, lParam)
- default:
- return f_DefSubclassProc(hwnd, uMsg, wParam, lParam)
- }
- panic(fmt.Errorf("Button message %d does not return a value (bug in buttonSubProc())", uMsg))
+//export buttonClicked
+func buttonClicked(data unsafe.Pointer) {
+ b := (*button)(data)
+ b.clicked.fire()
+ println("button clicked")
}
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 81bf271..ea3c745 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -32,3 +32,9 @@ extern DWORD initCommonControls(LPCWSTR, char **);
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+
+/* controls_windows.c */
+extern HWND newWidget(LPCWSTR, DWORD, DWORD);
+extern void controlSetParent(HWND, HWND);
+extern LRESULT forwardCommand(HWND, UINT, WPARAM, LPARAM);
+extern void setButtonSubclass(HWND, void *);