summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Krauter <simon.krauter@dbaudio.com>2019-07-26 10:27:00 +0200
committerSimon Krauter <simon.krauter@dbaudio.com>2019-07-26 10:27:00 +0200
commit6a39cee5037f0ca7ceaea499967efa456fb8f4b1 (patch)
treeda1a2da4c19545c9328a2fabcf5b84a5157831c4 /src
parentbb09bfa401fd8bf435ebbde844a3ba765b153a05 (diff)
downloadNiGui-6a39cee5037f0ca7ceaea499967efa456fb8f4b1.tar.gz
NiGui-6a39cee5037f0ca7ceaea499967efa456fb8f4b1.zip
Implemented High-DPI support for Windows.
Applications should use ``scaleToDpi()`` to convert pixel numbers from 96 DPI to system DPI.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/nigui.nim49
-rwxr-xr-xsrc/nigui/msgbox.nim10
-rwxr-xr-xsrc/nigui/private/windows/platform_impl.nim7
-rwxr-xr-xsrc/nigui/private/windows/windows.nim13
4 files changed, 52 insertions, 27 deletions
diff --git a/src/nigui.nim b/src/nigui.nim
index a318ea4..6a4551c 100755
--- a/src/nigui.nim
+++ b/src/nigui.nim
@@ -383,6 +383,9 @@ proc isDown*(key: Key): bool
proc downKeys*(): seq[Key]
+proc scaleToDpi*(val: int): int
+proc scaleToDpi*(val: float): float
+
# ----------------------------------------------------------------------------------------
# Dialogs
@@ -924,17 +927,22 @@ import unicode
# Global Variables
# ----------------------------------------------------------------------------------------
+const
+ defaultDpi = 96
+ defaultFontSizeForDefaultDpi = 12.0
+
var
fErrorHandler: ErrorHandlerProc = nil
windowList: seq[Window] = @[]
fScrollbarSize = -1
fDownKeys: seq[Key] = @[]
-
+ fSystemDpi = defaultDpi
+
# Default style:
fDefaultBackgroundColor: Color # initialized by platform-specific init()
fDefaultTextColor: Color # initialized by platform-specific init()
fDefaultFontFamily = ""
- fDefaultFontSize = 15.float
+ fDefaultFontSize = defaultFontSizeForDefaultDpi
# ----------------------------------------------------------------------------------------
@@ -1056,6 +1064,9 @@ proc isDown(key: Key): bool = fDownKeys.contains(key)
proc downKeys(): seq[Key] = fDownKeys
+proc scaleToDpi(val: int): int = (val * fSystemDpi) div defaultDpi
+proc scaleToDpi(val: float): float = val * fSystemDpi.float / defaultDpi.float
+
proc internalKeyDown(key: Key) =
if not fDownKeys.contains(key):
fDownKeys.add(key)
@@ -1365,8 +1376,8 @@ proc init(control: Control) =
control.tag = ""
control.fWidthMode = WidthMode_Static
control.fHeightMode = HeightMode_Static
- control.fWidth = 50
- control.fheight = 50
+ control.fWidth = 50.scaleToDpi
+ control.fheight = 50.scaleToDpi
control.fScrollableWidth = -1
control.fScrollableHeight = -1
control.resetFontFamily()
@@ -1648,7 +1659,7 @@ method setFontSize(control: Control, fontSize: float) =
# should be extended by ControlImpl
method resetFontSize(control: Control) =
- control.setFontSize(fDefaultFontSize)
+ control.setFontSize(app.defaultFontSize)
control.fUseDefaultFontSize = true
control.triggerRelayoutIfModeIsAuto()
@@ -1922,8 +1933,8 @@ proc newLayoutContainer(layout: Layout): LayoutContainer =
result.layout = layout
result.xAlign = XAlign_Left
result.yAlign = YAlign_Top
- result.spacing = 4
- result.padding = 2
+ result.spacing = 4.scaleToDpi
+ result.padding = 2.scaleToDpi
method naturalWidth(container: LayoutContainer): int =
# echo container.tag & ".naturalWidth"
@@ -2232,10 +2243,10 @@ method `text=`(frame: Frame, text: string) =
# should be extended by NativeFrame
method getPadding(frame: Frame): Spacing =
- result.left = 4
- result.right = 4
- result.top = 4
- result.bottom = 4
+ result.left = 4.scaleToDpi
+ result.right = 4.scaleToDpi
+ result.top = 4.scaleToDpi
+ result.bottom = 4.scaleToDpi
# should be extended by NativeFrame
method `onDraw=`(container: NativeFrame, callback: DrawProc) = raiseError("NativeFrame does not allow onDraw.")
@@ -2256,8 +2267,8 @@ proc init(button: Button) =
button.fOnClick = nil
button.fWidthMode = WidthMode_Auto
button.fHeightMode = HeightMode_Auto
- button.minWidth = 15
- button.minHeight = 15
+ button.minWidth = 15.scaleToDpi
+ button.minHeight = 15.scaleToDpi
button.enabled = true
method text(button: Button): string = button.fText
@@ -2302,8 +2313,8 @@ proc init(label: Label) =
label.fText = ""
label.fWidthMode = WidthMode_Auto
label.fHeightMode = HeightMode_Auto
- label.minWidth = 10
- label.minHeight = 10
+ label.minWidth = 10.scaleToDpi
+ label.minHeight = 10.scaleToDpi
method text(label: Label): string = label.fText
@@ -2333,8 +2344,8 @@ proc init(textBox: TextBox) =
textBox.ControlImpl.init()
textBox.fWidthMode = WidthMode_Expand
textBox.fHeightMode = HeightMode_Auto
- textBox.minWidth = 20
- textBox.minHeight = 20
+ textBox.minWidth = 20.scaleToDpi
+ textBox.minHeight = 20.scaleToDpi
textBox.editable = true
method naturalHeight(textBox: TextBox): int = textBox.getTextLineHeight()
@@ -2393,8 +2404,8 @@ proc init(textArea: TextArea) =
textArea.ControlImpl.init()
textArea.fWidthMode = WidthMode_Expand
textArea.fHeightMode = HeightMode_Expand
- textArea.minWidth = 20
- textArea.minHeight = 20
+ textArea.minWidth = 20.scaleToDpi
+ textArea.minHeight = 20.scaleToDpi
textArea.wrap = true
textArea.editable = true
diff --git a/src/nigui/msgbox.nim b/src/nigui/msgbox.nim
index eefb57a..596fb12 100755
--- a/src/nigui/msgbox.nim
+++ b/src/nigui/msgbox.nim
@@ -22,7 +22,7 @@ proc buttonClick(event: ClickEvent) =
event.control.parentWindow.dispose()
proc msgBox*(parent: Window, message: string, title = "Message", button1 = "OK", button2, button3: string = ""): int {.discardable.} =
- const buttonMinWidth = 100
+ const buttonMinWidth = 100.scaleToDpi
var window = new MessageBoxWindow
window.init()
window.title = title
@@ -32,7 +32,7 @@ proc msgBox*(parent: Window, message: string, title = "Message", button1 = "OK",
window.dispose()
var container = newLayoutContainer(Layout_Vertical)
- container.padding = 10
+ container.padding = 10.scaleToDpi
window.control = container
var labelContainer = newLayoutContainer(Layout_Horizontal)
@@ -46,7 +46,7 @@ proc msgBox*(parent: Window, message: string, title = "Message", button1 = "OK",
var buttonContainer = newLayoutContainer(Layout_Horizontal)
buttonContainer.widthMode = WidthMode_Expand
buttonContainer.xAlign = XAlign_Center
- buttonContainer.spacing = 12
+ buttonContainer.spacing = 12.scaleToDpi
container.add(buttonContainer)
var b1, b2, b3: Button
@@ -68,8 +68,8 @@ proc msgBox*(parent: Window, message: string, title = "Message", button1 = "OK",
b3.onClick = buttonClick
buttonContainer.add(b3)
- window.width = min(max(label.width + 40, buttonMinWidth * 3 + 65), 600)
- window.height = min(label.height, 300) + buttonContainer.height + 70
+ window.width = min(max(label.width + 40.scaleToDpi, buttonMinWidth * 3 + 65.scaleToDpi), 600.scaleToDpi)
+ window.height = min(label.height, 300.scaleToDpi) + buttonContainer.height + 70.scaleToDpi
# Center message box on window:
window.x = parent.x + ((parent.width - window.width) div 2)
diff --git a/src/nigui/private/windows/platform_impl.nim b/src/nigui/private/windows/platform_impl.nim
index a84ffbd..6a04c46 100755
--- a/src/nigui/private/windows/platform_impl.nim
+++ b/src/nigui/private/windows/platform_impl.nim
@@ -17,7 +17,6 @@ import tables
const pTopLevelWindowClass = "1"
const pContainerWindowClass = "2"
const pCustomControlWindowClass = "3"
-
var pDefaultParentWindow: pointer
var pKeyState: KeyState
var pKeyDownKey: Key
@@ -37,7 +36,7 @@ proc pCheckGdiplusStatus(status: int32, showAlert = true) =
pRaiseLastOSError(showAlert)
else:
raiseError("A GDI+ error occured. (Status: " & $status & ")", showAlert)
-
+
proc pColorToRGB32(color: Color): RGB32 =
result.red = color.red
result.green = color.green
@@ -379,6 +378,10 @@ proc init(app: App) =
app.defaultBackgroundColor = GetSysColor(COLOR_BTNFACE).pRgb32ToColor()
app.defaultFontFamily = "Arial"
fScrollbarSize = GetSystemMetrics(SM_CXVSCROLL)
+ # High DPI support:
+ discard SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE)
+ fSystemDpi = GetDpiForWindow(pDefaultParentWindow)
+ fDefaultFontSize = defaultFontSizeForDefaultDpi.scaleToDpi
proc runMainLoop() =
var msg: Msg
diff --git a/src/nigui/private/windows/windows.nim b/src/nigui/private/windows/windows.nim
index f35e603..e43bc56 100755
--- a/src/nigui/private/windows/windows.nim
+++ b/src/nigui/private/windows/windows.nim
@@ -24,6 +24,7 @@
{.pragma: libShell32, stdcall, dynlib: "Shell32.dll".}
{.pragma: libGdiplus, stdcall, dynlib: "Gdiplus.dll".}
{.pragma: libComdlg32, stdcall, dynlib: "Comdlg32.dll".}
+{.pragma: libShcore, stdcall, dynlib: "Shcore.dll".}
# ----------------------------------------------------------------------------------------
@@ -190,7 +191,9 @@ const
PixelFormat32bppARGB* = 2498570
ImageLockModeWrite* = 2
MAPVK_VSC_TO_VK_EX* = 3
-
+ PROCESS_DPI_UNAWARE* = 0
+ PROCESS_SYSTEM_DPI_AWARE* = 1
+ PROCESS_PER_MONITOR_DPI_AWARE* = 2
# ----------------------------------------------------------------------------------------
@@ -428,6 +431,7 @@ proc GetClipboardData*(uFormat: int32): pointer {.importc: "GetClipboardData", l
proc SetClipboardData*(uFormat: int32, hMem: pointer): pointer {.importc: "SetClipboardData", libUser32.}
proc EmptyClipboard*(): bool {.importc: "EmptyClipboard", libUser32.}
proc MapVirtualKeyW*(uCode, uMapType: int32): int32 {.importc: "MapVirtualKeyW", libUser32.}
+proc GetDpiForWindow*(hWnd: pointer): int32 {.importc: "GetDpiForWindow", libUser32.}
when defined(cpu64):
# Only available on 64-bit Windows:
@@ -523,3 +527,10 @@ proc CommDlgExtendedError*(): int32 {.importc: "CommDlgExtendedError", libComdlg
proc GetOpenFileNameW*(lpofn: var OpenFileName): bool {.importc: "GetOpenFileNameW", libComdlg32.}
proc GetSaveFileNameW*(lpofn: var OpenFileName): bool {.importc: "GetSaveFileNameW", libComdlg32.}
+
+# ----------------------------------------------------------------------------------------
+# Comdlg32 Procs
+# ----------------------------------------------------------------------------------------
+
+proc SetProcessDpiAwareness*(value: int32): int32 {.importc: "SetProcessDpiAwareness", libShcore.}
+