github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/winc/canvas.go (about) 1 //go:build windows 2 3 /* 4 * Copyright (C) 2019 The Winc Authors. All Rights Reserved. 5 * Copyright (C) 2010-2013 Allen Dang. All Rights Reserved. 6 */ 7 8 package winc 9 10 import ( 11 "fmt" 12 13 "github.com/secoba/wails/v2/internal/frontend/desktop/windows/winc/w32" 14 ) 15 16 type Canvas struct { 17 hwnd w32.HWND 18 hdc w32.HDC 19 doNotDispose bool 20 } 21 22 var nullBrush = NewNullBrush() 23 24 func NewCanvasFromHwnd(hwnd w32.HWND) *Canvas { 25 hdc := w32.GetDC(hwnd) 26 if hdc == 0 { 27 panic(fmt.Sprintf("Create canvas from %v failed.", hwnd)) 28 } 29 30 return &Canvas{hwnd: hwnd, hdc: hdc, doNotDispose: false} 31 } 32 33 func NewCanvasFromHDC(hdc w32.HDC) *Canvas { 34 if hdc == 0 { 35 panic("Cannot create canvas from invalid HDC.") 36 } 37 38 return &Canvas{hdc: hdc, doNotDispose: true} 39 } 40 41 func (ca *Canvas) Dispose() { 42 if !ca.doNotDispose && ca.hdc != 0 { 43 if ca.hwnd == 0 { 44 w32.DeleteDC(ca.hdc) 45 } else { 46 w32.ReleaseDC(ca.hwnd, ca.hdc) 47 } 48 49 ca.hdc = 0 50 } 51 } 52 53 func (ca *Canvas) DrawBitmap(bmp *Bitmap, x, y int) { 54 cdc := w32.CreateCompatibleDC(0) 55 defer w32.DeleteDC(cdc) 56 57 hbmpOld := w32.SelectObject(cdc, w32.HGDIOBJ(bmp.GetHBITMAP())) 58 defer w32.SelectObject(cdc, w32.HGDIOBJ(hbmpOld)) 59 60 w, h := bmp.Size() 61 62 w32.BitBlt(ca.hdc, x, y, w, h, cdc, 0, 0, w32.SRCCOPY) 63 } 64 65 func (ca *Canvas) DrawStretchedBitmap(bmp *Bitmap, rect *Rect) { 66 cdc := w32.CreateCompatibleDC(0) 67 defer w32.DeleteDC(cdc) 68 69 hbmpOld := w32.SelectObject(cdc, w32.HGDIOBJ(bmp.GetHBITMAP())) 70 defer w32.SelectObject(cdc, w32.HGDIOBJ(hbmpOld)) 71 72 w, h := bmp.Size() 73 74 rc := rect.GetW32Rect() 75 w32.StretchBlt(ca.hdc, int(rc.Left), int(rc.Top), int(rc.Right), int(rc.Bottom), cdc, 0, 0, w, h, w32.SRCCOPY) 76 } 77 78 func (ca *Canvas) DrawIcon(ico *Icon, x, y int) bool { 79 return w32.DrawIcon(ca.hdc, x, y, ico.Handle()) 80 } 81 82 // DrawFillRect draw and fill rectangle with color. 83 func (ca *Canvas) DrawFillRect(rect *Rect, pen *Pen, brush *Brush) { 84 w32Rect := rect.GetW32Rect() 85 86 previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) 87 defer w32.SelectObject(ca.hdc, previousPen) 88 89 previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(brush.GetHBRUSH())) 90 defer w32.SelectObject(ca.hdc, previousBrush) 91 92 w32.Rectangle(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) 93 } 94 95 func (ca *Canvas) DrawRect(rect *Rect, pen *Pen) { 96 w32Rect := rect.GetW32Rect() 97 98 previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) 99 defer w32.SelectObject(ca.hdc, previousPen) 100 101 // nullBrush is used to make interior of the rect transparent 102 previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(nullBrush.GetHBRUSH())) 103 defer w32.SelectObject(ca.hdc, previousBrush) 104 105 w32.Rectangle(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) 106 } 107 108 func (ca *Canvas) FillRect(rect *Rect, brush *Brush) { 109 w32.FillRect(ca.hdc, rect.GetW32Rect(), brush.GetHBRUSH()) 110 } 111 112 func (ca *Canvas) DrawEllipse(rect *Rect, pen *Pen) { 113 w32Rect := rect.GetW32Rect() 114 115 previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) 116 defer w32.SelectObject(ca.hdc, previousPen) 117 118 // nullBrush is used to make interior of the rect transparent 119 previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(nullBrush.GetHBRUSH())) 120 defer w32.SelectObject(ca.hdc, previousBrush) 121 122 w32.Ellipse(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) 123 } 124 125 // DrawFillEllipse draw and fill ellipse with color. 126 func (ca *Canvas) DrawFillEllipse(rect *Rect, pen *Pen, brush *Brush) { 127 w32Rect := rect.GetW32Rect() 128 129 previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) 130 defer w32.SelectObject(ca.hdc, previousPen) 131 132 previousBrush := w32.SelectObject(ca.hdc, w32.HGDIOBJ(brush.GetHBRUSH())) 133 defer w32.SelectObject(ca.hdc, previousBrush) 134 135 w32.Ellipse(ca.hdc, w32Rect.Left, w32Rect.Top, w32Rect.Right, w32Rect.Bottom) 136 } 137 138 func (ca *Canvas) DrawLine(x, y, x2, y2 int, pen *Pen) { 139 w32.MoveToEx(ca.hdc, x, y, nil) 140 141 previousPen := w32.SelectObject(ca.hdc, w32.HGDIOBJ(pen.GetHPEN())) 142 defer w32.SelectObject(ca.hdc, previousPen) 143 144 w32.LineTo(ca.hdc, int32(x2), int32(y2)) 145 } 146 147 // Refer win32 DrawText document for uFormat. 148 func (ca *Canvas) DrawText(text string, rect *Rect, format uint, font *Font, textColor Color) { 149 previousFont := w32.SelectObject(ca.hdc, w32.HGDIOBJ(font.GetHFONT())) 150 defer w32.SelectObject(ca.hdc, w32.HGDIOBJ(previousFont)) 151 152 previousBkMode := w32.SetBkMode(ca.hdc, w32.TRANSPARENT) 153 defer w32.SetBkMode(ca.hdc, previousBkMode) 154 155 previousTextColor := w32.SetTextColor(ca.hdc, w32.COLORREF(textColor)) 156 defer w32.SetTextColor(ca.hdc, previousTextColor) 157 158 w32.DrawText(ca.hdc, text, len(text), rect.GetW32Rect(), format) 159 }