github.com/as/shiny@v0.8.2/driver/win32/window.go (about) 1 2 // +build windows 3 4 package win32 5 6 import ( 7 "syscall" 8 "unsafe" 9 10 "github.com/as/shiny/screen" 11 ) 12 13 type newWindowParams struct { 14 opts *screen.NewWindowOptions 15 w syscall.Handle 16 err error 17 } 18 19 var windowMsgs = map[uint32]func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr){ 20 WmSetfocus: sendFocus, 21 WmKillfocus: sendFocus, 22 WmPaint: sendPaint, 23 msgShow: sendShow, 24 WmWindowposchanged: sendSizeEvent, 25 WmClose: sendClose, 26 27 WmLbuttondown: mousetab[WmLbuttondown].send, 28 WmLbuttonup: mousetab[WmLbuttonup].send, 29 WmMbuttondown: mousetab[WmMbuttondown].send, 30 WmMbuttonup: mousetab[WmMbuttonup].send, 31 WmRbuttondown: mousetab[WmRbuttondown].send, 32 WmRbuttonup: mousetab[WmRbuttonup].send, 33 WmMousemove: mousetab[WmMousemove].send, 34 WmMousewheel: sendScrollEvent, 35 36 WmKeydown: keytab.sendDown, 37 WmKeyup: keytab.sendUp, 38 // TODO case WmSyskeydown, WmSyskeyup: 39 40 // TODO(as): This will probably break something, let's not 41 //WmInputlangchange: changeLanguage, 42 } 43 44 func NewWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { 45 var p newWindowParams 46 p.opts = opts 47 SendScreenMessage(msgCreateWindow, 0, uintptr(unsafe.Pointer(&p))) 48 return p.w, p.err 49 } 50 51 func AddWindowMsg(fn func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr)) uint32 { 52 uMsg := currentUserWM.next() 53 windowMsgs[uMsg] = func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) uintptr { 54 fn(hwnd, uMsg, wParam, lParam) 55 return 0 56 } 57 return uMsg 58 } 59 60 func SendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { 61 return sendMessage(hwnd, uMsg, wParam, lParam) 62 } 63 64 // Resize makes hwnd client rectangle opts.Width by opts.Height in size. 65 func Resize(h syscall.Handle, p Point) error { 66 if p.X == 0 || p.Y == 0 { 67 return nil 68 } 69 70 var cr Rectangle 71 if err := GetClientRect(h, &cr); err != nil { 72 return err 73 } 74 75 var wr Rectangle 76 if err := GetWindowRect(h, &wr); err != nil { 77 return err 78 } 79 80 wr.Max.X = wr.Dx() - (cr.Max.X - int32(p.X)) 81 wr.Max.Y = wr.Dy() - (cr.Max.Y - int32(p.Y)) 82 83 return Reshape(h, wr) 84 } 85 86 // Reshape makes hwnd client rectangle opts.Width by opts.Height in size. 87 func Reshape(h syscall.Handle, r Rectangle) error { 88 return MoveWindow(h, r.Min.X, r.Min.Y, r.Dx(), r.Dy(), false) 89 } 90 91 // Show shows a newly created window. 92 // It sends the appropriate lifecycle events, makes the window appear 93 // on the screen, and sends an initial size event. 94 // 95 // This is a separate step from NewWindow to give the driver a chance 96 // to setup its internal state for a window before events start being 97 // delivered. 98 func Show(hwnd syscall.Handle) { 99 SendMessage(hwnd, msgShow, 0, 0) 100 } 101 102 func Release(hwnd syscall.Handle) { 103 DestroyWindow(hwnd) 104 } 105 106 func newWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { 107 // TODO(brainman): convert windowClass to *uint16 once (in initWindowClass) 108 wcname, err := syscall.UTF16PtrFromString(windowClass) 109 if err != nil { 110 return 0, err 111 } 112 title, err := syscall.UTF16PtrFromString(opts.GetTitle()) 113 if err != nil { 114 return 0, err 115 } 116 117 // h := syscall.Handle(0) 118 // if opts.Overlay{ 119 // h = GetConsoleWindow() 120 // } 121 hwnd, err := CreateWindowEx(0, 122 wcname, title, 123 WsOverlappedWindow, 124 CwUseDefault, CwUseDefault, 125 CwUseDefault, CwUseDefault, 126 0, // was console handle in experiment 127 0, hThisInstance, 0) 128 if err != nil { 129 return 0, err 130 } 131 // TODO(andlabs): use proper nCmdShow 132 // TODO(andlabs): call UpdateWindow() 133 134 return hwnd, nil 135 } 136 137 func windowWndProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { 138 fn := windowMsgs[uMsg] 139 if fn != nil { 140 return fn(hwnd, uMsg, wParam, lParam) 141 } 142 return DefWindowProc(hwnd, uMsg, wParam, lParam) 143 }