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>
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;
}
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;
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.