Migrated window_windows.go to C.

This commit is contained in:
Pietro Gagliardi 2014-07-17 23:11:16 -04:00
parent 29b80f7542
commit 0dc1538002
3 changed files with 122 additions and 74 deletions

View File

@ -51,3 +51,8 @@ extern HDC getDC(HWND);
extern void releaseDC(HWND, HDC); extern void releaseDC(HWND, HDC);
extern void getTextMetricsW(HDC, TEXTMETRICW *); extern void getTextMetricsW(HDC, TEXTMETRICW *);
extern void moveWindow(HWND, int, int, int, int); 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);

80
redo/window_windows.c Normal file
View File

@ -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());
}

View File

@ -8,8 +8,11 @@ import (
"unsafe" "unsafe"
) )
// #include "winapi_windows.h"
import "C"
type window struct { type window struct {
hwnd uintptr hwnd C.HWND
shownbefore bool shownbefore bool
child Control child Control
@ -19,21 +22,15 @@ type window struct {
spaced bool spaced bool
} }
const windowclassname = "gouiwindow" const windowclassname = ""
var windowclassptr = syscall.StringToUTF16Ptr(windowclassname) var windowclassptr = syscall.StringToUTF16Ptr(windowclassname)
func makeWindowWindowClass() error { func makeWindowWindowClass() error {
var wc s_WNDCLASSW var errmsg *C.char
wc.lpfnWndProc = syscall.NewCallback(windowWndProc) err := C.makeWindowWindowClass(&errmsg)
wc.hInstance = hInstance if err != 0 || errmsg != nil {
wc.hIcon = hDefaultIcon return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err))
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)
} }
return nil return nil
} }
@ -46,17 +43,8 @@ func newWindow(title string, width int, height int) *Request {
// hwnd set in WM_CREATE handler // hwnd set in WM_CREATE handler
closing: newEvent(), closing: newEvent(),
} }
hwnd, err := f_CreateWindowExW( hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w))
0, if hwnd != w.hwnd {
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 {
panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window (%p) differ", hwnd, w.hwnd)) panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window (%p) differ", hwnd, w.hwnd))
} }
c <- w c <- w
@ -85,7 +73,7 @@ func (w *window) Title() *Request {
c := make(chan interface{}) c := make(chan interface{})
return &Request{ return &Request{
op: func() { op: func() {
c <- getWindowText(w.hwnd) c <- C.GoString(C.getWindowText(w.hwnd))
}, },
resp: c, resp: c,
} }
@ -95,7 +83,7 @@ func (w *window) SetTitle(title string) *Request {
c := make(chan interface{}) c := make(chan interface{})
return &Request{ return &Request{
op: func() { op: func() {
setWindowText(w.hwnd, title, []t_LRESULT{c_FALSE}) C.setWindowText(w.hwnd, toUTF16(title))
c <- struct{}{} c <- struct{}{}
}, },
resp: c, resp: c,
@ -107,12 +95,11 @@ func (w *window) Show() *Request {
return &Request{ return &Request{
op: func() { op: func() {
if !w.shownbefore { if !w.shownbefore {
// TODO get rid of need for cast C.ShowWindow(w.hwnd, C.nCmdShow)
f_ShowWindow(w.hwnd, uintptr(nCmdShow)) C.updateWindow(w.hwnd)
updateWindow(w.hwnd, "Window.Show()")
w.shownbefore = true w.shownbefore = true
} else { } else {
f_ShowWindow(w.hwnd, c_SW_SHOW) C.ShowWindow(w.hwnd, C.SW_SHOW)
} }
c <- struct{}{} c <- struct{}{}
}, },
@ -124,25 +111,18 @@ func (w *window) Hide() *Request {
c := make(chan interface{}) c := make(chan interface{})
return &Request{ return &Request{
op: func() { op: func() {
f_ShowWindow(w.hwnd, c_SW_HIDE) C.ShowWindow(w.hwnd, C.SW_HIDE)
c <- struct{}{} c <- struct{}{}
}, },
resp: c, 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 { func (w *window) Close() *Request {
c := make(chan interface{}) c := make(chan interface{})
return &Request{ return &Request{
op: func() { op: func() {
doclose(w) C.windowClose(w.hwnd)
c <- struct{}{} c <- struct{}{}
}, },
resp: c, resp: c,
@ -160,40 +140,23 @@ func (w *window) OnClosing(e func(Doer) bool) *Request {
} }
} }
// TODO msg -> uMsg //export storeWindowHWND
func windowWndProc(hwnd uintptr, msg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT { func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) {
w := (*window)(unsafe.Pointer(f_GetWindowLongPtrW(hwnd, c_GWLP_USERDATA))) w := (*window)(data)
if w == nil { w.hwnd = hwnd
// the lpParam is available during WM_NCCREATE and WM_CREATE }
if msg == c_WM_NCCREATE {
storelpParam(hwnd, lParam) //export windowResize
w := (*window)(unsafe.Pointer(f_GetWindowLongPtrW(hwnd, c_GWLP_USERDATA))) func windowResize(data unsafe.Pointer, r *C.RECT) {
w.hwnd = hwnd w := (*window)(data)
} w.doresize(int(r.right - r.left), int(r.bottom - r.top))
// 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)
} //export windowClosing
switch msg { func windowClosing(data unsafe.Pointer) {
case c_WM_COMMAND: w := (*window)(data)
return forwardCommand(hwnd, msg, wParam, lParam) close := w.closing.fire()
case c_WM_SIZE: if close {
var r s_RECT C.windowClose(w.hwnd)
}
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)
}
panic(fmt.Errorf("Window message %d does not return a value (bug in windowWndProc())", msg))
} }