Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Custom Window W/Full Windows Functionality

0.00/5 (No votes)
18 Jan 2013 1  
WPF Custom Window W/Full Windows Functionality.

Introduction

Create a custom WPF window with full Windows functionality, not just partial.

Background

I fought for quite a while to get this working and found many snipe hunt trails along the way, or people that share small samples that work for only partial solutions or only work for the bottom resizing because the solution was not compatible all the way around. This is a full solution that is about 98% complete. I still have not perfected the upper left, upper right, and lower left corners. I will be finishing this up in the near future, but for now here is what I have.

Using the code

This code is used for XAML and WPF solutions with C#. 

The following is the XAML to get you started. Theses are the invisible rectangles that will border your window and monitor mousedowns etc...  I have written a quick project demo for anyone that can't make heads or tails of the poor formatting below. 

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Converters="clr-namespace:StenoViewerAndWriter.Converters" 
        Closed="MainWindowClosed" 
        AllowsTransparency="True"
        WindowStyle="None"
        BorderBrush="DarkGray"
        BorderThickness="2"
        MinHeight="500"
        MinWidth="700"
        SizeChanged="Window_SizeChanged" 
        KeyUp="Window_KeyUp"
        WindowStartupLocation="CenterScreen"
        MouseLeftButtonDown="Window_MouseLeftButtonDown"
        MouseLeftButtonUp="Window_MouseLeftButtonUp"
        MouseDoubleClick="Window_MouseDoubleClicked"
        ResizeMode="CanResizeWithGrip"> 
 <Grid> 
 <StackPanel x:Name="spWindowsButtons" Orientation="Horizontal" 
 VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,5,10,0" >
      
            <Button Background="Transparent" Padding="0" 
            Height="18" Click="btnMinimize_Clicked" BorderBrush="Transparent">
                  <Image x:Name="btnMin" 
                  Source="Images/MinimizeIcon.png" Height="15" Width="15" 
                  VerticalAlignment="Top" HorizontalAlignment="Right" />
            </Button>
            <Button Background="Transparent" Padding="0" 
            Height="18" Margin="10,0,0,0" Click="btnMaxRestore_Clicked" 
            BorderBrush="Transparent">
                <Image x:Name="btnMaxAndRestore" Source="Images/MaximizeIcon.png" 
                Height="15" Width="15" VerticalAlignment="Top" 
                HorizontalAlignment="Right" />
            </Button>
            <Button Background="Transparent" Padding="0" Height="18" 
            Margin="10,0,0,0" Click="btnClose_Clicked" BorderBrush="Transparent">
                <Image x:Name="btnClose" Source="Images/closeIcon.png" 
                Height="15" Width="15" VerticalAlignment="Top" 
                HorizontalAlignment="Right" />
            </Button>
        </StackPanel> 
        <Rectangle x:Name="DragHandleTopLeft" 
        MouseMove="DragHandle_MouseMove" MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter" Cursor="SizeNWSE" 
        Fill="Transparent" Margin="-5,-5,0,0" HorizontalAlignment="Left" 
        VerticalAlignment="Top" Height="15" Width="15" 
        MouseLeftButtonDown="DragHandle_MouseLeftButtonDown"/>
        <Rectangle x:Name="DragHandleTopRight" MouseMove="DragHandle_MouseMove" 
        MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"   Cursor="SizeNESW" 
        Fill="Transparent" Margin="0,-5,-5,0" 
        HorizontalAlignment="Right" VerticalAlignment="Top" 
        Height="15" Width="15" MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
        <Rectangle x:Name="DragHandleBottomLeft" 
        MouseMove="DragHandle_MouseMove" MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"  Cursor="SizeNESW" 
        Fill="Transparent" Margin="-5,0,0,-5" 
        HorizontalAlignment="Left" VerticalAlignment="Bottom" 
        Height="15" Width="15" 
        MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
        <Rectangle x:Name="DragHandleBottomRight" 
        MouseMove="DragHandle_MouseMove" MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"   Cursor="SizeNWSE" 
        Fill="Transparent" Margin="0,0,-5,-5" 
        HorizontalAlignment="Right" VerticalAlignment="Bottom" 
        Height="15" Width="15" 
        MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
        <Rectangle x:Name="DragHandleLeft" 
        MouseMove="DragHandle_MouseMove" MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"  Cursor="SizeWE" 
        Fill="Transparent" HorizontalAlignment="Left" 
        Margin="-5,10,0,10" Width="10" MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
        <Rectangle x:Name="DragHandleRight" 
        MouseMove="DragHandle_MouseMove" MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"  Cursor="SizeWE" Fill="Transparent" 
        HorizontalAlignment="Right" Margin="0,10,-5,10" Width="10" 
        MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
        <Rectangle x:Name="DragHandleTop" MouseMove="DragHandle_MouseMove" 
        MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
        MouseEnter="DragHandle_MouseEnter"  Cursor="SizeNS" 
        Fill="Transparent" VerticalAlignment="Top" Margin="10,-5,10,0" 
        Height="10" MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" />
            <Rectangle x:Name="DragHandleBottom" 
            MouseEnter="DragHandle_MouseEnter" Cursor="SizeNS" 
            Fill="Transparent" VerticalAlignment="Bottom" 
            Margin="10,0,10,-5" Height="10" 
            MouseLeftButtonUp="DragHandle_MouseLeftButtonUp" 
            MouseLeftButtonDown="DragHandle_MouseLeftButtonDown" 
            MouseMove="DragHandle_MouseMove" />

</Grid> 
</Window>
//Here is the C# Code Behind for this stuff 
private bool _isResizing;
private double _initY;
private double _initX;
  
private void btnClose_Clicked(object sender, RoutedEventArgs routedEventArgs)
{
    this.Close();
} 
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (!_isResizing)
        this.DragMove();
}
private void Window_MouseDoubleClicked(object sender, MouseButtonEventArgs e)
{
    ToggleWindowSize();
}
private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    _isResizing = false;
}
//Drag Handlers
private void DragHandle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    _isResizing = false;
    switch (direction)
    {
        case ResizeDirection.Top:
            DragHandleTop.ReleaseMouseCapture();
            break;
        case ResizeDirection.Bottom:
            DragHandleBottom.ReleaseMouseCapture();
            break;
        case ResizeDirection.Left:
            DragHandleLeft.ReleaseMouseCapture();
            break;
        case ResizeDirection.Right:
            DragHandleRight.ReleaseMouseCapture();
            break;
        case ResizeDirection.TopLeft:
            DragHandleTopLeft.ReleaseMouseCapture();
            break;
        case ResizeDirection.BottomRight:
            DragHandleBottomRight.ReleaseMouseCapture();
            break;
        case ResizeDirection.TopRight:
            DragHandleTopRight.ReleaseMouseCapture();
            break;
        case ResizeDirection.BottomLeft:
            DragHandleBottomLeft.ReleaseMouseCapture();
            break;
        default:
            this.Cursor = Cursors.Arrow;
            break;
    }
}
private void DragHandle_MouseEnter(object sender, MouseEventArgs e)
{
    if (e.LeftButton != MouseButtonState.Pressed)
        _isResizing = false;
}
private void DragHandle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    _initY = this.PointToScreen(e.GetPosition(this)).Y;
    _initX = this.PointToScreen(e.GetPosition(this)).X;
    _isResizing = true;
}
private void DragHandle_MouseMove(object sender, MouseEventArgs e)
{
    if (!_isResizing)
        return;

    FrameworkElement element = sender as FrameworkElement;
    string enumName = element.Name.Replace("DragHandle", "");
    direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), enumName);

    double newY = this.PointToScreen(e.GetPosition(this)).Y;
    double newX = this.PointToScreen(e.GetPosition(this)).X;
    double diff;
    double newHeight;
    double newWidth;

    switch (direction)
    {
        case ResizeDirection.Top:
            {
                diff = _initY - newY;
                newHeight = this.Height + diff;

                //ShowTestData = "Old Height=" + this.Height + "New Height=" + 
                //  newHeight.ToString() + " and Diff" + diff;
                if (newHeight >

Points of Interest

This is a huge pain in the butt and requires a little math and some patience. However this should be copy and pasteable code to help you get started.

History

Version 1: I have not made a demo project as this is in a corporate project that I cannot share, so all I can share is the code, but it does fully function. Hopefully I included everything you will need in the above.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here