func setWindowText(hwnd win.HWND, text string) error { if win.TRUE != win.SendMessage(hwnd, win.WM_SETTEXT, 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text)))) { return newError("WM_SETTEXT failed") } return nil }
func (tw *TabWidget) onClearedPages(pages []*TabPage) (err error) { win.SendMessage(tw.hWndTab, win.TCM_DELETEALLITEMS, 0, 0) for _, page := range pages { tw.removePage(page) } tw.currentIndex = -1 return nil }
func (tw *TabWidget) onPageChanged(page *TabPage) (err error) { index := tw.pages.Index(page) item := tw.tcitemFromPage(page) if 0 == win.SendMessage(tw.hWndTab, win.TCM_SETITEM, uintptr(index), uintptr(unsafe.Pointer(item))) { return newError("SendMessage(TCM_SETITEM) failed") } return nil }
func notifyIconWndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) (result uintptr) { // Retrieve our *NotifyIcon from the message window. ptr := win.GetWindowLongPtr(hwnd, win.GWLP_USERDATA) ni := (*NotifyIcon)(unsafe.Pointer(ptr)) switch lParam { case win.WM_LBUTTONDOWN: ni.publishMouseEvent(&ni.mouseDownPublisher, LeftButton) case win.WM_LBUTTONUP: ni.publishMouseEvent(&ni.mouseUpPublisher, LeftButton) case win.WM_RBUTTONDOWN: ni.publishMouseEvent(&ni.mouseDownPublisher, RightButton) case win.WM_RBUTTONUP: ni.publishMouseEvent(&ni.mouseUpPublisher, RightButton) win.SendMessage(hwnd, msg, wParam, win.WM_CONTEXTMENU) case win.WM_CONTEXTMENU: if ni.contextMenu.Actions().Len() == 0 { break } win.SetForegroundWindow(hwnd) var p win.POINT if !win.GetCursorPos(&p) { lastError("GetCursorPos") } actionId := uint16(win.TrackPopupMenuEx( ni.contextMenu.hMenu, win.TPM_NOANIMATION|win.TPM_RETURNCMD, p.X, p.Y, hwnd, nil)) if actionId != 0 { if action, ok := actionsById[actionId]; ok { action.raiseTriggered() } } return 0 case NIN_BALLOONUSERCLICK: ni.balloonClickedPublisher.Publish() } return win.DefWindowProc(hwnd, msg, wParam, lParam) }
func (tv *TableView) setSortIcon(index int, order SortOrder) error { headerHwnd := win.HWND(tv.SendMessage(win.LVM_GETHEADER, 0, 0)) idx := int(tv.toLVColIdx(index)) for i := range tv.visibleColumns() { item := win.HDITEM{ Mask: win.HDI_FORMAT, } iPtr := uintptr(i) itemPtr := uintptr(unsafe.Pointer(&item)) if win.SendMessage(headerHwnd, win.HDM_GETITEM, iPtr, itemPtr) == 0 { return newError("SendMessage(HDM_GETITEM)") } if i == idx { switch order { case SortAscending: item.Fmt &^= win.HDF_SORTDOWN item.Fmt |= win.HDF_SORTUP case SortDescending: item.Fmt &^= win.HDF_SORTUP item.Fmt |= win.HDF_SORTDOWN } } else { item.Fmt &^= win.HDF_SORTDOWN | win.HDF_SORTUP } if win.SendMessage(headerHwnd, win.HDM_SETITEM, iPtr, itemPtr) == 0 { return newError("SendMessage(HDM_SETITEM)") } } return nil }
func (tw *TabWidget) onRemovedPage(index int, page *TabPage) (err error) { err = tw.removePage(page) if err != nil { return } win.SendMessage(tw.hWndTab, win.TCM_DELETEITEM, uintptr(index), 0) if tw.pages.Len() > 0 { tw.currentIndex = 0 win.SendMessage(tw.hWndTab, win.TCM_SETCURSEL, uintptr(tw.currentIndex), 0) } else { tw.currentIndex = -1 } tw.onSelChange() return // FIXME: Either make use of this unreachable code or remove it. if index == tw.currentIndex { // removal of current visible tabpage... tw.currentIndex = -1 // select new tabpage if any : if tw.pages.Len() > 0 { // are we removing the rightmost page ? if index == tw.pages.Len()-1 { // If so, select the page on the left index -= 1 } } } tw.SetCurrentIndex(index) //tw.Invalidate() return }
func (tw *TabWidget) onSelChange() { pageCount := tw.pages.Len() if tw.currentIndex > -1 && tw.currentIndex < pageCount { page := tw.pages.At(tw.currentIndex) page.SetVisible(false) } tw.currentIndex = int(win.SendMessage(tw.hWndTab, win.TCM_GETCURSEL, 0, 0)) if tw.currentIndex > -1 && tw.currentIndex < pageCount { page := tw.pages.At(tw.currentIndex) page.SetVisible(true) page.Invalidate() } tw.currentIndexChangedPublisher.Publish() }
func (tw *TabWidget) imageIndex(image *Bitmap) (index int32, err error) { index = -1 if image != nil { if tw.imageList == nil { if tw.imageList, err = NewImageList(Size{16, 16}, 0); err != nil { return } win.SendMessage(tw.hWndTab, win.TCM_SETIMAGELIST, 0, uintptr(tw.imageList.hIml)) } // FIXME: Protect against duplicate insertion if index, err = tw.imageList.AddMasked(image); err != nil { return } } return }
func NewTabWidget(parent Container) (*TabWidget, error) { tw := &TabWidget{currentIndex: -1} tw.pages = newTabPageList(tw) if err := InitWidget( tw, parent, tabWidgetWindowClass, win.WS_VISIBLE, win.WS_EX_CONTROLPARENT); err != nil { return nil, err } succeeded := false defer func() { if !succeeded { tw.Dispose() } }() tw.SetPersistent(true) tw.hWndTab = win.CreateWindowEx( 0, syscall.StringToUTF16Ptr("SysTabControl32"), nil, win.WS_CHILD|win.WS_CLIPSIBLINGS|win.WS_TABSTOP|win.WS_VISIBLE, 0, 0, 0, 0, tw.hWnd, 0, 0, nil) if tw.hWndTab == 0 { return nil, lastError("CreateWindowEx") } win.SendMessage(tw.hWndTab, win.WM_SETFONT, uintptr(defaultFont.handleForDPI(0)), 1) setWindowFont(tw.hWndTab, tw.Font()) tw.MustRegisterProperty("HasCurrentPage", NewReadOnlyBoolProperty( func() bool { return tw.CurrentIndex() != -1 }, tw.CurrentIndexChanged())) succeeded = true return tw, nil }
func (tw *TabWidget) SetCurrentIndex(index int) error { if index == tw.currentIndex { return nil } if index < 0 || index >= tw.pages.Len() { return newError("invalid index") } ret := int(win.SendMessage(tw.hWndTab, win.TCM_SETCURSEL, uintptr(index), 0)) if ret == -1 { return newError("SendMessage(TCM_SETCURSEL) failed") } // FIXME: The SendMessage(TCM_SETCURSEL) call above doesn't cause a // TCN_SELCHANGE notification, so we use this workaround. tw.onSelChange() return nil }
func (tw *TabWidget) onInsertedPage(index int, page *TabPage) (err error) { item := tw.tcitemFromPage(page) if idx := int(win.SendMessage(tw.hWndTab, win.TCM_INSERTITEM, uintptr(index), uintptr(unsafe.Pointer(item)))); idx == -1 { return newError("SendMessage(TCM_INSERTITEM) failed") } page.SetVisible(false) style := uint32(win.GetWindowLong(page.hWnd, win.GWL_STYLE)) if style == 0 { return lastError("GetWindowLong") } style |= win.WS_CHILD style &^= win.WS_POPUP win.SetLastError(0) if win.SetWindowLong(page.hWnd, win.GWL_STYLE, int32(style)) == 0 { return lastError("SetWindowLong") } if win.SetParent(page.hWnd, tw.hWnd) == 0 { return lastError("SetParent") } if tw.pages.Len() == 1 { page.SetVisible(true) tw.SetCurrentIndex(0) } tw.resizePages() page.tabWidget = tw page.applyFont(tw.Font()) return }
func (tw *TabWidget) resizePages() { var r win.RECT if !win.GetWindowRect(tw.hWndTab, &r) { lastError("GetWindowRect") return } p := win.POINT{ r.Left, r.Top, } if !win.ScreenToClient(tw.hWnd, &p) { newError("ScreenToClient failed") return } r = win.RECT{ p.X, p.Y, r.Right - r.Left + p.X, r.Bottom - r.Top + p.Y, } win.SendMessage(tw.hWndTab, win.TCM_ADJUSTRECT, 0, uintptr(unsafe.Pointer(&r))) for _, page := range tw.pages.items { if err := page.SetBounds( Rectangle{ int(r.Left - 2), int(r.Top), int(r.Right - r.Left + 2), int(r.Bottom - r.Top), }); err != nil { return } } }
func windowText(hwnd win.HWND) string { textLength := win.SendMessage(hwnd, win.WM_GETTEXTLENGTH, 0, 0) buf := make([]uint16, textLength+1) win.SendMessage(hwnd, win.WM_GETTEXT, uintptr(textLength+1), uintptr(unsafe.Pointer(&buf[0]))) return syscall.UTF16ToString(buf) }
func setWindowFont(hwnd win.HWND, font *Font) { win.SendMessage(hwnd, win.WM_SETFONT, uintptr(font.handleForDPI(0)), 1) }
// SendMessage sends a message to the window and returns the result. func (wb *WindowBase) SendMessage(msg uint32, wParam, lParam uintptr) uintptr { return win.SendMessage(wb.hWnd, msg, wParam, lParam) }
func (dlg *FileDialog) ShowBrowseFolder(owner Form) (accepted bool, err error) { // Calling OleInitialize (or similar) is required for BIF_NEWDIALOGSTYLE. if hr := win.OleInitialize(); hr != win.S_OK && hr != win.S_FALSE { return false, newError(fmt.Sprint("OleInitialize Error: ", hr)) } defer win.OleUninitialize() pathFromPIDL := func(pidl uintptr) (string, error) { var path [win.MAX_PATH]uint16 if !win.SHGetPathFromIDList(pidl, &path[0]) { return "", newError("SHGetPathFromIDList failed") } return syscall.UTF16ToString(path[:]), nil } // We use this callback to disable the OK button in case of "invalid" // selections. callback := func(hwnd win.HWND, msg uint32, lp, wp uintptr) uintptr { const BFFM_SELCHANGED = 2 if msg == BFFM_SELCHANGED { _, err := pathFromPIDL(lp) var enabled uintptr if err == nil { enabled = 1 } const BFFM_ENABLEOK = win.WM_USER + 101 win.SendMessage(hwnd, BFFM_ENABLEOK, 0, enabled) } return 0 } var ownerHwnd win.HWND if owner != nil { ownerHwnd = owner.Handle() } // We need to put the initial path into a buffer of at least MAX_LENGTH // length, or we may get random crashes. var buf [win.MAX_PATH]uint16 copy(buf[:], syscall.StringToUTF16(dlg.InitialDirPath)) const BIF_NEWDIALOGSTYLE = 0x00000040 bi := win.BROWSEINFO{ HwndOwner: ownerHwnd, PszDisplayName: &buf[0], LpszTitle: syscall.StringToUTF16Ptr(dlg.Title), UlFlags: BIF_NEWDIALOGSTYLE, Lpfn: syscall.NewCallback(callback), } pidl := win.SHBrowseForFolder(&bi) if pidl == 0 { return false, nil } defer win.CoTaskMemFree(pidl) dlg.FilePath, err = pathFromPIDL(pidl) accepted = dlg.FilePath != "" return }
func (cw *CustomWidget) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { switch msg { case win.WM_PAINT: if cw.paint == nil { newError("paint func is nil") break } var ps win.PAINTSTRUCT var hdc win.HDC if wParam == 0 { hdc = win.BeginPaint(cw.hWnd, &ps) } else { hdc = win.HDC(wParam) } if hdc == 0 { newError("BeginPaint failed") break } defer func() { if wParam == 0 { win.EndPaint(cw.hWnd, &ps) } }() canvas, err := newCanvasFromHDC(hdc) if err != nil { newError("newCanvasFromHDC failed") break } defer canvas.Dispose() r := &ps.RcPaint bounds := Rectangle{ int(r.Left), int(r.Top), int(r.Right - r.Left), int(r.Bottom - r.Top), } if cw.paintMode == PaintBuffered { err = cw.bufferedPaint(canvas, bounds) } else { err = cw.paint(canvas, bounds) } if err != nil { newError("paint failed") break } return 0 case win.WM_ERASEBKGND: if cw.paintMode != PaintNormal { return 1 } case win.WM_PRINTCLIENT: win.SendMessage(hwnd, win.WM_PAINT, wParam, lParam) case win.WM_SIZE, win.WM_SIZING: if cw.invalidatesOnResize { cw.Invalidate() } } return cw.WidgetBase.WndProc(hwnd, msg, wParam, lParam) }