[v3 windows] Add HiDPI awareness

This commit is contained in:
stffabi 2023-05-02 09:39:13 +02:00 committed by Misite Bao
commit 75f0457375
4 changed files with 55 additions and 10 deletions

View file

@ -1,7 +1,6 @@
package application
import (
"github.com/samber/lo"
"log"
"net/http"
"os"
@ -9,6 +8,8 @@ import (
"strconv"
"sync"
"github.com/samber/lo"
"github.com/wailsapp/wails/v2/pkg/assetserver"
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
assetserveroptions "github.com/wailsapp/wails/v2/pkg/options/assetserver"
@ -16,6 +17,7 @@ import (
wailsruntime "github.com/wailsapp/wails/v3/internal/runtime"
"github.com/wailsapp/wails/v3/pkg/events"
"github.com/wailsapp/wails/v3/pkg/logger"
"github.com/wailsapp/wails/v3/pkg/w32"
)
var globalApplication *App
@ -33,6 +35,12 @@ func New(appOptions Options) *App {
return globalApplication
}
err := w32.SetProcessDPIAware()
if err != nil {
println("Fatal error in application initialisation: ", err.Error())
os.Exit(1)
}
mergeApplicationDefaults(&appOptions)
result := &App{

View file

@ -36,9 +36,9 @@ func (w *windowsWebviewWindow) setTitle(title string) {
}
func (w *windowsWebviewWindow) setSize(width, height int) {
x, y := w.position()
// TODO: Take scaling/DPI into consideration
w32.MoveWindow(w.hwnd, x, y, width, height, true)
rect := w32.GetWindowRect(w.hwnd)
width, height = w.scaleWithWindowDPI(width, height)
w32.MoveWindow(w.hwnd, int(rect.Left), int(rect.Top), width, height, true)
}
func (w *windowsWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
@ -206,7 +206,10 @@ func (w *windowsWebviewWindow) enableSizeConstraints() {
func (w *windowsWebviewWindow) size() (int, int) {
rect := w32.GetWindowRect(w.hwnd)
return int(rect.Right - rect.Left), int(rect.Bottom - rect.Top)
width := int(rect.Right - rect.Left)
height := int(rect.Bottom - rect.Top)
width, height = w.scaleToDefaultDPI(width, height)
return width, height
}
func (w *windowsWebviewWindow) setForeground() {
@ -218,18 +221,19 @@ func (w *windowsWebviewWindow) update() {
}
func (w *windowsWebviewWindow) width() int {
rect := w32.GetWindowRect(w.hwnd)
return int(rect.Right - rect.Left)
width, _ := w.size()
return width
}
func (w *windowsWebviewWindow) height() int {
rect := w32.GetWindowRect(w.hwnd)
return int(rect.Bottom - rect.Top)
_, height := w.size()
return height
}
func (w *windowsWebviewWindow) position() (int, int) {
rect := w32.GetWindowRect(w.hwnd)
return int(rect.Left), int(rect.Right)
left, right := w.scaleToDefaultDPI(int(rect.Left), int(rect.Right))
return left, right
}
func (w *windowsWebviewWindow) destroy() {
@ -293,6 +297,7 @@ func (w *windowsWebviewWindow) setHTML(html string) {
}
func (w *windowsWebviewWindow) setPosition(x int, y int) {
x, y = w.scaleWithWindowDPI(x, y)
info := w32.GetMonitorInfoForWindow(w.hwnd)
workRect := info.RcWork
w32.SetWindowPos(w.hwnd, w32.HWND_TOP, int(workRect.Left)+x, int(workRect.Top)+y, 0, 0, w32.SWP_NOSIZE)
@ -635,6 +640,16 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
if hasConstraints {
return 0
}
case w32.WM_DPICHANGED:
newWindowSize := (*w32.RECT)(unsafe.Pointer(lparam))
w32.SetWindowPos(w.hwnd,
uintptr(0),
int(newWindowSize.Left),
int(newWindowSize.Top),
int(newWindowSize.Right-newWindowSize.Left),
int(newWindowSize.Bottom-newWindowSize.Top),
w32.SWP_NOZORDER|w32.SWP_NOACTIVATE)
}
if options := w.parent.options; options.Frameless {
@ -743,10 +758,22 @@ func (w *windowsWebviewWindow) scaleWithWindowDPI(width, height int) (int, int)
return scaledWidth, scaledHeight
}
func (w *windowsWebviewWindow) scaleToDefaultDPI(width, height int) (int, int) {
dpix, dpiy := w.DPI()
scaledWidth := ScaleToDefaultDPI(width, dpix)
scaledHeight := ScaleToDefaultDPI(height, dpiy)
return scaledWidth, scaledHeight
}
func ScaleWithDPI(pixels int, dpi uint) int {
return (pixels * int(dpi)) / 96
}
func ScaleToDefaultDPI(pixels int, dpi uint) int {
return (pixels * 96) / int(dpi)
}
func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (w32.HICON, error) {
var err error
var result w32.HICON

View file

@ -552,6 +552,7 @@ const (
WM_MOUSEHOVER = 0x2A1
WM_MOUSELEAVE = 0x2A3
WM_CLIPBOARDUPDATE = 0x031D
WM_DPICHANGED = 0x02E0
)
// WM_ACTIVATE

View file

@ -130,6 +130,7 @@ var (
procGetMonitorInfo = moduser32.NewProc("GetMonitorInfoW")
procGetDpiForSystem = moduser32.NewProc("GetDpiForSystem")
procGetDpiForWindow = moduser32.NewProc("GetDpiForWindow")
procSetProcessDPIAware = moduser32.NewProc("SetProcessDPIAware")
procEnumDisplayMonitors = moduser32.NewProc("EnumDisplayMonitors")
procEnumDisplaySettingsEx = moduser32.NewProc("EnumDisplaySettingsExW")
procChangeDisplaySettingsEx = moduser32.NewProc("ChangeDisplaySettingsExW")
@ -303,6 +304,14 @@ func GetDpiForWindow(hwnd HWND) UINT {
return uint(dpi)
}
func SetProcessDPIAware() error {
status, r, err := procSetProcessDPIAware.Call()
if status == 0 {
return fmt.Errorf("SetProcessDPIAware failed %d: %v %v", status, r, err)
}
return nil
}
func GetForegroundWindow() HWND {
ret, _, _ := procGetForegroundWindow.Call()
return HWND(ret)