diff options
author | Alexander Neumann <alexander.neumann@picos-software.com> | 2019-05-07 11:55:35 +0200 |
---|---|---|
committer | Alexander Neumann <alexander.neumann@picos-software.com> | 2019-05-07 11:55:35 +0200 |
commit | c5be165f31cdc19dceb1ad0729a8d9d4a46ae073 (patch) | |
tree | 3708b7cf089f57e3ddadadc0c8eedc4d9f6958a0 | |
parent | Merge branch 'master' of github.com:lxn/walk (diff) | |
download | wireguard-windows-c5be165f31cdc19dceb1ad0729a8d9d4a46ae073.tar.xz wireguard-windows-c5be165f31cdc19dceb1ad0729a8d9d4a46ae073.zip |
More work on multi monitor HIDPI
-rw-r--r-- | boxlayout.go | 4 | ||||
-rw-r--r-- | brush.go | 2 | ||||
-rw-r--r-- | container.go | 10 | ||||
-rw-r--r-- | declarative/dialog.go | 4 | ||||
-rw-r--r-- | declarative/mainwindow.go | 4 | ||||
-rw-r--r-- | dialog.go | 8 | ||||
-rw-r--r-- | flowlayout.go | 4 | ||||
-rw-r--r-- | form.go | 32 | ||||
-rw-r--r-- | gradientcomposite.go | 4 | ||||
-rw-r--r-- | graphicseffects.go | 4 | ||||
-rw-r--r-- | gridlayout.go | 4 | ||||
-rw-r--r-- | groupbox.go | 10 | ||||
-rw-r--r-- | imageview.go | 2 | ||||
-rw-r--r-- | lineerrorpresenter.go | 4 | ||||
-rw-r--r-- | mainwindow.go | 16 | ||||
-rw-r--r-- | numberedit.go | 4 | ||||
-rw-r--r-- | scrollview.go | 28 | ||||
-rw-r--r-- | splitter.go | 33 | ||||
-rw-r--r-- | splitterlayout.go | 14 | ||||
-rw-r--r-- | static.go | 6 | ||||
-rw-r--r-- | statusbar.go | 8 | ||||
-rw-r--r-- | tableview.go | 4 | ||||
-rw-r--r-- | tableviewcolumn.go | 9 | ||||
-rw-r--r-- | tabwidget.go | 15 | ||||
-rw-r--r-- | textlabel.go | 2 | ||||
-rw-r--r-- | toolbar.go | 4 | ||||
-rw-r--r-- | tooltip.go | 2 | ||||
-rw-r--r-- | webview.go | 2 | ||||
-rw-r--r-- | webview_dwebbrowserevents2.go | 9 | ||||
-rw-r--r-- | widget.go | 14 | ||||
-rw-r--r-- | window.go | 205 |
31 files changed, 315 insertions, 156 deletions
diff --git a/boxlayout.go b/boxlayout.go index ce08199f..6c2f73bd 100644 --- a/boxlayout.go +++ b/boxlayout.go @@ -163,7 +163,7 @@ func (l *BoxLayout) MinSize() Size { return Size{} } - return l.MinSizeForSize(l.container.ClientBounds().Size()) + return l.MinSizeForSize(l.container.ClientBoundsPixels().Size()) } func (l *BoxLayout) MinSizeForSize(size Size) Size { @@ -251,7 +251,7 @@ func (l *BoxLayout) Update(reset bool) error { ifContainerIsScrollViewDoCoolSpecialLayoutStuff(l) - items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, l.container.ClientBounds(), l.margins, l.spacing, l.hwnd2StretchFactor) + items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, l.container.ClientBoundsPixels(), l.margins, l.spacing, l.hwnd2StretchFactor) if err != nil { return err } @@ -413,7 +413,7 @@ func (b *GradientBrush) attachWindow(wb *WindowBase) { var info *windowBrushInfo update := func() { - if bb, err := b.create(wb.window.ClientBounds().Size()); err == nil { + if bb, err := b.create(wb.window.ClientBoundsPixels().Size()); err == nil { if info.Delegate != nil { info.Delegate.bitmap.Dispose() info.Delegate.Dispose() diff --git a/container.go b/container.go index 64d7b791..de1f9966 100644 --- a/container.go +++ b/container.go @@ -61,13 +61,13 @@ func performScheduledLayouts() { if formResizeScheduled { formResizeScheduled = false - bounds := appSingleton.activeForm.Bounds() + bounds := appSingleton.activeForm.BoundsPixels() if appSingleton.activeForm.AsFormBase().fixedSize() { bounds.Width, bounds.Height = 0, 0 } - appSingleton.activeForm.SetBounds(bounds) + appSingleton.activeForm.SetBoundsPixels(bounds) } else { for _, layout := range layouts { if widget, ok := layout.Container().(Widget); ok && widget.Form() != appSingleton.activeForm { @@ -246,7 +246,7 @@ func applyLayoutResults(container Container, items []layoutResultItem) error { widget := item.widget x, y, w, h := item.bounds.X, item.bounds.Y, item.bounds.Width, item.bounds.Height - b := widget.Bounds() + b := widget.BoundsPixels() if b.X == x && b.Y == y && b.Width == w { if _, ok := widget.(*ComboBox); ok { @@ -595,7 +595,7 @@ func (cb *ContainerBase) doPaint() error { continue } - b := widget.Bounds().toRECT() + b := widget.BoundsPixels().toRECT() win.ExcludeClipRect(hdc, b.Left, b.Top, b.Right, b.Bottom) if err := effect.Draw(widget, canvas); err != nil { @@ -620,7 +620,7 @@ func (cb *ContainerBase) doPaint() error { if widget != nil && widget.Parent() != nil && widget.Parent().Handle() == cb.hWnd { for _, effect := range widget.GraphicsEffects().items { if effect == FocusEffect { - b := widget.Bounds().toRECT() + b := widget.BoundsPixels().toRECT() win.ExcludeClipRect(hdc, b.Left, b.Top, b.Right, b.Bottom) if err := FocusEffect.Draw(widget, canvas); err != nil { diff --git a/declarative/dialog.go b/declarative/dialog.go index a42edb3f..87590f4f 100644 --- a/declarative/dialog.go +++ b/declarative/dialog.go @@ -116,7 +116,7 @@ func (d Dialog) Create(owner walk.Form) error { w.SetSuspended(true) builder.Defer(func() error { w.SetSuspended(false) - w.SetBounds(w.Bounds()) + w.SetBoundsPixels(w.BoundsPixels()) return nil }) @@ -125,7 +125,7 @@ func (d Dialog) Create(owner walk.Form) error { } return builder.InitWidget(fi, w, func() error { - if err := w.SetSize(d.Size.toW()); err != nil { + if err := w.SetSizePixels(d.Size.toW()); err != nil { return err } diff --git a/declarative/mainwindow.go b/declarative/mainwindow.go index cb967701..f483564b 100644 --- a/declarative/mainwindow.go +++ b/declarative/mainwindow.go @@ -103,7 +103,7 @@ func (mw MainWindow) Create() error { w.SetSuspended(true) builder.Defer(func() error { w.SetSuspended(false) - w.SetBounds(w.Bounds()) + w.SetBoundsPixels(w.BoundsPixels()) return nil }) @@ -149,7 +149,7 @@ func (mw MainWindow) Create() error { w.StatusBar().SetVisible(true) } - if err := w.SetSize(mw.Size.toW()); err != nil { + if err := w.SetSizePixels(mw.Size.toW()); err != nil { return err } @@ -162,13 +162,13 @@ func (dlg *Dialog) Show() { size.Width = maxi(size.Width, min.Width) size.Height = maxi(size.Height, min.Height) } else { - size = dlg.Size() + size = dlg.SizePixels() } - ob := dlg.owner.Bounds() + ob := dlg.owner.BoundsPixels() if dlg.centerInOwnerWhenRun { - dlg.SetBounds(fitRectToScreen(dlg.hWnd, Rectangle{ + dlg.SetBoundsPixels(fitRectToScreen(dlg.hWnd, Rectangle{ ob.X + (ob.Width-size.Width)/2, ob.Y + (ob.Height-size.Height)/2, size.Width, @@ -176,7 +176,7 @@ func (dlg *Dialog) Show() { })) } } else { - dlg.SetBounds(dlg.Bounds()) + dlg.SetBoundsPixels(dlg.BoundsPixels()) } dlg.FormBase.Show() diff --git a/flowlayout.go b/flowlayout.go index 6292e281..db6d912a 100644 --- a/flowlayout.go +++ b/flowlayout.go @@ -90,7 +90,7 @@ func (l *FlowLayout) MinSize() Size { return Size{} } - return l.MinSizeForSize(l.container.ClientBounds().Size()) + return l.MinSizeForSize(l.container.ClientBoundsPixels().Size()) } func (l *FlowLayout) MinSizeForSize(size Size) Size { @@ -195,7 +195,7 @@ func (l *FlowLayout) Update(reset bool) error { ifContainerIsScrollViewDoCoolSpecialLayoutStuff(l) - bounds := l.container.ClientBounds() + bounds := l.container.ClientBoundsPixels() sections := l.sectionsForPrimarySize(bounds.Width) for i, section := range sections { @@ -200,9 +200,9 @@ func (fb *FormBase) SetLayout(value Layout) error { return fb.clientComposite.SetLayout(value) } -func (fb *FormBase) SetBounds(bounds Rectangle) error { +func (fb *FormBase) SetBoundsPixels(bounds Rectangle) error { if layout := fb.Layout(); layout != nil { - minSize := fb.sizeFromClientSize(layout.MinSizeForSize(fb.clientComposite.Size())) + minSize := fb.sizeFromClientSizePixels(layout.MinSizeForSize(fb.clientComposite.SizePixels())) if bounds.Width < minSize.Width { bounds.Width = minSize.Width @@ -212,7 +212,7 @@ func (fb *FormBase) SetBounds(bounds Rectangle) error { } } - if err := fb.WindowBase.SetBounds(bounds); err != nil { + if err := fb.WindowBase.SetBoundsPixels(bounds); err != nil { return err } @@ -270,10 +270,10 @@ func (fb *FormBase) onInsertedWidget(index int, widget Widget) error { if err == nil { if layout := fb.Layout(); layout != nil && !fb.Suspended() { minClientSize := fb.Layout().MinSize() - clientSize := fb.clientComposite.Size() + clientSize := fb.clientComposite.SizePixels() if clientSize.Width < minClientSize.Width || clientSize.Height < minClientSize.Height { - fb.SetClientSize(minClientSize) + fb.SetClientSizePixels(minClientSize) } } } @@ -376,7 +376,7 @@ func (fb *FormBase) Run() int { fb.started = true fb.startingPublisher.Publish() - fb.SetBounds(fb.Bounds()) + fb.SetBoundsPixels(fb.BoundsPixels()) // Some widgets perform weird scrolling stunts, when initially focused. // We try to fix that here and hope for the best. @@ -602,7 +602,7 @@ func (fb *FormBase) RestoreState() error { wp.Length = uint32(unsafe.Sizeof(wp)) if layout := fb.Layout(); layout != nil && fb.fixedSize() { - minSize := fb.sizeFromClientSize(layout.MinSize()) + minSize := fb.sizeFromClientSizePixels(layout.MinSize()) wp.RcNormalPosition.Right = wp.RcNormalPosition.Left + int32(minSize.Width) - 1 wp.RcNormalPosition.Bottom = wp.RcNormalPosition.Top + int32(minSize.Height) - 1 @@ -674,11 +674,11 @@ func (fb *FormBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) u var min Size if layout := fb.clientComposite.layout; layout != nil { - size := fb.clientSizeFromSize(fb.proposedSize) - min = fb.sizeFromClientSize(layout.MinSizeForSize(size)) + size := fb.clientSizeFromSizePixels(fb.proposedSize) + min = fb.sizeFromClientSizePixels(layout.MinSizeForSize(size)) if fb.proposedSize.Width < min.Width { - min = fb.sizeFromClientSize(layout.MinSizeForSize(min)) + min = fb.sizeFromClientSizePixels(layout.MinSizeForSize(min)) } } @@ -699,21 +699,23 @@ func (fb *FormBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) u fb.proposedSize = rectangleFromRECT(*rc).Size() - fb.clientComposite.SetBounds(fb.window.ClientBounds()) + fb.clientComposite.SetBoundsPixels(fb.window.ClientBoundsPixels()) case win.WM_SIZE: - fb.clientComposite.SetBounds(fb.window.ClientBounds()) + fb.clientComposite.SetBoundsPixels(fb.window.ClientBoundsPixels()) case win.WM_DPICHANGED: wasSuspended := fb.Suspended() fb.SetSuspended(true) defer fb.SetSuspended(wasSuspended) - rc := (*win.RECT)(unsafe.Pointer(lParam)) - fb.window.SetBounds(rectangleFromRECT(*rc)) - fb.ApplyDPI(int(win.HIWORD(uint32(wParam)))) + applyDPIToDescendants(fb.window, int(win.HIWORD(uint32(wParam)))) + + rc := (*win.RECT)(unsafe.Pointer(lParam)) + fb.window.SetBoundsPixels(rectangleFromRECT(*rc)) + case win.WM_SYSCOMMAND: if wParam == win.SC_CLOSE { fb.closeReason = CloseReasonUser diff --git a/gradientcomposite.go b/gradientcomposite.go index 54642b32..5a6c22ba 100644 --- a/gradientcomposite.go +++ b/gradientcomposite.go @@ -194,7 +194,7 @@ func (gc *GradientComposite) SetColor2(c Color) (err error) { } func (gc *GradientComposite) updateBackground() error { - bounds := gc.ClientBounds() + bounds := gc.ClientBoundsPixels() if bounds.Width < 1 || bounds.Height < 1 { return nil } @@ -262,7 +262,7 @@ func (gc *GradientComposite) Dispose() { func (gc *GradientComposite) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { switch msg { case win.WM_SIZE, win.WM_SIZING: - size := gc.ClientBounds().Size() + size := gc.ClientBoundsPixels().Size() if gc.brush != nil && gc.brush.bitmap.size == size { break } diff --git a/graphicseffects.go b/graphicseffects.go index 5527e4db..d204846c 100644 --- a/graphicseffects.go +++ b/graphicseffects.go @@ -111,7 +111,7 @@ func NewBorderGlowEffect(color Color) (*BorderGlowEffect, error) { } func (bge *BorderGlowEffect) Draw(widget Widget, canvas *Canvas) error { - b := widget.Bounds() + b := widget.BoundsPixels() canvas.DrawBitmapPart(bge.bitmap, Rectangle{b.X - 5, b.Y - 5, 5, 5}, Rectangle{0, 0, 5, 5}) canvas.DrawBitmapPart(bge.bitmap, Rectangle{b.X, b.Y - 5, b.Width, 5}, Rectangle{5 + 1, 0, 1, 5}) @@ -140,7 +140,7 @@ func NewDropShadowEffect(color Color) (*DropShadowEffect, error) { } func (dse *DropShadowEffect) Draw(widget Widget, canvas *Canvas) error { - b := widget.Bounds() + b := widget.BoundsPixels() canvas.DrawBitmapPart(dse.bitmap, Rectangle{b.X + b.Width, b.Y + 10 - 5, 5, 5}, Rectangle{5 + 2, 0, 5, 5}) canvas.DrawBitmapPart(dse.bitmap, Rectangle{b.X + b.Width, b.Y + 10, 5, b.Height - 10}, Rectangle{5 + 2, 5 + 1, 5, 1}) diff --git a/gridlayout.go b/gridlayout.go index c418a956..66f58fd7 100644 --- a/gridlayout.go +++ b/gridlayout.go @@ -319,7 +319,7 @@ func (l *GridLayout) MinSize() Size { return Size{} } - return l.MinSizeForSize(l.container.ClientBounds().Size()) + return l.MinSizeForSize(l.container.ClientBoundsPixels().Size()) } func (l *GridLayout) MinSizeForSize(size Size) Size { @@ -518,7 +518,7 @@ func (l *GridLayout) Update(reset bool) error { ifContainerIsScrollViewDoCoolSpecialLayoutStuff(l) - cb := l.container.ClientBounds() + cb := l.container.ClientBoundsPixels() widths := l.sectionSizesForSpace(Horizontal, cb.Width, nil) heights := l.sectionSizesForSpace(Vertical, cb.Height, widths) diff --git a/groupbox.go b/groupbox.go index 3e37c5f6..f8faaf0d 100644 --- a/groupbox.go +++ b/groupbox.go @@ -159,7 +159,7 @@ func (gb *GroupBox) HeightForWidth(width int) int { return cmsh.Height + gb.headerHeight } -func (gb *GroupBox) ClientBounds() Rectangle { +func (gb *GroupBox) ClientBoundsPixels() Rectangle { cb := windowClientBounds(gb.hWndGroupBox) if gb.Layout() == nil { @@ -353,7 +353,7 @@ func (gb *GroupBox) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) u win.UpdateWindow(gb.checkBox.hWnd) case win.WM_SIZE, win.WM_SIZING: - wbcb := gb.WidgetBase.ClientBounds() + wbcb := gb.WidgetBase.ClientBoundsPixels() if !win.MoveWindow( gb.hWndGroupBox, int32(wbcb.X), @@ -374,12 +374,12 @@ func (gb *GroupBox) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) u } else { x = gb.headerHeight * 2 / 3 } - gb.checkBox.SetBounds(Rectangle{x, gb.headerHeight, s.Width, s.Height}) + gb.checkBox.SetBoundsPixels(Rectangle{x, gb.headerHeight, s.Width, s.Height}) } - gbcb := gb.ClientBounds() + gbcb := gb.ClientBoundsPixels() gbcb.Height -= 2 - gb.composite.SetBounds(gbcb) + gb.composite.SetBoundsPixels(gbcb) } } diff --git a/imageview.go b/imageview.go index 18a07dba..e1908694 100644 --- a/imageview.go +++ b/imageview.go @@ -196,7 +196,7 @@ func (iv *ImageView) drawImage(canvas *Canvas, updateBounds Rectangle) error { return nil } - cb := iv.ClientBounds() + cb := iv.ClientBoundsPixels() cb.Width -= iv.margin * 2 cb.Height -= iv.margin * 2 diff --git a/lineerrorpresenter.go b/lineerrorpresenter.go index bd9e98c4..f16604d0 100644 --- a/lineerrorpresenter.go +++ b/lineerrorpresenter.go @@ -214,8 +214,8 @@ func (lep *LineErrorPresenter) WndProc(hwnd win.HWND, msg uint32, wParam, lParam switch msg { case win.WM_SIZE, win.WM_SIZING: if lep.composite != nil { - b := lep.ClientBounds() - lep.composite.SetBounds(Rectangle{b.X + 2, b.Y + 2, b.Width - 4, b.Height - 4}) + b := lep.ClientBoundsPixels() + lep.composite.SetBoundsPixels(Rectangle{b.X + 2, b.Y + 2, b.Width - 4, b.Height - 4}) } } diff --git a/mainwindow.go b/mainwindow.go index 07ab2015..efc77b58 100644 --- a/mainwindow.go +++ b/mainwindow.go @@ -78,7 +78,7 @@ func NewMainWindowWithName(name string) (*MainWindow, error) { mw.statusBar.parent = mw win.SetParent(mw.statusBar.hWnd, mw.hWnd) mw.statusBar.visibleChangedPublisher.event.Attach(func() { - mw.SetBounds(mw.Bounds()) + mw.SetBoundsPixels(mw.BoundsPixels()) }) succeeded = true @@ -114,18 +114,18 @@ func (mw *MainWindow) StatusBar() *StatusBar { return mw.statusBar } -func (mw *MainWindow) ClientBounds() Rectangle { - bounds := mw.FormBase.ClientBounds() +func (mw *MainWindow) ClientBoundsPixels() Rectangle { + bounds := mw.FormBase.ClientBoundsPixels() if mw.toolBar != nil && mw.toolBar.Actions().Len() > 0 { - tlbBounds := mw.toolBar.Bounds() + tlbBounds := mw.toolBar.BoundsPixels() bounds.Y += tlbBounds.Height bounds.Height -= tlbBounds.Height } if mw.statusBar.Visible() { - bounds.Height -= mw.statusBar.Height() + bounds.Height -= mw.statusBar.HeightPixels() } return bounds @@ -214,13 +214,13 @@ func (mw *MainWindow) SetFullscreen(fullscreen bool) error { func (mw *MainWindow) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { switch msg { case win.WM_SIZE, win.WM_SIZING: - cb := mw.ClientBounds() + cb := mw.ClientBoundsPixels() if mw.toolBar != nil { - mw.toolBar.SetBounds(Rectangle{0, 0, cb.Width, mw.toolBar.Height()}) + mw.toolBar.SetBoundsPixels(Rectangle{0, 0, cb.Width, mw.toolBar.HeightPixels()}) } - mw.statusBar.SetBounds(Rectangle{0, cb.Y + cb.Height, cb.Width, mw.statusBar.Height()}) + mw.statusBar.SetBoundsPixels(Rectangle{0, cb.Y + cb.Height, cb.Width, mw.statusBar.HeightPixels()}) } return mw.FormBase.WndProc(hwnd, msg, wParam, lParam) diff --git a/numberedit.go b/numberedit.go index 0e4fb983..49665c2c 100644 --- a/numberedit.go +++ b/numberedit.go @@ -408,8 +408,8 @@ func (ne *NumberEdit) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) break } - cb := ne.ClientBounds() - if err := ne.edit.SetBounds(cb); err != nil { + cb := ne.ClientBoundsPixels() + if err := ne.edit.SetBoundsPixels(cb); err != nil { break } } diff --git a/scrollview.go b/scrollview.go index 188da93e..a3bcfa2a 100644 --- a/scrollview.go +++ b/scrollview.go @@ -90,7 +90,7 @@ func (sv *ScrollView) sizeHint(ideal bool) Size { } s := sv.composite.MinSizeHint() - cb := sv.ClientBounds() + cb := sv.ClientBoundsPixels() h, v := sv.Scrollbars() @@ -217,13 +217,13 @@ func (sv *ScrollView) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) switch msg { case win.WM_HSCROLL: - sv.composite.SetX(sv.scroll(win.SB_HORZ, win.LOWORD(uint32(wParam)))) + sv.composite.SetX(sv.IntTo96DPI(sv.scroll(win.SB_HORZ, win.LOWORD(uint32(wParam))))) if wParam == win.SB_ENDSCROLL { avoidBGArtifacts() } case win.WM_VSCROLL: - sv.composite.SetY(sv.scroll(win.SB_VERT, win.LOWORD(uint32(wParam)))) + sv.composite.SetY(sv.IntTo96DPI(sv.scroll(win.SB_VERT, win.LOWORD(uint32(wParam))))) if wParam == win.SB_ENDSCROLL { avoidBGArtifacts() } @@ -240,7 +240,7 @@ func (sv *ScrollView) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) cmd = win.SB_LINEUP } - sv.composite.SetY(sv.scroll(win.SB_VERT, cmd)) + sv.composite.SetY(sv.IntTo96DPI(sv.scroll(win.SB_VERT, cmd))) avoidBGArtifacts() return 0 @@ -259,18 +259,18 @@ func (sv *ScrollView) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) func (sv *ScrollView) updateCompositeSize() { var minSize Size if fl, ok := sv.composite.layout.(*FlowLayout); ok { - minSize = fl.MinSizeForSize(sv.ClientBounds().Size()) + minSize = fl.MinSizeForSize(sv.ClientBoundsPixels().Size()) } else { minSize = sv.composite.layout.MinSize() } - s := maxSize(minSize, sv.ClientBounds().Size()) - sv.composite.SetSize(s) + s := maxSize(minSize, sv.ClientBoundsPixels().Size()) + sv.composite.SetSizePixels(s) sv.updateScrollBars() } func (sv *ScrollView) updateScrollBars() { - s := sv.composite.Size() - clb := sv.ClientBounds() + s := sv.composite.SizePixels() + clb := sv.ClientBoundsPixels() var si win.SCROLLINFO si.CbSize = uint32(unsafe.Sizeof(si)) @@ -284,18 +284,18 @@ func (sv *ScrollView) updateScrollBars() { si.NMax = int32(s.Width - 1) si.NPage = uint32(clb.Width) win.SetScrollInfo(sv.hWnd, win.SB_HORZ, &si, false) - sv.composite.SetX(sv.scroll(win.SB_HORZ, win.SB_THUMBPOSITION)) + sv.composite.SetX(sv.IntTo96DPI(sv.scroll(win.SB_HORZ, win.SB_THUMBPOSITION))) } if v { if h { - clb = sv.ClientBounds() + clb = sv.ClientBoundsPixels() } si.NMax = int32(s.Height - 1) si.NPage = uint32(clb.Height) win.SetScrollInfo(sv.hWnd, win.SB_VERT, &si, false) - sv.composite.SetY(sv.scroll(win.SB_VERT, win.SB_THUMBPOSITION)) + sv.composite.SetY(sv.IntTo96DPI(sv.scroll(win.SB_VERT, win.SB_THUMBPOSITION))) } if sbFlags != win.GetWindowLong(sv.hWnd, win.GWL_STYLE)&(win.WS_HSCROLL|win.WS_VSCROLL) { @@ -351,7 +351,7 @@ func ifContainerIsScrollViewDoCoolSpecialLayoutStuff(layout Layout) bool { min := layout.MinSize() flags := layout.LayoutFlags() - s := widget.Bounds().Size() + s := widget.BoundsPixels().Size() hsb, vsb := sv.Scrollbars() @@ -366,7 +366,7 @@ func ifContainerIsScrollViewDoCoolSpecialLayoutStuff(layout Layout) bool { } if changeCompositeSize { - widget.SetBounds(Rectangle{X: 0, Y: 0, Width: s.Width, Height: s.Height}) + widget.SetBoundsPixels(Rectangle{X: 0, Y: 0, Width: s.Width, Height: s.Height}) sv.updateScrollBars() return false } diff --git a/splitter.go b/splitter.go index 88dca5fb..8a730b20 100644 --- a/splitter.go +++ b/splitter.go @@ -23,6 +23,7 @@ func init() { MustRegisterWindowClass(splitterWindowClass) splitterHandleDraggingBrush, _ = NewSolidColorBrush(Color(win.GetSysColor(win.COLOR_BTNSHADOW))) + splitterHandleDraggingBrush.wb2info = map[*WindowBase]*windowBrushInfo{nil: nil} } type Splitter struct { @@ -299,9 +300,9 @@ func (s *Splitter) SetFixed(widget Widget, fixed bool) error { item.fixed = fixed - if b := widget.Bounds(); fixed && b.Width == 0 || b.Height == 0 { + if b := widget.BoundsPixels(); fixed && b.Width == 0 || b.Height == 0 { b.Width, b.Height = 100, 100 - widget.SetBounds(b) + widget.SetBoundsPixels(b) item.size = 100 } @@ -342,9 +343,9 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { } } else { layout := s.Layout().(*splitterLayout) - item := &splitterLayoutItem{stretchFactor: 1} + item := &splitterLayoutItem{stretchFactor: 1, wasVisible: true} layout.hwnd2Item[widget.Handle()] = item - item.visibleChangedHandle = widget.AsWidgetBase().Property("Visible").Changed().Attach(func() { + item.visibleChangedHandle = widget.VisibleChanged().Attach(func() { if !layout.suspended && widget.AsWidgetBase().visible != item.wasVisible { layout.Update(true) } @@ -396,18 +397,18 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { } handleIndex := s.children.Index(s.draggedHandle) - bh := s.draggedHandle.Bounds() + bh := s.draggedHandle.BoundsPixels() prev := closestVisibleWidget(handleIndex, -1) - bp := prev.Bounds() + bp := prev.BoundsPixels() msep := minSizeEffective(prev) next := closestVisibleWidget(handleIndex, 1) - bn := next.Bounds() + bn := next.BoundsPixels() msen := minSizeEffective(next) if s.Orientation() == Horizontal { - xh := s.draggedHandle.X() + xh := s.draggedHandle.XPixels() xnew := xh + x - s.mouseDownPos.X if xnew < bp.X+msep.Width { @@ -416,11 +417,11 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { xnew = bn.X + bn.Width - msen.Width - s.handleWidth } - if e := s.draggedHandle.SetX(xnew); e != nil { + if e := s.draggedHandle.SetXPixels(xnew); e != nil { return } } else { - yh := s.draggedHandle.Y() + yh := s.draggedHandle.YPixels() ynew := yh + y - s.mouseDownPos.Y if ynew < bp.Y+msep.Height { @@ -429,7 +430,7 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { ynew = bn.Y + bn.Height - msen.Height - s.handleWidth } - if e := s.draggedHandle.SetY(ynew); e != nil { + if e := s.draggedHandle.SetYPixels(ynew); e != nil { return } } @@ -480,9 +481,9 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { defer next.Invalidate() defer next.SetSuspended(false) - bh := dragHandle.Bounds() - bp := prev.Bounds() - bn := next.Bounds() + bh := dragHandle.BoundsPixels() + bp := prev.BoundsPixels() + bn := next.BoundsPixels() var sizePrev int var sizeNext int @@ -501,11 +502,11 @@ func (s *Splitter) onInsertedWidget(index int, widget Widget) (err error) { sizeNext = bn.Height } - if e := prev.SetBounds(bp); e != nil { + if e := prev.SetBoundsPixels(bp); e != nil { return } - if e := next.SetBounds(bn); e != nil { + if e := next.SetBoundsPixels(bn); e != nil { return } diff --git a/splitterlayout.go b/splitterlayout.go index a52192a4..cc046d7a 100644 --- a/splitterlayout.go +++ b/splitterlayout.go @@ -159,7 +159,7 @@ func (l *splitterLayout) MinSize() Size { return Size{} } - return l.MinSizeForSize(l.container.ClientBounds().Size()) + return l.MinSizeForSize(l.container.ClientBoundsPixels().Size()) } func (l *splitterLayout) MinSizeForSize(size Size) Size { @@ -178,7 +178,7 @@ func (l *splitterLayout) MinSizeForSize(size Size) Size { var cur Size if anyNonFixed && l.Fixed(widget) { - cur = widget.Size() + cur = widget.SizePixels() if l.orientation == Horizontal { cur.Height = 0 @@ -203,7 +203,7 @@ func (l *splitterLayout) MinSizeForSize(size Size) Size { func (l *splitterLayout) anyNonFixed() bool { for i, widget := range l.container.Children().items { - if i%2 == 0 && !l.Fixed(widget) { + if i%2 == 0 && widget.visible && !l.Fixed(widget) { return true } } @@ -213,7 +213,7 @@ func (l *splitterLayout) anyNonFixed() bool { func (l *splitterLayout) spaceForRegularWidgets() int { splitter := l.container.(*Splitter) - s := splitter.ClientBounds().Size() + s := splitter.ClientBoundsPixels().Size() var space int if l.orientation == Horizontal { @@ -257,7 +257,7 @@ func (l *splitterLayout) reset() { if i == 0 { if len(children.items) > 1 { - handleIndex = i + 1 + handleIndex = 1 } else { handleIndex = -1 } @@ -365,7 +365,7 @@ func (l *splitterLayout) Update(reset bool) error { splitter := l.container.(*Splitter) handleWidth := splitter.HandleWidth() sizes := make([]int, len(widgets)) - cb := splitter.ClientBounds() + cb := splitter.ClientBoundsPixels() cb.X += l.margins.HNear cb.Y += l.margins.HFar cb.Width -= l.margins.HNear + l.margins.HFar @@ -514,7 +514,7 @@ func (l *splitterLayout) Update(reset bool) error { } if maybeInvalidate { - if b := widget.Bounds(); w == b.Width && h == b.Height && (x != b.X || y != b.Y) { + if b := widget.BoundsPixels(); w == b.Width && h == b.Height && (x != b.X || y != b.Y) { widget.Invalidate() } } @@ -178,13 +178,13 @@ func (s *static) setText(text string) (changed bool, err error) { return false, err } - size := s.Bounds().Size() + size := s.BoundsPixels().Size() if err := s.updateParentLayout(); err != nil { return false, err } - if s.Bounds().Size() == size && size != (Size{}) { + if s.BoundsPixels().Size() == size && size != (Size{}) { s.updateStaticBounds() } @@ -226,7 +226,7 @@ func (s *static) updateStaticBounds() { format |= TextBottom } - cb := s.ClientBounds() + cb := s.ClientBoundsPixels() if format&TextVCenter != 0 || format&TextBottom != 0 { var size Size diff --git a/statusbar.go b/statusbar.go index 0302b50f..b5d3b1f9 100644 --- a/statusbar.go +++ b/statusbar.go @@ -61,6 +61,12 @@ func (sb *StatusBar) SetVisible(visible bool) { sb.Parent().SendMessage(win.WM_SIZE, 0, 0) } +func (sb *StatusBar) ApplyDPI(dpi int) { + sb.WidgetBase.ApplyDPI(dpi) + + sb.update() +} + func (sb *StatusBar) update() error { if err := sb.updateParts(); err != nil { return err @@ -83,7 +89,7 @@ func (sb *StatusBar) updateParts() error { rightEdges := make([]int32, len(items)) var right int32 for i, item := range items { - right += int32(item.width) + right += int32(sb.IntFrom96DPI(item.width)) rightEdges[i] = right } var rep *int32 diff --git a/tableview.go b/tableview.go index 23f68b2c..6d3cbfe8 100644 --- a/tableview.go +++ b/tableview.go @@ -2259,7 +2259,7 @@ func (tv *TableView) WndProc(hwnd win.HWND, msg uint32, wp, lp uintptr) uintptr } func (tv *TableView) updateLVSizes() { - cb := tv.ClientBounds() + cb := tv.ClientBoundsPixels() var width int for i := tv.columns.Len() - 1; i >= 0; i-- { @@ -2268,6 +2268,8 @@ func (tv *TableView) updateLVSizes() { } } + width = tv.IntFrom96DPI(width) + win.MoveWindow(tv.hwndNormalLV, int32(width), 0, int32(cb.Width-width), int32(cb.Height), true) var sbh int diff --git a/tableviewcolumn.go b/tableviewcolumn.go index f8aa4f40..8e902d20 100644 --- a/tableviewcolumn.go +++ b/tableviewcolumn.go @@ -298,7 +298,7 @@ func (tvc *TableViewColumn) Width() int { return tvc.width } - return int(tvc.sendMessage(win.LVM_GETCOLUMNWIDTH, uintptr(tvc.indexInListView()), 0)) + return tvc.tv.IntTo96DPI(int(tvc.sendMessage(win.LVM_GETCOLUMNWIDTH, uintptr(tvc.indexInListView()), 0))) } // SetWidth sets the width of the column in pixels. @@ -431,10 +431,15 @@ func (tvc *TableViewColumn) update() error { func (tvc *TableViewColumn) getLVCOLUMN() *win.LVCOLUMN { var lvc win.LVCOLUMN + width := tvc.width + if tvc.tv != nil { + width = tvc.tv.IntFrom96DPI(width) + } + lvc.Mask = win.LVCF_FMT | win.LVCF_WIDTH | win.LVCF_TEXT | win.LVCF_SUBITEM lvc.ISubItem = int32(tvc.indexInListView()) lvc.PszText = syscall.StringToUTF16Ptr(tvc.TitleEffective()) - lvc.Cx = int32(tvc.width) + lvc.Cx = int32(width) switch tvc.alignment { case AlignCenter: diff --git a/tabwidget.go b/tabwidget.go index 6508171b..5e97a4dd 100644 --- a/tabwidget.go +++ b/tabwidget.go @@ -125,8 +125,8 @@ func (tw *TabWidget) MinSizeHint() Size { min.Height = maxi(min.Height, s.Height) } - b := tw.Bounds() - pb := tw.pages.At(0).Bounds() + b := tw.BoundsPixels() + pb := tw.pages.At(0).BoundsPixels() size := Size{b.Width - pb.Width + min.Width, b.Height - pb.Height + min.Height} @@ -139,8 +139,8 @@ func (tw *TabWidget) HeightForWidth(width int) int { } var height int - margin := tw.Size() - pageSize := tw.pages.At(0).Size() + margin := tw.SizePixels() + pageSize := tw.pages.At(0).SizePixels() margin.Width -= pageSize.Width margin.Height -= pageSize.Height @@ -171,7 +171,8 @@ func (tw *TabWidget) applyFont(font *Font) { setWindowFont(tw.hWndTab, font) - applyFontToDescendants(tw, font) + // FIXME: won't work with ApplyDPI + // applyFontToDescendants(tw, font) } func (tw *TabWidget) CurrentIndex() int { @@ -280,7 +281,7 @@ func (tw *TabWidget) resizePages() { win.SendMessage(tw.hWndTab, win.TCM_ADJUSTRECT, 0, uintptr(unsafe.Pointer(&r))) for _, page := range tw.pages.items { - if err := page.SetBounds( + if err := page.SetBoundsPixels( Rectangle{ int(r.Left - 2), int(r.Top), @@ -367,7 +368,7 @@ func tabWidgetTabWndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uint hdc := win.BeginPaint(hwnd, &ps) defer win.EndPaint(hwnd, &ps) - cb := tw.ClientBounds() + cb := tw.ClientBoundsPixels() bitmap, err := NewBitmap(cb.Size()) if err != nil { diff --git a/textlabel.go b/textlabel.go index ab06ca69..ad05bd75 100644 --- a/textlabel.go +++ b/textlabel.go @@ -53,7 +53,7 @@ func (tl *TextLabel) MinSizeHint() Size { } func (tl *TextLabel) SizeHint() Size { - return tl.calculateTextSizeForWidth(tl.Width()) + return tl.calculateTextSizeForWidth(tl.WidthPixels()) } func (tl *TextLabel) HeightForWidth(width int) int { @@ -258,8 +258,8 @@ func (tb *ToolBar) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) ui case win.WM_MOUSEMOVE, win.WM_MOUSELEAVE, win.WM_LBUTTONDOWN: tb.Invalidate() - case win.WM_PAINT: - tb.Invalidate() + // case win.WM_PAINT: + // tb.Invalidate() case win.WM_COMMAND: switch win.HIWORD(uint32(wParam)) { @@ -142,7 +142,7 @@ func (tt *ToolTip) track(tool Widget) error { tt.SendMessage(win.TTM_TRACKACTIVATE, 1, uintptr(unsafe.Pointer(ti))) - b := tool.Bounds() + b := tool.BoundsPixels() p := win.POINT{X: 0, Y: int32(b.Y + b.Height)} if form.RightToLeftLayout() { @@ -431,7 +431,7 @@ func (wv *WebView) withWebBrowser2(f func(webBrowser2 *win.IWebBrowser2) error) func (wv *WebView) onResize() { // FIXME: handle error? wv.withWebBrowser2(func(webBrowser2 *win.IWebBrowser2) error { - bounds := wv.ClientBounds() + bounds := wv.ClientBoundsPixels() webBrowser2.Put_Left(0) webBrowser2.Put_Top(0) diff --git a/webview_dwebbrowserevents2.go b/webview_dwebbrowserevents2.go index 4649a9e2..ec2b448e 100644 --- a/webview_dwebbrowserevents2.go +++ b/webview_dwebbrowserevents2.go @@ -12,8 +12,9 @@ import ( ) import ( - "github.com/lxn/win" "time" + + "github.com/lxn/win" ) var webViewDWebBrowserEvents2Vtbl *win.DWebBrowserEvents2Vtbl @@ -180,11 +181,11 @@ func webView_DWebBrowserEvents2_Invoke( // FIXME: Horrible hack to avoid glitch where the document is not displayed. time.AfterFunc(time.Millisecond*100, func() { wv.Synchronize(func() { - b := wv.Bounds() + b := wv.BoundsPixels() b.Width++ - wv.SetBounds(b) + wv.SetBoundsPixels(b) b.Width-- - wv.SetBounds(b) + wv.SetBoundsPixels(b) }) }) @@ -151,12 +151,12 @@ func (wb *WidgetBase) AsWidgetBase() *WidgetBase { return wb } -// Bounds returns the outer bounding box Rectangle of the WidgetBase, including +// BoundsPixels returns the outer bounding box Rectangle of the WidgetBase, including // decorations. // // The coordinates are relative to the parent of the Widget. -func (wb *WidgetBase) Bounds() Rectangle { - b := wb.WindowBase.Bounds() +func (wb *WidgetBase) BoundsPixels() Rectangle { + b := wb.WindowBase.BoundsPixels() if wb.parent != nil { p := win.POINT{int32(b.X), int32(b.Y)} @@ -316,7 +316,7 @@ func (wb *WidgetBase) SetParent(parent Container) (err error) { } } - b := wb.Bounds() + b := wb.BoundsPixels() if !win.SetWindowPos( wb.hWnd, @@ -420,7 +420,7 @@ func (wb *WidgetBase) onClearedGraphicsEffects() error { func (wb *WidgetBase) invalidateBorderInParent() { if wb.parent != nil && wb.parent.Layout() != nil { - b := wb.Bounds().toRECT() + b := wb.BoundsPixels().toRECT() s := int32(wb.parent.Layout().Spacing()) hwnd := wb.parent.Handle() @@ -503,13 +503,13 @@ func (wb *WidgetBase) updateParentLayoutWithReset(reset bool) error { if len(inProgressEventsByForm[appSingleton.activeForm]) > 0 { formResizeScheduled = true } else { - bounds := wnd.Bounds() + bounds := wnd.BoundsPixels() if wnd.AsFormBase().fixedSize() { bounds.Width, bounds.Height = 0, 0 } - wnd.SetBounds(bounds) + wnd.SetBoundsPixels(bounds) return nil } @@ -46,6 +46,14 @@ type Window interface { // parent. Bounds() Rectangle + // BoundsPixels returns the outer bounding box Rectangle of the Window, including + // decorations. + // + // For a Form, like *MainWindow or *Dialog, the Rectangle is in screen + // coordinates, for a child Window the coordinates are relative to its + // parent. + BoundsPixels() Rectangle + // BoundsChanged returns an *Event that you can attach to for handling bounds // changed events for the Window. BoundsChanged() *Event @@ -57,13 +65,17 @@ type Window interface { // excluding decorations. ClientBounds() Rectangle + // ClientBoundsPixels returns the inner bounding box Rectangle of the Window, + // excluding decorations. + ClientBoundsPixels() Rectangle + // ContextMenu returns the context menu of the Window. // // By default this is nil. ContextMenu() *Menu // CreateCanvas creates and returns a *Canvas that can be used to draw - // inside the ClientBounds of the Window. + // inside the ClientBoundsPixels of the Window. // // Remember to call the Dispose method on the canvas to release resources, // when you no longer need it. @@ -114,6 +126,9 @@ type Window interface { // Height returns the outer height of the Window, including decorations. Height() int + // HeightPixels returns the outer height of the Window, including decorations. + HeightPixels() int + // Invalidate schedules a full repaint of the Window. Invalidate() error @@ -182,9 +197,17 @@ type Window interface { // parent. SetBounds(value Rectangle) error - // SetClientSize sets the Size of the inner bounding box of the Window, + // SetBoundsPixels sets the outer bounding box Rectangle of the Window, including + // decorations. + // + // For a Form, like *MainWindow or *Dialog, the Rectangle is in screen + // coordinates, for a child Window the coordinates are relative to its + // parent. + SetBoundsPixels(value Rectangle) error + + // SetClientSizePixels sets the Size of the inner bounding box of the Window, // excluding decorations. - SetClientSize(value Size) error + SetClientSizePixels(value Size) error // SetContextMenu sets the context menu of the Window. SetContextMenu(value *Menu) @@ -208,6 +231,9 @@ type Window interface { // SetHeight sets the outer height of the Window, including decorations. SetHeight(value int) error + // SetHeightPixels sets the outer height of the Window, including decorations. + SetHeightPixels(value int) error + // SetMinMaxSize sets the minimum and maximum outer Size of the Window, // including decorations. // @@ -228,6 +254,9 @@ type Window interface { // SetSize sets the outer Size of the Window, including decorations. SetSize(value Size) error + // SetSizePixels sets the outer Size of the Window, including decorations. + SetSizePixels(value Size) error + // SetSuspended sets if the Window is suspended for layout and repainting // purposes. // @@ -242,19 +271,35 @@ type Window interface { // SetWidth sets the outer width of the Window, including decorations. SetWidth(value int) error + // SetWidthPixels sets the outer width of the Window, including decorations. + SetWidthPixels(value int) error + // SetX sets the x coordinate of the Window, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. SetX(value int) error + // SetXPixels sets the x coordinate of the Window, relative to the screen for + // RootWidgets like *MainWindow or *Dialog and relative to the parent for + // child Windows. + SetXPixels(value int) error + // SetY sets the y coordinate of the Window, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. SetY(value int) error + // SetYPixels sets the y coordinate of the Window, relative to the screen for + // RootWidgets like *MainWindow or *Dialog and relative to the parent for + // child Windows. + SetYPixels(value int) error + // Size returns the outer Size of the Window, including decorations. Size() Size + // SizePixels returns the outer Size of the Window, including decorations. + SizePixels() Size + // SizeChanged returns an *Event that you can attach to for handling size // changed events for the Window. SizeChanged() *Event @@ -277,6 +322,9 @@ type Window interface { // Width returns the outer width of the Window, including decorations. Width() int + // WidthPixels returns the outer width of the Window, including decorations. + WidthPixels() int + // WndProc is the window procedure of the window. // // When implementing your own WndProc to add or modify behavior, call the @@ -288,10 +336,20 @@ type Window interface { // child Windows. X() int + // XPixels returns the x coordinate of the Window, relative to the screen for + // RootWidgets like *MainWindow or *Dialog and relative to the parent for + // child Windows. + XPixels() int + // Y returns the y coordinate of the Window, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. Y() int + + // YPixels returns the y coordinate of the Window, relative to the screen for + // RootWidgets like *MainWindow or *Dialog and relative to the parent for + // child Windows. + YPixels() int } type calcTextSizeInfo struct { @@ -815,7 +873,9 @@ type ApplyDPIer interface { func (wb *WindowBase) ApplyDPI(dpi int) { wb.dpi = dpi - wb.window.SetFont(wb.window.Font()) + if af, ok := wb.window.(applyFonter); ok { + af.applyFont(wb.window.Font()) + } } func (wb *WindowBase) IntFrom96DPI(value int) int { @@ -1173,6 +1233,23 @@ func (wb *WindowBase) BringToTop() error { // // The coordinates are relative to the screen. func (wb *WindowBase) Bounds() Rectangle { + return wb.RectangleTo96DPI(wb.BoundsPixels()) +} + +// SetBounds sets the outer bounding box Rectangle of the *WindowBase, +// including decorations. +// +// For a Form, like *MainWindow or *Dialog, the Rectangle is in screen +// coordinates, for a child Window the coordinates are relative to its parent. +func (wb *WindowBase) SetBounds(bounds Rectangle) error { + return wb.SetBoundsPixels(wb.RectangleFrom96DPI(bounds)) +} + +// BoundsPixels returns the outer bounding box Rectangle of the *WindowBase, including +// decorations. +// +// The coordinates are relative to the screen. +func (wb *WindowBase) BoundsPixels() Rectangle { var r win.RECT if !win.GetWindowRect(wb.hWnd, &r) { @@ -1188,12 +1265,12 @@ func (wb *WindowBase) Bounds() Rectangle { } } -// SetBounds sets the outer bounding box Rectangle of the *WindowBase, +// SetBoundsPixels sets the outer bounding box Rectangle of the *WindowBase, // including decorations. // // For a Form, like *MainWindow or *Dialog, the Rectangle is in screen // coordinates, for a child Window the coordinates are relative to its parent. -func (wb *WindowBase) SetBounds(bounds Rectangle) error { +func (wb *WindowBase) SetBoundsPixels(bounds Rectangle) error { if !win.MoveWindow( wb.hWnd, int32(bounds.X), @@ -1406,74 +1483,132 @@ func (wb *WindowBase) calculateTextSizeForWidth(width int) Size { // Size returns the outer Size of the *WindowBase, including decorations. func (wb *WindowBase) Size() Size { - return wb.window.Bounds().Size() + return wb.SizeTo96DPI(wb.SizePixels()) +} + +// SizePixels returns the outer Size of the *WindowBase, including decorations. +func (wb *WindowBase) SizePixels() Size { + return wb.window.BoundsPixels().Size() } // SetSize sets the outer Size of the *WindowBase, including decorations. func (wb *WindowBase) SetSize(size Size) error { - bounds := wb.window.Bounds() + return wb.SetSizePixels(wb.SizeFrom96DPI(size)) +} + +// SetSizePixels sets the outer Size of the *WindowBase, including decorations. +func (wb *WindowBase) SetSizePixels(size Size) error { + bounds := wb.window.BoundsPixels() - return wb.SetBounds(bounds.SetSize(size)) + return wb.SetBoundsPixels(bounds.SetSize(size)) } // X returns the x coordinate of the *WindowBase, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. func (wb *WindowBase) X() int { - return wb.window.Bounds().X + return wb.IntTo96DPI(wb.XPixels()) +} + +// XPixels returns the x coordinate of the *WindowBase, relative to the screen for +// RootWidgets like *MainWindow or *Dialog and relative to the parent for +// child Windows. +func (wb *WindowBase) XPixels() int { + return wb.window.BoundsPixels().X } // SetX sets the x coordinate of the *WindowBase, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. func (wb *WindowBase) SetX(value int) error { - bounds := wb.window.Bounds() + return wb.SetXPixels(wb.IntFrom96DPI(value)) +} + +// SetXPixels sets the x coordinate of the *WindowBase, relative to the screen for +// RootWidgets like *MainWindow or *Dialog and relative to the parent for +// child Windows. +func (wb *WindowBase) SetXPixels(value int) error { + bounds := wb.window.BoundsPixels() bounds.X = value - return wb.SetBounds(bounds) + return wb.SetBoundsPixels(bounds) } // Y returns the y coordinate of the *WindowBase, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. func (wb *WindowBase) Y() int { - return wb.window.Bounds().Y + return wb.IntTo96DPI(wb.YPixels()) +} + +// YPixels returns the y coordinate of the *WindowBase, relative to the screen for +// RootWidgets like *MainWindow or *Dialog and relative to the parent for +// child Windows. +func (wb *WindowBase) YPixels() int { + return wb.window.BoundsPixels().Y } // SetY sets the y coordinate of the *WindowBase, relative to the screen for // RootWidgets like *MainWindow or *Dialog and relative to the parent for // child Windows. func (wb *WindowBase) SetY(value int) error { - bounds := wb.window.Bounds() + return wb.SetYPixels(wb.IntFrom96DPI(value)) +} + +// SetYPixels sets the y coordinate of the *WindowBase, relative to the screen for +// RootWidgets like *MainWindow or *Dialog and relative to the parent for +// child Windows. +func (wb *WindowBase) SetYPixels(value int) error { + bounds := wb.window.BoundsPixels() bounds.Y = value - return wb.SetBounds(bounds) + return wb.SetBoundsPixels(bounds) } // Width returns the outer width of the *WindowBase, including decorations. func (wb *WindowBase) Width() int { - return wb.window.Bounds().Width + return wb.IntTo96DPI(wb.WidthPixels()) +} + +// WidthPixels returns the outer width of the *WindowBase, including decorations. +func (wb *WindowBase) WidthPixels() int { + return wb.window.BoundsPixels().Width } // SetWidth sets the outer width of the *WindowBase, including decorations. func (wb *WindowBase) SetWidth(value int) error { - bounds := wb.window.Bounds() + return wb.SetWidthPixels(wb.IntFrom96DPI(value)) +} + +// SetWidthPixels sets the outer width of the *WindowBase, including decorations. +func (wb *WindowBase) SetWidthPixels(value int) error { + bounds := wb.window.BoundsPixels() bounds.Width = value - return wb.SetBounds(bounds) + return wb.SetBoundsPixels(bounds) } // Height returns the outer height of the *WindowBase, including decorations. func (wb *WindowBase) Height() int { - return wb.window.Bounds().Height + return wb.IntTo96DPI(wb.HeightPixels()) +} + +// HeightPixels returns the outer height of the *WindowBase, including decorations. +func (wb *WindowBase) HeightPixels() int { + return wb.window.BoundsPixels().Height } // SetHeight sets the outer height of the *WindowBase, including decorations. func (wb *WindowBase) SetHeight(value int) error { - bounds := wb.window.Bounds() + return wb.SetHeightPixels(wb.IntFrom96DPI(value)) +} + +// SetHeightPixels sets the outer height of the *WindowBase, including decorations. +func (wb *WindowBase) SetHeightPixels(value int) error { + bounds := wb.window.BoundsPixels() bounds.Height = value - return wb.SetBounds(bounds) + return wb.SetBoundsPixels(bounds) } func windowClientBounds(hwnd win.HWND) Rectangle { @@ -1495,31 +1630,37 @@ func windowClientBounds(hwnd win.HWND) Rectangle { // ClientBounds returns the inner bounding box Rectangle of the *WindowBase, // excluding decorations. func (wb *WindowBase) ClientBounds() Rectangle { + return wb.RectangleTo96DPI(wb.ClientBoundsPixels()) +} + +// ClientBoundsPixels returns the inner bounding box Rectangle of the *WindowBase, +// excluding decorations. +func (wb *WindowBase) ClientBoundsPixels() Rectangle { return windowClientBounds(wb.hWnd) } -func (wb *WindowBase) sizeFromClientSize(clientSize Size) Size { +func (wb *WindowBase) sizeFromClientSizePixels(clientSize Size) Size { window := wb.window - s := window.Size() - cs := window.ClientBounds().Size() + s := window.SizePixels() + cs := window.ClientBoundsPixels().Size() ncs := Size{s.Width - cs.Width, s.Height - cs.Height} return Size{clientSize.Width + ncs.Width, clientSize.Height + ncs.Height} } -func (wb *WindowBase) clientSizeFromSize(size Size) Size { +func (wb *WindowBase) clientSizeFromSizePixels(size Size) Size { window := wb.window - s := window.Size() - cs := window.ClientBounds().Size() + s := window.SizePixels() + cs := window.ClientBoundsPixels().Size() ncs := Size{s.Width - cs.Width, s.Height - cs.Height} return Size{size.Width - ncs.Width, size.Height - ncs.Height} } -// SetClientSize sets the Size of the inner bounding box of the *WindowBase, +// SetClientSizePixels sets the Size of the inner bounding box of the *WindowBase, // excluding decorations. -func (wb *WindowBase) SetClientSize(value Size) error { - return wb.SetSize(wb.sizeFromClientSize(value)) +func (wb *WindowBase) SetClientSizePixels(value Size) error { + return wb.SetSizePixels(wb.sizeFromClientSizePixels(value)) } // RightToLeftReading returns whether the reading order of the Window @@ -1571,7 +1712,7 @@ func (wb *WindowBase) FocusedChanged() *Event { } // CreateCanvas creates and returns a *Canvas that can be used to draw -// inside the ClientBounds of the *WindowBase. +// inside the ClientBoundsPixels of the *WindowBase. // // Remember to call the Dispose method on the canvas to release resources, // when you no longer need it. @@ -1930,7 +2071,7 @@ func (wb *WindowBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) wb.prepareDCForBackground(hdc, hwnd, wnd) - if err := canvas.FillRectangle(bg, wb.ClientBounds()); err != nil { + if err := canvas.FillRectangle(bg, wb.ClientBoundsPixels()); err != nil { break } |