Как масштабировать элементы управления с сохранением соотношения сторон и положения без окна просмотра? - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь повторить отображение Интерфейс реорганизатора в Настройки отображения , в котором есть кнопки, расположенные относительно их физического местоположения, и их можно переставить с помощью перетаскивания мышью

Windows 10 display rearrangement

Я могу получить границы экрана из класса экрана

Система. Windows .Forms.Screen

и создайте кнопку с указанными границами на холсте, но они слишком велики (например, 1366 x 768) для отображения в контейнере, поэтому я решил использовать встроенный в WPF элемент управления ViewBox

Проблема с viewbox заключается в том, что он масштабирует не только границы, но и отображаемый элемент

enter image description here

Я не могу контролировать BorderThickness , FontSize и Margin , они становятся крайне незначительными или слишком большими при изменении размера холста.

Что мне нужно, так это Scale просто размер, но не все. Я хочу, чтобы граница толщины имела фиксированный размер, а не масштабированный. В настройках одна кнопка BorderThickness остается неизменной даже после изменения размера. Что бы я ни пытался, я получаю это>

enter image description here

Здесь размер кнопки составляет 1366 x 768, ее толщина составляет 1 пиксель (не ясно видно, у меня есть установить 4 пикселя, чтобы было понятно), и иметь размер шрифта 240 пикселей.

Эта кнопка размещена на холсте, размер которого определяется программно, холст размещается в окне просмотра, которое размещено в граница. Что я должен сделать, чтобы просто масштабировать размер?

1 Ответ

0 голосов
/ 02 февраля 2020

Я наконец достиг этого, я избавился от окна просмотра и сумел сделать это с помощью кода

Код:

    Private Sub LoadScreens()
        Dim ox As Integer = 0
        Dim oy As Integer = 0
        Dim canvaswidth As Integer = 0
        Dim canvasheight As Integer = 0
        Dim rect As New List(Of System.Drawing.Rectangle)
        For i = 0 To Forms.Screen.AllScreens.Count - 1
            Dim screen = Forms.Screen.AllScreens(i)
            Dim r = screen.Bounds
            rect.Add(r)
        Next
        For Each r In rect
            If r.X < ox Then ox = r.X
            If r.Y < oy Then oy = r.Y
        Next
        For Each r In rect
            If r.X + r.Width + Math.Abs(ox) > canvaswidth Then canvaswidth = r.X + r.Width + Math.Abs(ox)
            If r.Y + r.Height + Math.Abs(oy) > canvasheight Then canvasheight = r.Y + r.Height + Math.Abs(oy)
        Next

        ScreenCanvas.Children.Clear()

        Dim scale = GetScale(TParent.ActualWidth, TParent.ActualHeight, canvaswidth, canvasheight)

        ScreenCanvas.Width = canvaswidth * scale
        ScreenCanvas.Height = canvasheight * scale

        For i = 0 To rect.Count - 1
            Dim r = rect(i)
            Dim left = (r.X - ox) * scale
            Dim top = (r.Y - oy) * scale
            Dim nr As New Primitives.ToggleButton With {
                .Width = r.Width * scale,
                .Height = r.Height * scale,
                .Content = New TextBlock() With {.Text = i + 1, .VerticalAlignment = VerticalAlignment.Center, .HorizontalAlignment = HorizontalAlignment.Center}
            }
            ScreenCanvas.Children.Add(nr)
            Canvas.SetLeft(nr, left)
            Canvas.SetTop(nr, top)
        Next
    End Sub

    Private Function GetScale(w1 As Double, h1 As Double, w2 As Double, h2 As Double) As Double
        Dim scaleHeight = h1 / h2
        Dim scaleWidth = w1 / w2
        Dim scale = Math.Min(scaleHeight, scaleWidth)
        Return scale
    End Function

Кнопки Toggle программно создаются, масштабируются, позиционируются и добавлены к масштабированному холсту: ScreenCanvas , который размещен в сетке TParent .

XAML:

          <Border CornerRadius="10" Margin="40" Padding="40" Background="#22aaaaaa">
            <Grid x:Name="TParent" Height="150" >
                <Grid.Resources>
                    <Style TargetType="{x:Type ToggleButton}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ToggleButton}">
                                    <Border Background="White" BorderBrush="Red" BorderThickness="2">
                                        <ContentPresenter TextBlock.Foreground="Black"/>
                                    </Border>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Grid.Resources>
                <Canvas x:Name="ScreenCanvas" HorizontalAlignment="Center"  VerticalAlignment="Bottom"/>
            </Grid>
        </Border>

Вот окончательный результат :

enter image description here

Теперь я могу контролировать толщину, угол, поле:)

Редактировать:

У меня есть обновлен интерфейс и добавлен код для обновления их местоположения и размера при изменении размера сетки.

Код:

     Private Sub TParent_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles TParent.SizeChanged
        If e.WidthChanged AndAlso _init Then
            Dim canvaswidth = ScreenCanvas.ActualWidth
            Dim canvasheight = ScreenCanvas.ActualHeight
            Dim scale = GetScale(TParent.ActualWidth, TParent.ActualHeight, canvaswidth, canvasheight)
            ScreenCanvas.Width = canvaswidth * scale
            ScreenCanvas.Height = canvasheight * scale
            For Each c As FrameworkElement In ScreenCanvas.Children
                c.Width = c.ActualWidth * scale
                c.Height = c.ActualHeight * scale
                Dim top = Canvas.GetTop(c) * scale
                Dim left = Canvas.GetLeft(c) * scale
                Canvas.SetTop(c, top)
                Canvas.SetLeft(c, left)
            Next
        End If
    End Sub

Пользовательский интерфейс:

enter image description here

...