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  }