func (wb *WindowBase) dialogBaseUnits() Size { // The window may use a font different from that in WindowBase, // like e.g. NumberEdit does, so we try to use the right one. window := windowFromHandle(wb.hWnd) hdc := win.GetDC(wb.hWnd) defer win.ReleaseDC(wb.hWnd, hdc) hFont := window.Font().handleForDPI(0) hFontOld := win.SelectObject(hdc, win.HGDIOBJ(hFont)) defer win.SelectObject(hdc, win.HGDIOBJ(hFontOld)) var tm win.TEXTMETRIC if !win.GetTextMetrics(hdc, &tm) { newError("GetTextMetrics failed") } var size win.SIZE if !win.GetTextExtentPoint32( hdc, dialogBaseUnitsUTF16StringPtr, 52, &size) { newError("GetTextExtentPoint32 failed") } return Size{int((size.CX/26 + 1) / 2), int(tm.TmHeight)} }
// create an Alpha Icon or Cursor from an Image // http://support.microsoft.com/kb/318876 func createAlphaCursorOrIconFromImage(im image.Image, hotspot image.Point, fIcon bool) (win.HICON, error) { hBitmap, err := hBitmapFromImage(im) if err != nil { return 0, err } defer win.DeleteObject(win.HGDIOBJ(hBitmap)) // Create an empty mask bitmap. hMonoBitmap := win.CreateBitmap(int32(im.Bounds().Dx()), int32(im.Bounds().Dy()), 1, 1, nil) if hMonoBitmap == 0 { return 0, newError("CreateBitmap failed") } defer win.DeleteObject(win.HGDIOBJ(hMonoBitmap)) var ii win.ICONINFO if fIcon { ii.FIcon = win.TRUE } ii.XHotspot = uint32(hotspot.X) ii.YHotspot = uint32(hotspot.Y) ii.HbmMask = hMonoBitmap ii.HbmColor = hBitmap // Create the alpha cursor with the alpha DIB section. hIconOrCursor := win.CreateIconIndirect(&ii) return hIconOrCursor, nil }
func (le *LineEdit) initCharWidth() { font := le.Font() if font == le.charWidthFont { return } le.charWidthFont = font le.charWidth = 8 hdc := win.GetDC(le.hWnd) if hdc == 0 { newError("GetDC failed") return } defer win.ReleaseDC(le.hWnd, hdc) defer win.SelectObject(hdc, win.SelectObject(hdc, win.HGDIOBJ(font.handleForDPI(0)))) buf := []uint16{'M'} var s win.SIZE if !win.GetTextExtentPoint32(hdc, &buf[0], int32(len(buf)), &s) { newError("GetTextExtentPoint32 failed") return } le.charWidth = int(s.CX) }
func (wb *WindowBase) calculateTextSizeImpl(text string) Size { hdc := win.GetDC(wb.hWnd) if hdc == 0 { newError("GetDC failed") return Size{} } defer win.ReleaseDC(wb.hWnd, hdc) hFontOld := win.SelectObject(hdc, win.HGDIOBJ(wb.window.Font().handleForDPI(0))) defer win.SelectObject(hdc, hFontOld) var size Size lines := strings.Split(text, "\n") for _, line := range lines { var s win.SIZE str := syscall.StringToUTF16(strings.TrimRight(line, "\r ")) if !win.GetTextExtentPoint32(hdc, &str[0], int32(len(str)-1), &s) { newError("GetTextExtentPoint32 failed") return Size{} } size.Width = maxi(size.Width, int(s.CX)) size.Height += int(s.CY) } return size }
func newBitmapFromHBITMAP(hBmp win.HBITMAP) (bmp *Bitmap, err error) { var dib win.DIBSECTION if win.GetObject(win.HGDIOBJ(hBmp), unsafe.Sizeof(dib), unsafe.Pointer(&dib)) == 0 { return nil, newError("GetObject failed") } bmih := &dib.DsBmih bmihSize := uintptr(unsafe.Sizeof(*bmih)) pixelsSize := uintptr(int32(bmih.BiBitCount)*bmih.BiWidth*bmih.BiHeight) / 8 totalSize := uintptr(bmihSize + pixelsSize) hPackedDIB := win.GlobalAlloc(win.GHND, totalSize) dest := win.GlobalLock(hPackedDIB) defer win.GlobalUnlock(hPackedDIB) src := unsafe.Pointer(&dib.DsBmih) win.MoveMemory(dest, src, bmihSize) dest = unsafe.Pointer(uintptr(dest) + bmihSize) src = dib.DsBm.BmBits win.MoveMemory(dest, src, pixelsSize) return &Bitmap{ hBmp: hBmp, hPackedDIB: hPackedDIB, size: Size{ int(bmih.BiWidth), int(bmih.BiHeight), }, }, nil }
func (b *nullBrush) Dispose() { if b.hBrush != 0 { win.DeleteObject(win.HGDIOBJ(b.hBrush)) b.hBrush = 0 } }
func (b *SolidColorBrush) Dispose() { if b.hBrush != 0 { win.DeleteObject(win.HGDIOBJ(b.hBrush)) b.hBrush = 0 } }
func hPackedDIBFromHBITMAP(hBmp win.HBITMAP) (win.HGLOBAL, error) { var dib win.DIBSECTION if win.GetObject(win.HGDIOBJ(hBmp), unsafe.Sizeof(dib), unsafe.Pointer(&dib)) == 0 { return 0, newError("GetObject failed") } bmihSize := uintptr(unsafe.Sizeof(dib.DsBmih)) pixelsSize := uintptr( int32(dib.DsBmih.BiBitCount) * dib.DsBmih.BiWidth * dib.DsBmih.BiHeight) totalSize := bmihSize + pixelsSize hPackedDIB := win.GlobalAlloc(win.GHND, totalSize) dest := win.GlobalLock(hPackedDIB) defer win.GlobalUnlock(hPackedDIB) src := unsafe.Pointer(&dib.DsBmih) win.MoveMemory(dest, src, bmihSize) dest = unsafe.Pointer(uintptr(dest) + bmihSize) src = unsafe.Pointer(uintptr(src) + bmihSize) win.MoveMemory(dest, src, pixelsSize) return hPackedDIB, nil }
func (cb *ComboBox) calculateMaxItemTextWidth() int { hdc := win.GetDC(cb.hWnd) if hdc == 0 { newError("GetDC failed") return -1 } defer win.ReleaseDC(cb.hWnd, hdc) hFontOld := win.SelectObject(hdc, win.HGDIOBJ(cb.Font().handleForDPI(0))) defer win.SelectObject(hdc, hFontOld) var maxWidth int count := cb.model.ItemCount() for i := 0; i < count; i++ { var s win.SIZE str := syscall.StringToUTF16(cb.itemString(i)) if !win.GetTextExtentPoint32(hdc, &str[0], int32(len(str)-1), &s) { newError("GetTextExtentPoint32 failed") return -1 } maxWidth = maxi(maxWidth, int(s.CX)) } return maxWidth }
func (p *nullPen) Dispose() { if p.hPen != 0 { win.DeleteObject(win.HGDIOBJ(p.hPen)) p.hPen = 0 } }
func (p *GeometricPen) Dispose() { if p.hPen != 0 { win.DeleteObject(win.HGDIOBJ(p.hPen)) p.hPen = 0 } }
func (cw *CustomWidget) bufferedPaint(canvas *Canvas, updateBounds Rectangle) error { hdc := win.CreateCompatibleDC(canvas.hdc) if hdc == 0 { return newError("CreateCompatibleDC failed") } defer win.DeleteDC(hdc) buffered := Canvas{hdc: hdc, doNotDispose: true} if _, err := buffered.init(); err != nil { return err } w, h := int32(updateBounds.Width), int32(updateBounds.Height) if w < 1 { w = 1 } if h < 1 { h = 1 } hbmp := win.CreateCompatibleBitmap(canvas.hdc, w, h) if hbmp == 0 { return lastError("CreateCompatibleBitmap failed") } defer win.DeleteObject(win.HGDIOBJ(hbmp)) oldbmp := win.SelectObject(buffered.hdc, win.HGDIOBJ(hbmp)) if oldbmp == 0 { return newError("SelectObject failed") } defer win.SelectObject(buffered.hdc, oldbmp) win.SetViewportOrgEx(buffered.hdc, -int32(updateBounds.X), -int32(updateBounds.Y), nil) win.SetBrushOrgEx(buffered.hdc, -int32(updateBounds.X), -int32(updateBounds.Y), nil) err := cw.paint(&buffered, updateBounds) if !win.BitBlt(canvas.hdc, int32(updateBounds.X), int32(updateBounds.Y), w, h, buffered.hdc, int32(updateBounds.X), int32(updateBounds.Y), win.SRCCOPY) { return lastError("buffered BitBlt failed") } return err }
// Dispose releases the os resources that were allocated for the Font. // // The Font can no longer be used for drawing operations or with GUI widgets // after calling this method. It is safe to call Dispose multiple times. func (f *Font) Dispose() { for dpi, hFont := range f.dpi2hFont { if dpi != 0 { win.DeleteObject(win.HGDIOBJ(hFont)) } delete(f.dpi2hFont, dpi) } }
func (bmp *Bitmap) Dispose() { if bmp.hBmp != 0 { win.DeleteObject(win.HGDIOBJ(bmp.hBmp)) win.GlobalUnlock(bmp.hPackedDIB) win.GlobalFree(bmp.hPackedDIB) bmp.hPackedDIB = 0 bmp.hBmp = 0 } }
func (bmp *Bitmap) withSelectedIntoMemDC(f func(hdcMem win.HDC) error) error { return withCompatibleDC(func(hdcMem win.HDC) error { hBmpOld := win.SelectObject(hdcMem, win.HGDIOBJ(bmp.hBmp)) if hBmpOld == 0 { return newError("SelectObject failed") } defer win.SelectObject(hdcMem, hBmpOld) return f(hdcMem) }) }
func (c *Canvas) withFontAndTextColor(font *Font, color Color, f func() error) error { return c.withGdiObj(win.HGDIOBJ(font.handleForDPI(c.dpiy)), func() error { oldColor := win.SetTextColor(c.hdc, win.COLORREF(color)) if oldColor == win.CLR_INVALID { return newError("SetTextColor failed") } defer func() { win.SetTextColor(c.hdc, oldColor) }() return f() }) }
func (c *Canvas) MeasureText(text string, font *Font, bounds Rectangle, format DrawTextFormat) (boundsMeasured Rectangle, runesFitted int, err error) { // HACK: We don't want to actually draw on the Canvas here, but if we use // the DT_CALCRECT flag to avoid drawing, DRAWTEXTPARAMc.UiLengthDrawn will // not contain a useful value. To work around this, we create an in-memory // metafile and draw into that instead. if c.measureTextMetafile == nil { c.measureTextMetafile, err = NewMetafile(c) if err != nil { return } } hFont := win.HGDIOBJ(font.handleForDPI(c.dpiy)) oldHandle := win.SelectObject(c.measureTextMetafile.hdc, hFont) if oldHandle == 0 { err = newError("SelectObject failed") return } defer win.SelectObject(c.measureTextMetafile.hdc, oldHandle) rect := &win.RECT{ int32(bounds.X), int32(bounds.Y), int32(bounds.X + bounds.Width), int32(bounds.Y + bounds.Height), } var params win.DRAWTEXTPARAMS params.CbSize = uint32(unsafe.Sizeof(params)) strPtr := syscall.StringToUTF16Ptr(text) dtfmt := uint32(format) | win.DT_EDITCONTROL | win.DT_WORDBREAK height := win.DrawTextEx( c.measureTextMetafile.hdc, strPtr, -1, rect, dtfmt, ¶ms) if height == 0 { err = newError("DrawTextEx failed") return } boundsMeasured = Rectangle{ int(rect.Left), int(rect.Top), int(rect.Right - rect.Left), int(height), } runesFitted = int(params.UiLengthDrawn) return }
func NewCanvasFromImage(image Image) (*Canvas, error) { switch img := image.(type) { case *Bitmap: hdc := win.CreateCompatibleDC(0) if hdc == 0 { return nil, newError("CreateCompatibleDC failed") } succeeded := false defer func() { if !succeeded { win.DeleteDC(hdc) } }() if win.SelectObject(hdc, win.HGDIOBJ(img.hBmp)) == 0 { return nil, newError("SelectObject failed") } succeeded = true return (&Canvas{hdc: hdc}).init() case *Metafile: c, err := newCanvasFromHDC(img.hdc) if err != nil { return nil, err } c.recordingMetafile = img return c, nil } return nil, newError("unsupported image type") }
func hBitmapFromWindow(window Window) (win.HBITMAP, error) { hdcMem := win.CreateCompatibleDC(0) if hdcMem == 0 { return 0, newError("CreateCompatibleDC failed") } defer win.DeleteDC(hdcMem) var r win.RECT if !win.GetWindowRect(window.Handle(), &r) { return 0, newError("GetWindowRect failed") } hdc := win.GetDC(window.Handle()) width, height := r.Right-r.Left, r.Bottom-r.Top hBmp := win.CreateCompatibleBitmap(hdc, width, height) win.ReleaseDC(window.Handle(), hdc) hOld := win.SelectObject(hdcMem, win.HGDIOBJ(hBmp)) flags := win.PRF_CHILDREN | win.PRF_CLIENT | win.PRF_ERASEBKGND | win.PRF_NONCLIENT | win.PRF_OWNED window.SendMessage(win.WM_PRINT, uintptr(hdcMem), uintptr(flags)) win.SelectObject(hdcMem, hOld) return hBmp, nil }
func (c *Canvas) withPen(pen Pen, f func() error) error { return c.withGdiObj(win.HGDIOBJ(pen.handle()), f) }
func (c *Canvas) withBrush(brush Brush, f func() error) error { return c.withGdiObj(win.HGDIOBJ(brush.handle()), f) }