Migrated window_windows.go to C.
This commit is contained in:
parent
29b80f7542
commit
0dc1538002
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
|
@ -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))
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue