github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/winc/toolbar.go (about) 1 //go:build windows 2 3 /* 4 * Copyright (C) 2019 The Winc Authors. All Rights Reserved. 5 */ 6 7 package winc 8 9 import ( 10 "syscall" 11 "unsafe" 12 13 "github.com/secoba/wails/v2/internal/frontend/desktop/windows/winc/w32" 14 ) 15 16 type Toolbar struct { 17 ControlBase 18 iml *ImageList 19 20 buttons []*ToolButton 21 } 22 23 type ToolButton struct { 24 tb *Toolbar 25 26 text string 27 enabled bool 28 checkable bool 29 checked bool 30 image int 31 32 onClick EventManager 33 } 34 35 func (bt *ToolButton) OnClick() *EventManager { 36 return &bt.onClick 37 } 38 39 func (bt *ToolButton) update() { bt.tb.update(bt) } 40 41 func (bt *ToolButton) IsSeparator() bool { return bt.text == "-" } 42 func (bt *ToolButton) SetSeparator() { bt.text = "-" } 43 44 func (bt *ToolButton) Enabled() bool { return bt.enabled } 45 func (bt *ToolButton) SetEnabled(b bool) { bt.enabled = b; bt.update() } 46 47 func (bt *ToolButton) Checkable() bool { return bt.checkable } 48 func (bt *ToolButton) SetCheckable(b bool) { bt.checkable = b; bt.update() } 49 50 func (bt *ToolButton) Checked() bool { return bt.checked } 51 func (bt *ToolButton) SetChecked(b bool) { bt.checked = b; bt.update() } 52 53 func (bt *ToolButton) Text() string { return bt.text } 54 func (bt *ToolButton) SetText(s string) { bt.text = s; bt.update() } 55 56 func (bt *ToolButton) Image() int { return bt.image } 57 func (bt *ToolButton) SetImage(i int) { bt.image = i; bt.update() } 58 59 // NewHToolbar creates horizontal toolbar with text on same line as image. 60 func NewHToolbar(parent Controller) *Toolbar { 61 return newToolbar(parent, w32.CCS_NODIVIDER|w32.TBSTYLE_FLAT|w32.TBSTYLE_TOOLTIPS|w32.TBSTYLE_WRAPABLE| 62 w32.WS_CHILD|w32.TBSTYLE_LIST) 63 } 64 65 // NewToolbar creates toolbar with text below the image. 66 func NewToolbar(parent Controller) *Toolbar { 67 return newToolbar(parent, w32.CCS_NODIVIDER|w32.TBSTYLE_FLAT|w32.TBSTYLE_TOOLTIPS|w32.TBSTYLE_WRAPABLE| 68 w32.WS_CHILD /*|w32.TBSTYLE_TRANSPARENT*/) 69 } 70 71 func newToolbar(parent Controller, style uint) *Toolbar { 72 tb := new(Toolbar) 73 74 tb.InitControl("ToolbarWindow32", parent, 0, style) 75 76 exStyle := w32.SendMessage(tb.hwnd, w32.TB_GETEXTENDEDSTYLE, 0, 0) 77 exStyle |= w32.TBSTYLE_EX_DRAWDDARROWS | w32.TBSTYLE_EX_MIXEDBUTTONS 78 w32.SendMessage(tb.hwnd, w32.TB_SETEXTENDEDSTYLE, 0, exStyle) 79 RegMsgHandler(tb) 80 81 tb.SetFont(DefaultFont) 82 tb.SetPos(0, 0) 83 tb.SetSize(200, 40) 84 85 return tb 86 } 87 88 func (tb *Toolbar) SetImageList(imageList *ImageList) { 89 w32.SendMessage(tb.hwnd, w32.TB_SETIMAGELIST, 0, uintptr(imageList.Handle())) 90 tb.iml = imageList 91 } 92 93 func (tb *Toolbar) initButton(btn *ToolButton, state, style *byte, image *int32, text *uintptr) { 94 *style |= w32.BTNS_AUTOSIZE 95 96 if btn.checked { 97 *state |= w32.TBSTATE_CHECKED 98 } 99 100 if btn.enabled { 101 *state |= w32.TBSTATE_ENABLED 102 } 103 104 if btn.checkable { 105 *style |= w32.BTNS_CHECK 106 } 107 108 if len(btn.Text()) > 0 { 109 *style |= w32.BTNS_SHOWTEXT 110 } 111 112 if btn.IsSeparator() { 113 *style = w32.BTNS_SEP 114 } 115 116 *image = int32(btn.Image()) 117 *text = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(btn.Text()))) 118 } 119 120 func (tb *Toolbar) update(btn *ToolButton) { 121 tbbi := w32.TBBUTTONINFO{ 122 DwMask: w32.TBIF_IMAGE | w32.TBIF_STATE | w32.TBIF_STYLE | w32.TBIF_TEXT, 123 } 124 125 tbbi.CbSize = uint32(unsafe.Sizeof(tbbi)) 126 127 var i int 128 for i = range tb.buttons { 129 if tb.buttons[i] == btn { 130 break 131 } 132 } 133 134 tb.initButton(btn, &tbbi.FsState, &tbbi.FsStyle, &tbbi.IImage, &tbbi.PszText) 135 if w32.SendMessage(tb.hwnd, w32.TB_SETBUTTONINFO, uintptr(i), uintptr(unsafe.Pointer(&tbbi))) == 0 { 136 panic("SendMessage(TB_SETBUTTONINFO) failed") 137 } 138 } 139 140 func (tb *Toolbar) AddSeparator() { 141 tb.AddButton("-", 0) 142 } 143 144 // AddButton creates and adds button to the toolbar. Use returned toolbutton to setup OnClick event. 145 func (tb *Toolbar) AddButton(text string, image int) *ToolButton { 146 bt := &ToolButton{ 147 tb: tb, // points to parent 148 text: text, 149 image: image, 150 enabled: true, 151 } 152 tb.buttons = append(tb.buttons, bt) 153 index := len(tb.buttons) - 1 154 155 tbb := w32.TBBUTTON{ 156 IdCommand: int32(index), 157 } 158 159 tb.initButton(bt, &tbb.FsState, &tbb.FsStyle, &tbb.IBitmap, &tbb.IString) 160 w32.SendMessage(tb.hwnd, w32.TB_BUTTONSTRUCTSIZE, uintptr(unsafe.Sizeof(tbb)), 0) 161 162 if w32.SendMessage(tb.hwnd, w32.TB_INSERTBUTTON, uintptr(index), uintptr(unsafe.Pointer(&tbb))) == w32.FALSE { 163 panic("SendMessage(TB_ADDBUTTONS)") 164 } 165 166 w32.SendMessage(tb.hwnd, w32.TB_AUTOSIZE, 0, 0) 167 return bt 168 } 169 170 func (tb *Toolbar) WndProc(msg uint32, wparam, lparam uintptr) uintptr { 171 switch msg { 172 case w32.WM_COMMAND: 173 switch w32.HIWORD(uint32(wparam)) { 174 case w32.BN_CLICKED: 175 id := uint16(w32.LOWORD(uint32(wparam))) 176 btn := tb.buttons[id] 177 btn.onClick.Fire(NewEvent(tb, nil)) 178 } 179 } 180 return w32.DefWindowProc(tb.hwnd, msg, wparam, lparam) 181 }