From b331057ee7c3d2d1c42105ddfff0fbf3c772e7e9 Mon Sep 17 00:00:00 2001 From: Joshua Achorn Date: Fri, 18 Jan 2019 10:50:52 -0500 Subject: [PATCH 1/3] prevent Windows 7 crash caused by no shcore.dll --- internal/windows/shcoredll_windows.go | 26 ++++++++++++++++++++++++++ internal/windows/user32dll_windows.go | 2 ++ 2 files changed, 28 insertions(+) diff --git a/internal/windows/shcoredll_windows.go b/internal/windows/shcoredll_windows.go index 49a3fa6..c0d5ff8 100644 --- a/internal/windows/shcoredll_windows.go +++ b/internal/windows/shcoredll_windows.go @@ -14,9 +14,35 @@ var ( // GetDpiForMonitor https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulehandlew func GetDpiForMonitor(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error { + err := getDpiForMonitor.Find() + if err != nil { + return getDpiWindows7(monitor, dpiType, dpiX, dpiY) + } + ret, _, err := getDpiForMonitor.Call(uintptr(monitor), uintptr(dpiType), uintptr(unsafe.Pointer(dpiX)), uintptr(unsafe.Pointer(dpiY))) if ret != 0 { return errs.NewWithCause(getDpiForMonitor.Name, err) } return nil } + +// Windows 7 compatible function to mimic GetDpiForMonitor +func getDpiWindows7(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error { + overallX := 0 + overallY := 0 + + _hdc, _, _ := getDC.Call(uintptr(0)) + + hdc := HDC(_hdc) + + if hdc > 0 { + overallX = GetDeviceCaps(hdc, LOGPIXELSX) + overallY = GetDeviceCaps(hdc, LOGPIXELSY) + releaseDC.Call(uintptr(hdc)) + } + if overallX > 0 && overallY > 0 { + *dpiX = uint32(overallX) + *dpiY = uint32(overallY) + } + return nil +} diff --git a/internal/windows/user32dll_windows.go b/internal/windows/user32dll_windows.go index dd7a31b..8604755 100644 --- a/internal/windows/user32dll_windows.go +++ b/internal/windows/user32dll_windows.go @@ -27,6 +27,7 @@ var ( enumWindows = user32.NewProc("EnumWindows") getActiveWindow = user32.NewProc("GetActiveWindow") getClientRect = user32.NewProc("GetClientRect") + getDC = user32.NewProc("GetDC") getDpiForSystem = user32.NewProc("GetDpiForSystem") getFocus = user32.NewProc("GetFocus") getForegroundWindow = user32.NewProc("GetForegroundWindow") @@ -44,6 +45,7 @@ var ( postQuitMessage = user32.NewProc("PostQuitMessage") registerClassExW = user32.NewProc("RegisterClassExW") registerWindowMessageW = user32.NewProc("RegisterWindowMessageW") + releaseDC = user32.NewProc("ReleaseDC") setActiveWindow = user32.NewProc("SetActiveWindow") setFocus = user32.NewProc("SetFocus") setForegroundWindow = user32.NewProc("SetForegroundWindow") From 62430f0e8b697297d40328207192cfb3b956d2b8 Mon Sep 17 00:00:00 2001 From: Joshua Achorn Date: Fri, 18 Jan 2019 11:22:13 -0500 Subject: [PATCH 2/3] get DPI with physical monitor's device context --- internal/windows/displays_windows.go | 41 +++++++++++++++++++-------- internal/windows/shcoredll_windows.go | 23 +-------------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/internal/windows/displays_windows.go b/internal/windows/displays_windows.go index afb9727..c5e7457 100644 --- a/internal/windows/displays_windows.go +++ b/internal/windows/displays_windows.go @@ -19,19 +19,36 @@ func (d *driver) Displays() []*webapp.Display { var dpiX, dpiY uint32 if err = GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); err != nil { jot.Error(err) - } else { - d.Bounds.X = float64(info.MonitorBounds.Left) - d.Bounds.Y = float64(info.MonitorBounds.Top) - d.Bounds.Width = float64(info.MonitorBounds.Right - info.MonitorBounds.Left) - d.Bounds.Height = float64(info.MonitorBounds.Bottom - info.MonitorBounds.Top) - d.UsableBounds.X = float64(info.WorkBounds.Left) - d.UsableBounds.Y = float64(info.WorkBounds.Top) - d.UsableBounds.Width = float64(info.WorkBounds.Right - info.WorkBounds.Left) - d.UsableBounds.Height = float64(info.WorkBounds.Bottom - info.WorkBounds.Top) - d.ScalingFactor = float64(dpiX) / 96 - d.IsMain = info.Flags&MONITORINFOF_PRIMARY != 0 - result = append(result, d) + // Windows 7 fallback + overallX := 0 + overallY := 0 + + _hdc, _, _ := getDC.Call(uintptr(dc)) + + hdc := HDC(_hdc) + + if hdc > 0 { + overallX = GetDeviceCaps(hdc, LOGPIXELSX) + overallY = GetDeviceCaps(hdc, LOGPIXELSY) + releaseDC.Call(uintptr(hdc)) + } + if overallX > 0 && overallY > 0 { + dpiX = uint32(overallX) + dpiY = uint32(overallY) + } } + + d.Bounds.X = float64(info.MonitorBounds.Left) + d.Bounds.Y = float64(info.MonitorBounds.Top) + d.Bounds.Width = float64(info.MonitorBounds.Right - info.MonitorBounds.Left) + d.Bounds.Height = float64(info.MonitorBounds.Bottom - info.MonitorBounds.Top) + d.UsableBounds.X = float64(info.WorkBounds.Left) + d.UsableBounds.Y = float64(info.WorkBounds.Top) + d.UsableBounds.Width = float64(info.WorkBounds.Right - info.WorkBounds.Left) + d.UsableBounds.Height = float64(info.WorkBounds.Bottom - info.WorkBounds.Top) + d.ScalingFactor = float64(dpiX) / 96 + d.IsMain = info.Flags&MONITORINFOF_PRIMARY != 0 + result = append(result, d) } return 1 }, 0); err != nil { diff --git a/internal/windows/shcoredll_windows.go b/internal/windows/shcoredll_windows.go index c0d5ff8..c57880e 100644 --- a/internal/windows/shcoredll_windows.go +++ b/internal/windows/shcoredll_windows.go @@ -16,7 +16,7 @@ var ( func GetDpiForMonitor(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error { err := getDpiForMonitor.Find() if err != nil { - return getDpiWindows7(monitor, dpiType, dpiX, dpiY) + return err } ret, _, err := getDpiForMonitor.Call(uintptr(monitor), uintptr(dpiType), uintptr(unsafe.Pointer(dpiX)), uintptr(unsafe.Pointer(dpiY))) @@ -25,24 +25,3 @@ func GetDpiForMonitor(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error } return nil } - -// Windows 7 compatible function to mimic GetDpiForMonitor -func getDpiWindows7(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error { - overallX := 0 - overallY := 0 - - _hdc, _, _ := getDC.Call(uintptr(0)) - - hdc := HDC(_hdc) - - if hdc > 0 { - overallX = GetDeviceCaps(hdc, LOGPIXELSX) - overallY = GetDeviceCaps(hdc, LOGPIXELSY) - releaseDC.Call(uintptr(hdc)) - } - if overallX > 0 && overallY > 0 { - *dpiX = uint32(overallX) - *dpiY = uint32(overallY) - } - return nil -} From 57668bbe79dfe093b7bb2df58b339350aeadc1c5 Mon Sep 17 00:00:00 2001 From: Joshua Achorn Date: Fri, 18 Jan 2019 11:46:17 -0500 Subject: [PATCH 3/3] tidied up code --- internal/windows/displays_windows.go | 14 ++------------ internal/windows/shcoredll_windows.go | 2 +- internal/windows/user32dll_windows.go | 2 -- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/internal/windows/displays_windows.go b/internal/windows/displays_windows.go index c5e7457..0f0febb 100644 --- a/internal/windows/displays_windows.go +++ b/internal/windows/displays_windows.go @@ -18,20 +18,10 @@ func (d *driver) Displays() []*webapp.Display { } else { var dpiX, dpiY uint32 if err = GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); err != nil { - jot.Error(err) // Windows 7 fallback - overallX := 0 - overallY := 0 + overallX := GetDeviceCaps(dc, LOGPIXELSX) + overallY := GetDeviceCaps(dc, LOGPIXELSY) - _hdc, _, _ := getDC.Call(uintptr(dc)) - - hdc := HDC(_hdc) - - if hdc > 0 { - overallX = GetDeviceCaps(hdc, LOGPIXELSX) - overallY = GetDeviceCaps(hdc, LOGPIXELSY) - releaseDC.Call(uintptr(hdc)) - } if overallX > 0 && overallY > 0 { dpiX = uint32(overallX) dpiY = uint32(overallY) diff --git a/internal/windows/shcoredll_windows.go b/internal/windows/shcoredll_windows.go index c57880e..b42589b 100644 --- a/internal/windows/shcoredll_windows.go +++ b/internal/windows/shcoredll_windows.go @@ -16,7 +16,7 @@ var ( func GetDpiForMonitor(monitor HMONITOR, dpiType int32, dpiX, dpiY *uint32) error { err := getDpiForMonitor.Find() if err != nil { - return err + return errs.NewWithCause(getDpiForMonitor.Name, err) } ret, _, err := getDpiForMonitor.Call(uintptr(monitor), uintptr(dpiType), uintptr(unsafe.Pointer(dpiX)), uintptr(unsafe.Pointer(dpiY))) diff --git a/internal/windows/user32dll_windows.go b/internal/windows/user32dll_windows.go index 8604755..dd7a31b 100644 --- a/internal/windows/user32dll_windows.go +++ b/internal/windows/user32dll_windows.go @@ -27,7 +27,6 @@ var ( enumWindows = user32.NewProc("EnumWindows") getActiveWindow = user32.NewProc("GetActiveWindow") getClientRect = user32.NewProc("GetClientRect") - getDC = user32.NewProc("GetDC") getDpiForSystem = user32.NewProc("GetDpiForSystem") getFocus = user32.NewProc("GetFocus") getForegroundWindow = user32.NewProc("GetForegroundWindow") @@ -45,7 +44,6 @@ var ( postQuitMessage = user32.NewProc("PostQuitMessage") registerClassExW = user32.NewProc("RegisterClassExW") registerWindowMessageW = user32.NewProc("RegisterWindowMessageW") - releaseDC = user32.NewProc("ReleaseDC") setActiveWindow = user32.NewProc("SetActiveWindow") setFocus = user32.NewProc("SetFocus") setForegroundWindow = user32.NewProc("SetForegroundWindow")