Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / WPF
Tip/Trick

WPF Custom Window W/Full Windows Functionality

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
18 Jan 2013CPOL1 min read 20.8K   13   5
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. 

XML
<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>
C#
//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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSource Pin
Konstantin Glushakov27-Jan-13 8:35
Konstantin Glushakov27-Jan-13 8:35 
AnswerRe: Source Pin
jiju chovva10-Feb-13 14:48
jiju chovva10-Feb-13 14:48 
Try this one - a working version of custom window.

https://github.com/MahApps/MahApps.Metro[^]
QuestionIncomplete! Pin
FatCatProgrammer6-Nov-12 9:12
FatCatProgrammer6-Nov-12 9:12 
QuestionThe code is truncated... Pin
gabbby694-Nov-12 7:05
gabbby694-Nov-12 7:05 
AnswerRe: The code is truncated... Pin
Programmer355-Nov-12 8:02
Programmer355-Nov-12 8:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.