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  }