// 12 july 2014 package ui import ( "fmt" "syscall" "unsafe" ) type window struct { hwnd uintptr shownbefore bool closing *event } const windowclassname = "gouiwindow" var windowclassptr = syscall.StringToUTF16Ptr(windowclassname) func makeWindowWindowClass() error { var wc s_WNDCLASSW 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) } return nil } func newWindow(title string, width int, height int) *Request { c := make(chan interface{}) return &Request{ op: func() { w := &window{ // 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 { panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window (%p) differ", hwnd, w.hwnd)) } c <- w }, resp: c, } } func (w *window) SetControl(control Control) *Request { c := make(chan interface{}) return &Request{ op: func() { // TODO unparent // TODO reparent c <- struct{}{} }, resp: c, } } func (w *window) Title() *Request { c := make(chan interface{}) return &Request{ op: func() { c <- getWindowText(w.hwnd) }, resp: c, } } func (w *window) SetTitle(title string) *Request { c := make(chan interface{}) return &Request{ op: func() { setWindowText(w.hwnd, title, []t_LRESULT{c_FALSE}) c <- struct{}{} }, resp: c, } } func (w *window) Show() *Request { c := make(chan interface{}) 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()") w.shownbefore = true } else { f_ShowWindow(w.hwnd, c_SW_SHOW) } c <- struct{}{} }, resp: c, } } func (w *window) Hide() *Request { c := make(chan interface{}) return &Request{ op: func() { f_ShowWindow(w.hwnd, c_SW_HIDE) c <- struct{}{} }, resp: c, } } func (w *window) Close() *Request { c := make(chan interface{}) return &Request{ op: func() { // TODO c <- struct{}{} }, resp: c, } } func (w *window) OnClosing(e func(Doer) bool) *Request { c := make(chan interface{}) return &Request{ op: func() { w.closing.setbool(e) c <- struct{}{} }, resp: c, } } 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 { default: return f_DefWindowProcW(hwnd, msg, wParam, lParam) } panic(fmt.Errorf("Window message %d does not return a value (bug in windowWndProc())", msg)) } // TODO func newButton(string)*Request{return nil}