WPF/XAML: как мне увеличить размер окна без рамки?

Я использую окно без рамки и сам рисую Chrome. Я хочу изменить размер окна типичным образом и определил сетку 3x3, а центр - это содержимое и внешние ячейки, составляющие соответствующие области, требующие различной обработки (TopLeft/TopMiddle/TopRight... и т.д.), Например курсоры. Максимизировать, Свернуть, Переместить и т.д. Все прямо, но я мог бы использовать некоторые указатели для изменения размера в разных направлениях на основе ячейки, над которой курсор закончился.

Ответ 1

Это кажется довольно напряженным. Минимальная/максимальная ширина и высота учитываются, а также переменные границы. Единственная проблема, о которой я знаю, - это когда движение курсора происходит быстро, а размер находится в пределах 20 пикселей от минимума, который он несколько прилипает из-за частоты обновления. Не огромная сделка, но я ее сортирую.

alt text http://cartesia.pbworks.com/f/1265489984/Resize.png

Я не могу заставить тег Window отображаться правильно... (Просто выньте апостроф, и все будет хорошо). У кого-нибудь есть мысли?

XAML

<'Window x:Class="Article_1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="Article_1_Resizing"
    Background="Transparent" AllowsTransparency="True"
        WindowStyle="None" WindowStartupLocation="CenterScreen"
    MinHeight="100" Height="400" MaxHeight="600"
    MinWidth="100" Width="400" MaxWidth="800">

 <Window.Resources>

  <SolidColorBrush x:Key="Brush_ChromeBackground" Color="#FFC8D1E0"/>
  <SolidColorBrush x:Key="Brush_ChromeBorder" Color="#FFA0A0A0"/>

  <sys:Double x:Key="Chrome_BorderWidth">5</sys:Double>

 </Window.Resources>

 <Border x:Name="Border_Chrome"
     BorderBrush="{StaticResource Brush_ChromeBorder}" BorderThickness="1,1,1,1"
     CornerRadius="2,2,2,2"
     Width="Auto">

  <Grid x:Name="Grid" ShowGridLines="False">

   <Grid.RowDefinitions>
    <RowDefinition x:Name="row_Top" Height="Auto"/>
    <RowDefinition x:Name="row_Middle" Height="*"/>
    <RowDefinition x:Name="row_Bottom" Height="Auto"/>
   </Grid.RowDefinitions>

   <Grid.ColumnDefinitions>
    <ColumnDefinition x:Name="col_Left" Width="Auto"/>
    <ColumnDefinition x:Name="col_Middle" Width="*"/>
    <ColumnDefinition x:Name="col_Right" Width="Auto"/>
   </Grid.ColumnDefinitions>

   <!-- Top Row -->
   <Rectangle x:Name="Rectangle_TopLeft"
         Grid.Row="0" Grid.Column="0"
         Width="{StaticResource Chrome_BorderWidth}" Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNWSE"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>

   <Rectangle x:Name="Rectangle_TopMiddle"
         Grid.Row="0" Grid.Column="1"
         Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNS"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>

   <Rectangle x:Name="Rectangle_TopRight"
         Grid.Row="0" Grid.Column="2"
         Width="{StaticResource Chrome_BorderWidth}" Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNESW"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>


   <!-- Middle Row -->
   <Rectangle x:Name="Rectangle_MiddleLeft"
         Grid.Row="1" Grid.Column="0"
         Width="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeWE"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>

   <!-- Content -->
   <Label Content="Mouse Down to Move - Double Click to Close"
       Grid.Row="1" Grid.Column="1"
       Background="White" Foreground="Black"
       HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
       VerticalAlignment="Stretch" VerticalContentAlignment="Center"
       MouseDoubleClick="_Close"
       MouseLeftButtonDown="Move"/>

   <Rectangle x:Name="Rectangle_MiddleRight"
         Grid.Row="1" Grid.Column="2"
         Width="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeWE"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>


   <!-- Bottom Row -->
   <Rectangle x:Name="Rectangle_BottomLeft"
         Grid.Row="2" Grid.Column="0"
         Width="{StaticResource Chrome_BorderWidth}" Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNESW"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>

   <Rectangle x:Name="Rectangle_BottomMiddle"
         Grid.Row="2" Grid.Column="1"
         Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNS"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>

   <Rectangle x:Name="Rectangle_BottomRight"
         Grid.Row="2" Grid.Column="2"
         Width="{StaticResource Chrome_BorderWidth}" Height="{StaticResource Chrome_BorderWidth}"
         Fill="{StaticResource Brush_ChromeBackground}"
         Cursor="SizeNWSE"
         MouseLeftButtonDown="Resize_Begin" MouseLeftButtonUp="Resize_End"
         MouseMove="Resize"/>
  </Grid>

 </Border>

</Window>

Код за

Partial Public Class Article_1

  Public Sub New()

    InitializeComponent()

    Initialize_Sizes

  End Sub

  Private isResizing as Boolean = False

  Private Const CURSOR_OFFSET_SMALL As Double = 3
  Private Const CURSOR_OFFSET_LARGE As Double = 5

  Private _x As Double = 0
  Private _Y As Double = 0

  Private Sub Initialize_Sizes

    Dim _MinWidth As Double = Rectangle_MiddleLeft.Width + _
                              Rectangle_BottomRight.Width + _
                              border_Chrome.BorderThickness.Left + _
                              border_Chrome.BorderThickness.Right + 1

    If MinWidth < _MinWidth then _
       MinWidth = _MinWidth

    Dim _MinHeight As Double = Rectangle_TopMiddle.Height + _
                               Rectangle_BottomMiddle.Height + _
                               border_Chrome.BorderThickness.top + _
                               border_Chrome.BorderThickness.Bottom + 1

    If MinHeight < _MinHeight then _
       MinHeight = _MinHeight

  End Sub

  Private sub Resize_Begin(sender as object, _
                           e As MouseEventArgs) 

    isResizing = True

    DirectCast(sender, Rectangle).CaptureMouse

  End Sub

  Private sub Resize_End(sender as object, _
                         e As MouseEventArgs)

    isResizing = False

    DirectCast(sender, Rectangle).ReleaseMouseCapture

  End Sub

  Private Sub Resize(sender As Object, _
                     e As MouseEventArgs)

    If isResizing = False then Exit Sub

      _x = e.GetPosition(me).x
      _y = e.GetPosition(me).Y 

      Select Case DirectCast(sender, Rectangle).Name

        Case "Rectangle_TopLeft" :      Resize_Width_Left
                                        Resize_Height_Top
        Case "Rectangle_TopMiddle" :    Resize_Height_Top
        Case "Rectangle_TopRight" :     Resize_Width_Right
                                        Resize_Height_Top

        Case "Rectangle_MiddleLeft" :   Resize_Width_Left
        Case "Rectangle_MiddleRight" :  Resize_Width_Right


        Case "Rectangle_BottomLeft" :   Resize_Width_Left
                                        Resize_Height_Bottom
        Case "Rectangle_BottomMiddle" : Resize_Height_Bottom
        Case "Rectangle_BottomRight" :  Resize_Width_Right
                                        Resize_Height_Bottom

        Case else : MessageBox.Show("Error in Resize")

      End Select

  End Sub

  Private Sub Resize_Width_Left

    _x -= CURSOR_OFFSET_SMALL

    If Width - _x >= MinWidth Then        
      If Width - _x <= MaxWidth then

        Width -= _x
        Left += _x

      End If
    End If

  End Sub

  Private Sub Resize_Width_Right

    _x += CURSOR_OFFSET_LARGE

    Select Case _x

      Case Is < MinWidth : width = MinWidth
      Case Is > MaxWidth : Width = MaxWidth

      Case Else : Width = _x

    End Select

  End Sub

  Private Sub Resize_Height_Top

    _y -= CURSOR_OFFSET_SMALL

    If Height - _y >= MinHeight Then        
      If Height - _y <= MaxHeight then

        Height -= _y
        Top += _y

      End If
    End If

  End Sub

  Private Sub Resize_Height_Bottom

    _y += CURSOR_OFFSET_SMALL

    Select Case _y

      Case Is < MinHeight : Height = MinHeight
      Case Is > MaxHeight : Height = MaxHeight

      Case Else : Height = _y

    End Select

  End Sub

  Private Sub Move(ByVal sender As Object, _
                    ByVal e As System.Windows.Input.MouseButtonEventArgs)

    Dim curs As Cursor = Cursor

    Cursor = Cursors.SizeAll

    DragMove()

    Cursor = Curs

  End Sub

  Private Sub _Close()

    Close

  End Sub

End Class

Ответ 2

Для минималистского подхода

  • Установите цвет Brush_ChromeBackground на "Прозрачный". Это делает невидимым прямоугольники перетаскивания.
  • Установите для параметра Window ResizeMode значение "NoResize". Это скрывает серый скошенный край вокруг окна, оставляя только 1px Border_Chrome.

Кроме того, я перевел код на С#:

public partial class Article_1 : Window
{
    private bool _isResizing = false;
    private const double CURSOR_OFFSET_SMALL = 3;
    private const double CURSOR_OFFSET_LARGE = 5;

    public Article_1()
    {
        InitializeComponent();
        MinWidth = Math.Max(MinWidth, Rectangle_MiddleLeft.Width + Rectangle_MiddleRight.Width + 10);
        MinHeight = Math.Max(MinHeight, Rectangle_TopMiddle.Height + Rectangle_BottomMiddle.Height + 10);
    }

    private void Resize_Begin(object sender, MouseButtonEventArgs e)
    {
        if (sender is Rectangle)
        {
            _isResizing = true;
            ((Rectangle)sender).CaptureMouse();
        }
    }

    private void Resize_End(object sender, MouseButtonEventArgs e)
    {
        if (sender is Rectangle)
        {
            _isResizing = false;
            ((Rectangle)sender).ReleaseMouseCapture();
        }
    }

    private void Resize(object sender, MouseEventArgs e)
    {
        if (_isResizing && (sender is Rectangle))
        {
            double x = e.GetPosition(this).X;
            double y = e.GetPosition(this).Y;

            string mode = ((Rectangle)sender).Name.ToLower();
            if (mode.Contains("left"))
            {
                x -= CURSOR_OFFSET_SMALL;
                if ((Width - x >= MinWidth) && (Width - x <= MaxWidth))
                {
                    Width -= x;
                    Left += x;
                }
            }
            if (mode.Contains("right"))
            {
                Width = Math.Max(MinWidth, Math.Min(MaxWidth, x + CURSOR_OFFSET_LARGE));
            }
            if (mode.Contains("top"))
            {
                y -= CURSOR_OFFSET_SMALL;
                if ((Height - y >= MinHeight) && (Height - y <= MaxHeight))
                {
                    Height -= y;
                    Top += y;
                }
            }
            if (mode.Contains("bottom"))
            {
                Height = Math.Max(MinHeight, Math.Min(MaxHeight, y + CURSOR_OFFSET_SMALL));
            }
        }
    }

    private void Move(object sender, MouseButtonEventArgs e)
    {
        Cursor old = Cursor;
        Cursor = Cursors.SizeAll;
        DragMove();
        Cursor = old;
    }

    private void Close(object sender, MouseButtonEventArgs e)
    {
        Close();
    }
}