Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF/XAML: How do I size a window with no border?

I am using a window with no border and drawing the Chrome myself. I want to resize the window in a typical manner and have defined a 3x3 grid with the center being the content and the outer cells constituting the respective areas requiring different treatment (TopLeft/TopMiddle/TopRight... etc.) such as cursors. Maximize, Minimize, Move etc are all straight forward but I could use some pointers to resize in various directions based on the cell the cursor is over.

like image 553
Brad Avatar asked Jan 21 '10 18:01

Brad


People also ask

What is the difference between page and window in WPF?

Window is the root control that must be used to hold/host other controls (e.g. Button) as container. Page is a control which can be hosted in other container controls like NavigationWindow or Frame. Page control has its own goal to serve like other controls (e.g. Button). Page is to create browser like applications.

How do I open a WPF window in full screen?

Just set the WindowState to Maximized , and the WindowStyle to None . Also setting the Window as topmost will make sure no other Window shows up over your window.

How do I display a WPF window?

When a Window is created at run-time using the Window object, it is not visible by default. To make it visible, we can use Show or ShowDialog method. Show method of Window class is responsible for displaying a window.


2 Answers

This seems pretty tight. Min/Max width and Height are accounted for as well as variable borderwidths. The only issue I'm aware of is when the cursor movement is rapid and the size is within 20 pix of the min it sticks somewhat because of refresh rate. Not a huge deal but I'll sort it.

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

I can't seem to get the Window tag to display properly...(Just take out the apostrophe and it should be fine.) Anyone have any thoughts?

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>

Code Behind

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
like image 93
13 revs Avatar answered Oct 10 '22 11:10

13 revs


For a minimalist approach,

  1. Set the Brush_ChromeBackground color to "Transparent". This makes the drag rectangles invisible.
  2. Set the Window's ResizeMode to "NoResize". This hides the grey bevelled edge around the window, leaving the 1px Border_Chrome only.

Also, I translated the code-behind to C#:

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();
    }
}
like image 35
user404601 Avatar answered Oct 10 '22 11:10

user404601