diff options
| -rw-r--r-- | redo/container_windows.c | 84 | ||||
| -rw-r--r-- | redo/layout_windows.go | 33 | ||||
| -rw-r--r-- | redo/uitask_windows.go | 3 | ||||
| -rw-r--r-- | redo/winapi_windows.h | 6 | ||||
| -rw-r--r-- | redo/window_windows.c | 17 | ||||
| -rw-r--r-- | redo/window_windows.go | 38 |
6 files changed, 148 insertions, 33 deletions
diff --git a/redo/container_windows.c b/redo/container_windows.c new file mode 100644 index 0000000..5db4548 --- /dev/null +++ b/redo/container_windows.c @@ -0,0 +1,84 @@ +/* 17 july 2014 */ + +#include "winapi_windows.h" +#include "_cgo_export.h" + +/* +This could all just be part of Window, but doing so just makes things complex. +In this case, I chose to waste a window handle rather than keep things super complex. +If this is seriously an issue in the future, I can roll it back. +*/ + +#define containerclass L"gouicontainer" + +static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + void *data; + RECT r; + + data = (void *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); + if (data == NULL) { + /* the lpParam is available during WM_NCCREATE and WM_CREATE */ + if (uMsg == WM_NCCREATE) { + storelpParam(hwnd, lParam); + data = (void *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); + storeContainerHWND(data, hwnd); + } + /* act as if we're not ready yet, even during WM_NCCREATE (nothing important to the switch statement below happens here anyway) */ + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + + switch (uMsg) { + case WM_COMMAND: + return forwardCommand(hwnd, uMsg, wParam, lParam); + case WM_NOTIFY: + return forwardNotify(hwnd, uMsg, wParam, lParam); + case WM_SIZE: + if (GetClientRect(hwnd, &r) == 0) + xpanic("error getting client rect for Window in WM_SIZE", GetLastError()); + containerResize(data, &r); + return 0; + default: + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + xmissedmsg("container", "containerWndProc()", uMsg); + return 0; /* unreached */ +} + +DWORD makeContainerWindowClass(char **errmsg) +{ + WNDCLASSW wc; + + ZeroMemory(&wc, sizeof (WNDCLASSW)); + wc.lpfnWndProc = containerWndProc; + wc.hInstance = hInstance; + wc.hIcon = hDefaultIcon; + wc.hCursor = hArrowCursor; + wc.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH); + if (wc.hbrBackground == NULL) { + *errmsg = "error getting hollow brush for container window class"; + return GetLastError(); + } + wc.lpszClassName = containerclass; + if (RegisterClassW(&wc) == 0) { + *errmsg = "error registering container window class"; + return GetLastError(); + } + return 0; +} + +HWND newContainer(void *data) +{ + HWND hwnd; + + hwnd = CreateWindowExW( + 0, + containerclass, L"", + WS_CHILD | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + 100, 100, + msgwin, NULL, hInstance, data); + if (hwnd == NULL) + xpanic("container creation failed", GetLastError()); + return hwnd; +} diff --git a/redo/layout_windows.go b/redo/layout_windows.go index 7d55a58..3010be9 100644 --- a/redo/layout_windows.go +++ b/redo/layout_windows.go @@ -20,15 +20,23 @@ type layout struct { *sizer } +func makeContainerWindowClass() error { + var errmsg *C.char + + err := C.makeContainerWindowClass(&errmsg) + if err != 0 || errmsg != nil { + return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err)) + } + return nil +} + func newLayout(title string, width int, height int, child C.BOOL, control Control) *layout { l := &layout{ - // hwnd set in WM_CREATE handler - closing: newEvent(), sizer: new(sizer), } - hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), child, unsafe.Pointer(l)) + hwnd := C.newContainer(unsafe.Pointer(l)) if hwnd != l.hwnd { - panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window/layout (%p) differ", hwnd, l.hwnd)) + panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, l.hwnd)) } l.child = control l.child.setParent(&controlParent{l.hwnd}) @@ -39,24 +47,15 @@ func (l *layout) setParent(p *controlParent) { C.controlSetParent(l.hwnd, p.hwnd) } -//export storeWindowHWND -func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) { +//export storeContainerHWND +func storeContainerHWND(data unsafe.Pointer, hwnd C.HWND) { l := (*layout)(data) l.hwnd = hwnd } -//export windowResize -func windowResize(data unsafe.Pointer, r *C.RECT) { +//export containerResize +func containerResize(data unsafe.Pointer, r *C.RECT) { l := (*layout)(data) // the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe l.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top)) } - -//export windowClosing -func windowClosing(data unsafe.Pointer) { - l := (*layout)(data) - close := l.closing.fire() - if close { - C.windowClose(l.hwnd) - } -} diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go index 7913a5c..71b097c 100644 --- a/redo/uitask_windows.go +++ b/redo/uitask_windows.go @@ -30,6 +30,9 @@ func uiinit() error { if err := makeWindowWindowClass(); err != nil { return fmt.Errorf("error creating Window window class: %v", err) } + if err := makeContainerWindowClass(); err != nil { + return fmt.Errorf("error creating container window class: %v", err) + } return nil } diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index 285bbcd..db90e97 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -74,7 +74,7 @@ extern LONG controlTextLength(HWND, LPWSTR); /* window_windows.c */ extern DWORD makeWindowWindowClass(char **); -extern HWND newWindow(LPWSTR, int, int, BOOL, void *); +extern HWND newWindow(LPWSTR, int, int, void *); extern void windowClose(HWND); /* common_windows.c */ @@ -98,4 +98,8 @@ extern void tableAppendColumn(HWND, int, LPWSTR); extern void tableUpdate(HWND, int); extern void tableAddExtendedStyles(HWND, LPARAM); +/* container_windows.c */ +extern DWORD makeContainerWindowClass(char **); +extern HWND newContainer(void *); + #endif diff --git a/redo/window_windows.c b/redo/window_windows.c index 5ed4de9..9cf0654 100644 --- a/redo/window_windows.c +++ b/redo/window_windows.c @@ -60,29 +60,20 @@ DWORD makeWindowWindowClass(char **errmsg) return 0; } -HWND newWindow(LPWSTR title, int width, int height, BOOL child, void *data) +HWND newWindow(LPWSTR title, int width, int height, void *data) { HWND hwnd; - DWORD style; - HWND parent; - style = WS_OVERLAPPEDWINDOW; - parent = NULL; - if (child) { - style = WS_CHILD | WS_VISIBLE; - parent = msgwin; - } hwnd = CreateWindowExW( 0, windowclass, title, - style, + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, - parent, NULL, hInstance, data); + NULL, NULL, hInstance, data); if (hwnd == NULL) xpanic("Window creation failed", GetLastError()); - if (!child) - calculateBaseUnits(hwnd); + calculateBaseUnits(hwnd); return hwnd; } diff --git a/redo/window_windows.go b/redo/window_windows.go index 3306613..9cf98d0 100644 --- a/redo/window_windows.go +++ b/redo/window_windows.go @@ -11,8 +11,12 @@ import ( import "C" type window struct { - *layout + hwnd C.HWND shownbefore bool + + closing *event + + *layout } func makeWindowWindowClass() error { @@ -27,13 +31,20 @@ func makeWindowWindowClass() error { func newWindow(title string, width int, height int, control Control) *window { w := &window{ - layout: newLayout(title, width, height, C.FALSE, control), + // hwnd set in WM_CREATE handler + closing: newEvent(), + layout: newLayout(control), + } + hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w)) + if hwnd != l.hwnd { + panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd)) } // TODO keep? hresult := C.EnableThemeDialogTexture(w.hwnd, C.ETDT_ENABLE | C.ETDT_USETABTEXTURE) if hresult != C.S_OK { panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult)) } + w.layout.setParent(&controlParent{w.hwnd}) return w } @@ -66,3 +77,26 @@ func (w *window) Close() { func (w *window) OnClosing(e func() bool) { w.closing.setbool(e) } + +//export storeWindowHWND +func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) { + w := (*wiindow)(data) + w.hwnd = hwnd +} + +//export windowResize +func windowResize(data unsafe.Pointer, r *C.RECT) { + w := (*window)(data) + // the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe + // TODO + C.moveWindow(w.layout.hwnd, int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top)) +} + +//export windowClosing +func windowClosing(data unsafe.Pointer) { + l := (*layout)(data) + close := l.closing.fire() + if close { + C.windowClose(l.hwnd) + } +} |
