diff options
| -rw-r--r-- | redo/winapi_windows.h | 5 | ||||
| -rw-r--r-- | redo/window_windows.c | 80 | ||||
| -rw-r--r-- | redo/window_windows.go | 107 |
3 files changed, 120 insertions, 72 deletions
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index 1dce454..068cb13 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -51,3 +51,8 @@ extern HDC getDC(HWND); extern void releaseDC(HWND, HDC); extern void getTextMetricsW(HDC, TEXTMETRICW *); extern void moveWindow(HWND, int, int, int, int); + +/* window_windows.c */ +extern DWORD makeWindowWindowClass(char **); +extern HWND newWindow(LPCWSTR, int, int, void *); +extern void windowClose(HWND); diff --git a/redo/window_windows.c b/redo/window_windows.c new file mode 100644 index 0000000..5b45840 --- /dev/null +++ b/redo/window_windows.c @@ -0,0 +1,80 @@ +/* 17 july 2014 */ + +#include "winapi_windows.h" + +#define windowclass L"gouiwindow" + +static LRESULT CALLBACK windowWinProc(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); + storeWindowHWND(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, msg, wParam, lParam) + case WM_SIZE: + if (GetClientRect(hwnd, &r) == 0) + xparent("error getting client rect for Window in WM_SIZE", GetLastError()); + windowResize(data, &r); + return 0; + case WM_CLOSE: + windowClosing(data); + return 0; + default: + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + xmissedmsg("Window", "windowWinProc()", uMsg); + return 0; /* unreached */ +} + +DWORD makeWindowWindowClass(char **errmsg) +{ + WNDCLASSW wc; + + ZeroMemory(&wc, sizeof (WNDCLASSW)); + wc.lpfnWndProc = windowWndProc; + wc.hInstance = hInstance; + wc.hIcon = hDefaultIcon; + wc.hCursor = hArrowCursor; + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wc.lpszClassName = windowclass; + if (RegisterClassW(&wc) == 0) { + *errmsg = "error registering Window window class"; + return GetLastError(); + } + return 0; +} + +HWND newWindow(LPCWSTR title, int width, int height, void *data) +{ + HWND hwnd; + + hwnd = CreateWindowExW( + 0, + windowclass, title, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + width, height, + NULL, NULL, hInstance, w); + if (hwnd == NULL) + xpanic("Window creation failed", GetLastError(); + return hwnd; +} + +void windowClose(HWND hwnd) +{ + if (DestroyWindow(hwnd) == 0) + xpanic("error destroying window", GetLastError()); +} diff --git a/redo/window_windows.go b/redo/window_windows.go index c58d028..c670daa 100644 --- a/redo/window_windows.go +++ b/redo/window_windows.go @@ -8,8 +8,11 @@ import ( "unsafe" ) +// #include "winapi_windows.h" +import "C" + type window struct { - hwnd uintptr + hwnd C.HWND shownbefore bool child Control @@ -19,21 +22,15 @@ type window struct { spaced bool } -const windowclassname = "gouiwindow" +const windowclassname = "" var windowclassptr = syscall.StringToUTF16Ptr(windowclassname) func makeWindowWindowClass() error { - var wc s_WNDCLASSW + var errmsg *C.char - wc.lpfnWndProc = syscall.NewCallback(windowWndProc) - wc.hInstance = hInstance - wc.hIcon = hDefaultIcon - wc.hCursor = hArrowCursor - wc.hbrBackground = c_COLOR_BTNFACE + 1 - wc.lpszClassName = windowclassptr - res, err := f_RegisterClassW(&wc) - if res == 0 { - return fmt.Errorf("error registering Window window class: %v", err) + err := C.makeWindowWindowClass(&errmsg) + if err != 0 || errmsg != nil { + return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err)) } return nil } @@ -46,17 +43,8 @@ func newWindow(title string, width int, height int) *Request { // hwnd set in WM_CREATE handler closing: newEvent(), } - hwnd, err := f_CreateWindowExW( - 0, - windowclassptr, - syscall.StringToUTF16Ptr(title), - c_WS_OVERLAPPEDWINDOW, - c_CW_USEDEFAULT, c_CW_USEDEFAULT, - uintptr(width), uintptr(height), - hNULL, hNULL, hInstance, unsafe.Pointer(w)) - if hwnd == hNULL { - panic(fmt.Errorf("Window creation failed: %v", err)) - } else if hwnd != w.hwnd { + hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w)) + if hwnd != w.hwnd { panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window (%p) differ", hwnd, w.hwnd)) } c <- w @@ -85,7 +73,7 @@ func (w *window) Title() *Request { c := make(chan interface{}) return &Request{ op: func() { - c <- getWindowText(w.hwnd) + c <- C.GoString(C.getWindowText(w.hwnd)) }, resp: c, } @@ -95,7 +83,7 @@ func (w *window) SetTitle(title string) *Request { c := make(chan interface{}) return &Request{ op: func() { - setWindowText(w.hwnd, title, []t_LRESULT{c_FALSE}) + C.setWindowText(w.hwnd, toUTF16(title)) c <- struct{}{} }, resp: c, @@ -107,12 +95,11 @@ func (w *window) Show() *Request { return &Request{ op: func() { if !w.shownbefore { - // TODO get rid of need for cast - f_ShowWindow(w.hwnd, uintptr(nCmdShow)) - updateWindow(w.hwnd, "Window.Show()") + C.ShowWindow(w.hwnd, C.nCmdShow) + C.updateWindow(w.hwnd) w.shownbefore = true } else { - f_ShowWindow(w.hwnd, c_SW_SHOW) + C.ShowWindow(w.hwnd, C.SW_SHOW) } c <- struct{}{} }, @@ -124,25 +111,18 @@ func (w *window) Hide() *Request { c := make(chan interface{}) return &Request{ op: func() { - f_ShowWindow(w.hwnd, c_SW_HIDE) + C.ShowWindow(w.hwnd, C.SW_HIDE) c <- struct{}{} }, resp: c, } } -func doclose(w *window) { - res, err := f_DestroyWindow(w.hwnd) - if res == 0 { - panic(fmt.Errorf("error destroying window: %v", err)) - } -} - func (w *window) Close() *Request { c := make(chan interface{}) return &Request{ op: func() { - doclose(w) + C.windowClose(w.hwnd) c <- struct{}{} }, resp: c, @@ -160,40 +140,23 @@ func (w *window) OnClosing(e func(Doer) bool) *Request { } } -// TODO msg -> uMsg -func windowWndProc(hwnd uintptr, msg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT { - w := (*window)(unsafe.Pointer(f_GetWindowLongPtrW(hwnd, c_GWLP_USERDATA))) - if w == nil { - // the lpParam is available during WM_NCCREATE and WM_CREATE - if msg == c_WM_NCCREATE { - storelpParam(hwnd, lParam) - w := (*window)(unsafe.Pointer(f_GetWindowLongPtrW(hwnd, c_GWLP_USERDATA))) - w.hwnd = hwnd - } - // act as if we're not ready yet, even during WM_NCCREATE (nothing important to the switch statement below happens here anyway) - return f_DefWindowProcW(hwnd, msg, wParam, lParam) - } - switch msg { - case c_WM_COMMAND: - return forwardCommand(hwnd, msg, wParam, lParam) - case c_WM_SIZE: - var r s_RECT +//export storeWindowHWND +func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) { + w := (*window)(data) + w.hwnd = hwnd +} + +//export windowResize +func windowResize(data unsafe.Pointer, r *C.RECT) { + w := (*window)(data) + w.doresize(int(r.right - r.left), int(r.bottom - r.top)) +} - res, err := f_GetClientRect(w.hwnd, &r) - if res == 0 { - panic(fmt.Errorf("error getting client rect for Window in WM_SIZE: %v", err)) - } - w.doresize(int(r.right - r.left), int(r.bottom - r.top)) - fmt.Printf("new size %d x %d\n", r.right - r.left, r.bottom - r.top) - return 0 - case c_WM_CLOSE: - close := w.closing.fire() - if close { - doclose(w) - } - return 0 - default: - return f_DefWindowProcW(hwnd, msg, wParam, lParam) +//export windowClosing +func windowClosing(data unsafe.Pointer) { + w := (*window)(data) + close := w.closing.fire() + if close { + C.windowClose(w.hwnd) } - panic(fmt.Errorf("Window message %d does not return a value (bug in windowWndProc())", msg)) } |
