Setting an XAML Window always on top (but no TopMost property) - c#

I am developing an application based on OptiTrack SDK (from NaturalPoint). I need to run the application window as "Always on Top". The window is designed in XAML and is controled in the class "CameraView" but it does not seem to include a "TopMost" property or equivalent. Attached are the code of "CameraView.xaml.cs" and the code of "CameraView.xaml" that are part of OptiTrack SDK (NaturalPoint) called "Single_Camera_CSharp_.NET_3.0".
One could expect the class CameraView to contain properties or members to set the position of the window on the screen or to set it to TopMost but as far as searched I found nothing. I wonder what I should do.
Thank you,
Brian
================
"CameraView.xaml.cs"
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Threading;
namespace TestProject
{
public partial class CameraView
{
private const int NP_OPTION_OBJECT_COLOR_OPTION = 3;
private const int NP_OPTION_VIDEO_TYPE = 48;
private const int NP_OPTION_NUMERIC_DISPLAY_ON = 71;
private const int NP_OPTION_NUMERIC_DISPLAY_OFF = 72;
private const int NP_OPTION_FETCH_RLE = 73;
private const int NP_OPTION_FETCH_GRAYSCALE = 74;
private const int NP_OPTION_FRAME_DECIMATION = 52;
private const int NP_OPTION_INTENSITY = 50;
private const int NP_OPTION_SEND_EMPTY_FRAMES = 41;
private const int NP_OPTION_THRESHOLD = 5;
private const int NP_OPTION_EXPOSURE = 46;
private const int NP_OPTION_SEND_FRAME_MASK = 73;
private const int NP_OPTION_TEXT_OVERLAY_OPTION = 74;
// public delegate void OnCameraViewCreate(CameraView camera);
// public static OnCameraViewCreate onCameraViewCreate;
private System.Drawing.Bitmap raw = new System.Drawing.Bitmap(353, 288, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
private int mFrameCounter;
private int mDisplayCounter;
private DispatcherTimer timer1 = new DispatcherTimer();
private bool mVideoFrameAvailable = false;
private int mNumeric = -1;
private bool mGreyscale = false;
private bool mOverlay = true;
public CameraView()
{
this.InitializeComponent();
timer1.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer1.Tick += new EventHandler(timer1_Tick);
}
public int Numeric
{
get { return mNumeric; }
set
{
mNumeric = value % 100;
if (mNumeric >= 0)
{
if (Camera != null)
Camera.SetOption(NP_OPTION_NUMERIC_DISPLAY_ON, value % 100);
}
}
}
private bool CameraRunning = false;
private OptiTrack.NPCamera mCamera;
public OptiTrack.NPCamera Camera
{
get { return mCamera; }
set
{
if (mCamera == value) return; //== Don't do anything if you're assigning the same camera ==
if (mCamera != null)
{
//== Shut the selected camera down ==<<
if (CameraRunning)
{
CameraRunning = false;
mCamera.Stop();
mCamera.FrameAvailable -= FrameAvailable;
}
}
mCamera = value;
if (mCamera == null)
{
mNumeric = -1;
}
else
{
serialLabel.Content = "Camera "+mCamera.SerialNumber.ToString(); //mNumeric.ToString();
}
}
}
private void FrameAvailable(OptiTrack.NPCamera Camera)
{
mFrameCounter++;
try
{
OptiTrack.NPCameraFrame frame = Camera.GetFrame(0);
int id = frame.Id;
if (CameraRunning)
{
GetFrameData(Camera, frame);
}
frame.Free();
}
catch (Exception)
{
int r = 0;
r++;
}
}
private void GetFrameData(OptiTrack.NPCamera camera, OptiTrack.NPCameraFrame frame)
{
BitmapData bmData = raw.LockBits(new System.Drawing.Rectangle(0, 0, raw.Width, raw.Height),
ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int stride = bmData.Stride;
System.IntPtr bufferPtr = bmData.Scan0;
unsafe
{
byte* buffer = (byte*)(void*)bufferPtr;
camera.GetFrameImage(frame, bmData.Width, bmData.Height, bmData.Stride, 32, ref buffer[0]);
}
raw.UnlockBits(bmData);
mVideoFrameAvailable = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
if (CameraRunning && mVideoFrameAvailable)
{
mVideoFrameAvailable = false;
cameraImage.Source = Img(raw);
mDisplayCounter++;
}
}
private System.Windows.Media.ImageSource Img(System.Drawing.Bitmap img)
{
System.Drawing.Imaging.BitmapData bmData = img.LockBits(new System.Drawing.Rectangle(0, 0, img.Width, img.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
System.Windows.Media.Imaging.BitmapSource bitmap = System.Windows.Media.Imaging.BitmapSource.Create(
img.Width, img.Height, 96, 96, PixelFormats.Bgra32,
System.Windows.Media.Imaging.BitmapPalettes.WebPalette,
bmData.Scan0, bmData.Stride * bmData.Height, bmData.Stride);
img.UnlockBits(bmData);
return bitmap;
}
private void startStopButton_Click(object sender, RoutedEventArgs e)
{
if (CameraRunning)
StopCamera();
else
StartCamera();
}
public void StartCamera()
{
if (Camera != null)
{
mFrameCounter = 0;
mDisplayCounter = 0;
Camera.FrameAvailable += FrameAvailable;
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 0);
Camera.SetOption(NP_OPTION_FRAME_DECIMATION, 1);
Camera.SetOption(NP_OPTION_INTENSITY, 0);
Camera.SetOption(NP_OPTION_EXPOSURE, 10);
Camera.SetOption(NP_OPTION_THRESHOLD, 50);
Camera.SetOption(NP_OPTION_OBJECT_COLOR_OPTION, 0);
SetOverlayOption();
SetGreyscaleOption();
timer1.Start();
Camera.Start();
CameraRunning = true;
this.Numeric = mNumeric;
startStopButton.Content = "Stop Camera";
}
}
private void SetGreyscaleOption()
{
if(mGreyscale)
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 1);
else
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 0);
}
private void SetOverlayOption()
{
if(mOverlay)
Camera.SetOption(NP_OPTION_TEXT_OVERLAY_OPTION, 255);
else
Camera.SetOption(NP_OPTION_TEXT_OVERLAY_OPTION, 0);
}
public void StopCamera()
{
if (Camera != null)
{
Camera.Stop();
timer1.Stop();
CameraRunning = false;
Camera.FrameAvailable -= FrameAvailable;
Camera.SetOption(NP_OPTION_NUMERIC_DISPLAY_OFF, 0);
startStopButton.Content = "Start Camera";
}
}
private void greyscaleButton_Click(object sender, RoutedEventArgs e)
{
if(mGreyscale)
mGreyscale = false;
else
mGreyscale = true;
SetGreyscaleOption();
}
private void OverlayButton_Click(object sender, RoutedEventArgs e)
{
if(mOverlay)
mOverlay = false;
else
mOverlay = true;
SetOverlayOption();
}
private void exposureSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (mCamera!=null)
{
mCamera.SetOption(NP_OPTION_EXPOSURE, (int) this.exposureSlider.Value);
}
}
private void thresholdSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (mCamera != null)
{
mCamera.SetOption(NP_OPTION_THRESHOLD, (int)this.thresholdSlider.Value);
}
}
private void optionsButton_Click(object sender, RoutedEventArgs e)
{
if (!propertyPanel.IsVisible)
propertyPanel.Visibility = Visibility.Visible;
else
propertyPanel.Visibility = Visibility.Collapsed;
}
}
}
================
"CameraView.xaml"
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestProject.CameraView"
x:Name="CameraView1"
Width="Auto" Height="Auto"
xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<Grid x:Name="LayoutRoot" Width="Auto" Height="Auto">
<Grid.Background>
<x:Null/>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="113.904"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="26.667"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="0,0,0,0" Grid.ColumnSpan="2">
<Rectangle RadiusX="1.25" RadiusY="1.25" Margin="0,0,0,0" VerticalAlignment="Stretch">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.492,0.149" StartPoint="0.492,0.843">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FF23283F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.291,-4.231" StartPoint="1.668,18.025">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Rectangle RadiusX="3.333" RadiusY="3.333" Opacity="0.13" Margin="0,0,0,13">
<Rectangle.Fill>
<SolidColorBrush Color="#FFFFFFFF"/>
</Rectangle.Fill>
<Rectangle.Stroke>
<x:Null/>
</Rectangle.Stroke>
</Rectangle>
</Grid>
<Image Margin="0,0,0,0" x:Name="cameraImage" Grid.ColumnSpan="2" Grid.Row="1"/>
<Label x:Name="serialLabel" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Camera 10024" HorizontalAlignment="Right" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="1">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<WrapPanel Margin="3,3,3,3">
<Button HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="startStopButton" Width="100" Height="Auto" BorderThickness="0,0,0,0" Content="Start Camera" Click="startStopButton_Click"/>
<Button x:Name="optionsButton" Width="61.474" Height="Auto" BorderThickness="0,0,0,0" Content="Options" Click="optionsButton_Click"/>
</WrapPanel>
<Grid Visibility="Visible" d:LayoutOverrides="HorizontalAlignment, VerticalAlignment" HorizontalAlignment="Right" Margin="0,0,16,16" x:Name="propertyPanel" VerticalAlignment="Bottom" Width="169.237" Height="81.455" Grid.ColumnSpan="2" Grid.Row="1">
<Rectangle Stroke="#FFFFFFFF" StrokeThickness="3" Margin="0,0,0,0">
<Rectangle.BitmapEffect>
<DropShadowBitmapEffect/>
</Rectangle.BitmapEffect>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF1E212F" Offset="0"/>
<GradientStop Color="#FF313551" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Slider HorizontalAlignment="Stretch" Margin="62.633,5,4.681,0" x:Name="exposureSlider" VerticalAlignment="Top" Width="Auto" Height="Auto" Orientation="Horizontal" Maximum="255" ValueChanged="exposureSlider_ValueChanged"/>
<Label x:Name="serialLabel_Copy" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Exposure" HorizontalAlignment="Left" Margin="3.853,3.853,0,0" VerticalAlignment="Top" Width="57.352">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<Label x:Name="serialLabel_Copy1" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Threshold" d:LayoutOverrides="Height" HorizontalAlignment="Left" Margin="3.853,27.691,0,0" VerticalAlignment="Top" Width="59.829">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<Slider x:Name="thresholdSlider" Width="Auto" Orientation="Horizontal" Maximum="253" d:LayoutOverrides="Height, Margin" Margin="62.633,27.691,4.681,0" VerticalAlignment="Top" Minimum="54" Value="54" ValueChanged="thresholdSlider_ValueChanged"/>
<Button x:Name="greyScaleButton" Width="75.333" Content="Greyscale" Click="greyscaleButton_Click" HorizontalAlignment="Left" Height="21" d:LayoutOverrides="Height" Margin="8,53.761,0,0" VerticalAlignment="Top"/>
<Button x:Name="Overlay" Height="21" Content="Overlay" Click="OverlayButton_Click" d:LayoutOverrides="Height" HorizontalAlignment="Right" Margin="0,53.761,8,0" VerticalAlignment="Top" Width="64"/>
</Grid>
</Grid>
</UserControl>

The Topmost property exists on the Window class: http://msdn.microsoft.com/en-us/library/system.windows.window.topmost.aspx.
Your CameraView class is derived from UserControl, which is a kind of control that sits inside a Window (or other container such as a Page, but that's not important here). UserControl doesn't have a Topmost property because it doesn't appear independently on the desktop.
Host your CameraView in a Window and set the Window.Topmost:
<!-- MyWindow.xaml -->
<Window ...
xmlns:local="clr-namespace:TestProject"
Topmost="True">
<local:CameraView />
</Window>
where the ellipses represent the default gunk like x:Class and WPF xmlns declarations that Visual Studio creates for you.

In the UserControl code behind, you can get a reference to the window that is hosting it, then set the Topmost property. Example,
Window parent = Window.GetWindow(this);
parent.Topmost = true;

This is UserControl. You can set TopMost property for Windows only

Related

Child window is blocking the main thread

I'm using a user control I found online to express processing.
What I'm trying to do is showing a window containing this user control until main thread finishes processing.
This is the user control code:
public partial class CircularProgressBar
{
#region Data
private readonly DispatcherTimer animationTimer;
#endregion
#region Constructor
public CircularProgressBar()
{
InitializeComponent();
animationTimer = new DispatcherTimer( DispatcherPriority.ContextIdle, Dispatcher);
animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 75);
}
#endregion
#region Private Methods
private void Start()
{
Mouse.OverrideCursor = Cursors.Wait;
animationTimer.Tick += HandleAnimationTick;
animationTimer.Start();
}
private void Stop()
{
animationTimer.Stop();
Mouse.OverrideCursor = Cursors.Arrow;
animationTimer.Tick -= HandleAnimationTick;
}
private void HandleAnimationTick(object sender, EventArgs e)
{
SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
}
private void HandleLoaded(object sender, RoutedEventArgs e)
{
const double offset = Math.PI;
const double step = Math.PI * 2 / 10.0;
SetPosition(C0, offset, 0.0, step);
SetPosition(C1, offset, 1.0, step);
SetPosition(C2, offset, 2.0, step);
SetPosition(C3, offset, 3.0, step);
SetPosition(C4, offset, 4.0, step);
SetPosition(C5, offset, 5.0, step);
SetPosition(C6, offset, 6.0, step);
SetPosition(C7, offset, 7.0, step);
SetPosition(C8, offset, 8.0, step);
}
private void SetPosition(Ellipse ellipse, double offset, double posOffSet, double step)
{
ellipse.SetValue(Canvas.LeftProperty, 50.0 + Math.Sin(offset + posOffSet * step) * 50.0);
ellipse.SetValue(Canvas.TopProperty, 50 + Math.Cos(offset + posOffSet * step) * 50.0);
}
private void HandleUnloaded(object sender, RoutedEventArgs e)
{
Stop();
}
private void HandleVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
bool isVisible = (bool)e.NewValue;
if (isVisible)
Start();
else
Stop();
}
#endregion
}
XAML:
<UserControl Height="Auto" Width="Auto" Background="Transparent" IsVisibleChanged="HandleVisibleChanged">
<Grid x:Name="LayoutRoot" Background="Transparent" ToolTip="Searching...." HorizontalAlignment="Center" VerticalAlignment="Center">
<Canvas RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center"
VerticalAlignment="Center" Width="120"
Height="120" Loaded="HandleLoaded"
Unloaded="HandleUnloaded" >
<Ellipse x:Name="C0" Width="20" Height="20" Canvas.Left="0" Canvas.Top="0" Stretch="Fill" Fill="Black" Opacity="1.0"/>
<Ellipse x:Name="C1" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.9"/>
<Ellipse x:Name="C2" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.8"/>
<Ellipse x:Name="C3" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.7"/>
<Ellipse x:Name="C4" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.6"/>
<Ellipse x:Name="C5" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.5"/>
<Ellipse x:Name="C6" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.4"/>
<Ellipse x:Name="C7" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.3"/>
<Ellipse x:Name="C8" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.2"/>
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotate"
Angle="0" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</UserControl>
I'm using this user control in a window and calling this window when I start processing using:
private void ThreadStartingPoint()
{
Window.Show();
Window.Focus();
System.Windows.Threading.Dispatcher.Run();
}
This is blocking the execution of main thread, I do not know what wrong I have done as I'm new to this.
Dispatcher.Run is certainly blocking. You cannot call this method on the main thread without blocking.
If you want to create a new window on a dedicated thread for some reason, you could refer to #Reed Copsey's blog post:
Launching a WPF Window in a Separate Thread, Part 1: http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/
It explains how to do this properly:
// Create a thread
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
Window1 tempWindow = new Window1();
tempWindow.Content = new CircularProgressBar();
// When the window closes, shut down the dispatcher
tempWindow.Closed += (s, e) =>
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
tempWindow.Show();
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();

WPF Custom Window Maximization Problems

I'm quite new to WPF and am trying to build a GUI in Blend, but I'm running into all sorts of issues.
I want my finished product to look like this: https://imgur.com/a/BU8Te
(the red is just a placeholder for icons).
Here is the XAML I've got so far:
<Window x:Class="GUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GUI"
mc:Ignorable="d"
Title="GUI"
Height="840"
Width="920"
WindowStyle="none"
ResizeMode="CanResizeWithGrip"
AllowsTransparency="true"
MouseLeftButtonDown="Window_MouseLeftButtonDown"
WindowStartupLocation="CenterScreen"
Background="Transparent"
MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}">
<Border x:Name="shadow">
<Grid x:Name="grid" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="100"/>
<RowDefinition Height="2"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#F9F9F9" />
<Border Grid.Row="1" Background="#F9F9F9" />
<Border Grid.Row="2" Background="#E9E9E9" />
<DockPanel Grid.Row="0" LastChildFill="False">
<Button x:Name="btnClose"
DockPanel.Dock="Right"
VerticalAlignment="Center"
Height="20" Width="20"
Click="btnClose_Click"
Style="{DynamicResource CloseButton}">
<Path Data="m 357.0883 499.0572 12.62375 12.6275 5.31375 -5.31625 -12.62625 -12.62625 12.62625 -12.61875 -5.31375 -5.3125 -12.62375 12.62 -12.6325 -12.62 -5.30375 5.3125 12.6175 12.61875 -12.6175 12.62625 5.30375 5.31625 12.6325 -12.6275 z" Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,0" ></Path>
</Button>
<Button x:Name="btnMaximise"
DockPanel.Dock="Right"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="20" Width="20"
Click="btnMaximise_Click"
Style="{DynamicResource TitleButton}">
<Path Data="M4.3685131,23.127279L4.3685131,47.283243 47.117023,47.283243 47.117023,23.127279z M0,10.684L53.755001,10.684 53.755001,51.668001 0,51.668001z M8.5679998,0L58.668022,0 64,0 64,5.6864691 64,45.317999 58.668022,45.317999 58.668022,5.6864691 8.5679998,5.6864691z"
Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,0" ></Path>
</Button>
<Button x:Name="btnMinimise"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DockPanel.Dock="Right"
Height="20" Width="20"
Click="btnMinimise_Click"
VerticalContentAlignment="Bottom"
Style="{DynamicResource TitleButton}">
<Button.Content>
<Path Data="M0,20L53.333,20 53.333,8.888 0,8.888z"
Stretch="Uniform" Fill="#FFAAAAAA" Width="10" Margin="0,0,0,5"></Path>
</Button.Content>
</Button>
</DockPanel>
</Grid>
</Border>
</Window>
But when I maximise the window, the top left corner is off my screen (-15, -15 maybe?) and the bottom right corner is also too far up and left because of this. I modified some code that I found online (can't remember the source) which fixed this:
private bool isMaximized;
private Rect normalBounds;
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized && !isMaximized)
{
// max
WindowState = WindowState.Normal;
isMaximized = true;
normalBounds = RestoreBounds;
Height = SystemParameters.WorkArea.Height;
MaxHeight = Height;
MinHeight = Height;
Top = 0;
Left = 0;
Width = SystemParameters.WorkArea.Width;
SetMovable(false);
}
else if (WindowState == WindowState.Maximized && isMaximized)
{
// min
WindowState = WindowState.Normal;
isMaximized = false;
MaxHeight = Double.PositiveInfinity;
MinHeight = 0;
Top = normalBounds.Top;
Left = normalBounds.Left;
Width = normalBounds.Width;
Height = normalBounds.Height;
SetMovable(true);
}
}
private void SetMovable(bool enable)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if (enable)
source.RemoveHook(WndProc);
else
source.AddHook(WndProc);
}
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
switch (msg)
{
case WM_SYSCOMMAND:
int command = wParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
handled = true;
break;
}
return IntPtr.Zero;
}
Now that works perfectly, but I'm really struggling to get this to work with a drop shadow on the window. When I add a 10px border to the window and set the dropshadow on this, I get the resizing icon in my border and not in my window:
https://imgur.com/a/S9oLK
I also had to modify the StateChanged event method to hide the border when maximised:
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized && !isMaximized)
{
// max
WindowState = WindowState.Normal;
isMaximized = true;
normalBounds = RestoreBounds;
Height = SystemParameters.WorkArea.Height;
MaxHeight = Height;
MinHeight = Height;
Top = 0;
Left = 0;
Width = SystemParameters.WorkArea.Width;
SetMovable(false);
this.grid.Margin = new Thickness(0);
this.BorderThickness = new Thickness(0);
}
else if (WindowState == WindowState.Maximized && isMaximized)
{
// min
WindowState = WindowState.Normal;
isMaximized = false;
MaxHeight = Double.PositiveInfinity;
MinHeight = 0;
Top = normalBounds.Top;
Left = normalBounds.Left;
Width = normalBounds.Width;
Height = normalBounds.Height;
SetMovable(true);
this.grid.Margin = new Thickness(10);
this.BorderThickness = new Thickness(10);
}
}
But this obviously doesn't work when the window is snapped to the edge of a screen: https://i.imgur.com/pGC1fio.png
To summarise, my issues are:
Resize grabber is in border not main window.
I don't know how to hide the border when the window is snapped to the edge of the screen.
Is there a simple way to fix this? I feel like I'm having to create a very hacky fix for all of this and thought it would be a lot easier to implement a custom window like this.
Thanks in advance for any help.

WPF scrolling marquee - HandOffBehavior

I am trying to figure out how to best use WPF's HandOffBehavior technique. Right now, I have a scrolling error marquee in my application that animates opening up, scrolling the error message, and then closing itself.
I was just starting to build this WPF application this week. The problem is that I can't seem to gracefully prepare for a scenario like when the user clicks the Login button twice or more times in small consecutive intervals. I would like to see the error marquee only continue sending the error text across the screen when the user commits such behavior with the login button rather than open and close the marquee multiple redundant times, etc. Here's the relevant code.
MainWindow.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.Entity;
using System.Windows.Media.Animation;
using PasswordHash;
namespace ChatClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void logIn(object sender, RoutedEventArgs e)
{
string nameRecord = "";
string passRecord = "";
if (UsernameField.Text == "" || UserPassField.Password == "")
{
openErrorMarquee("Username and password required");
}
else
{
using (otongadgethubEntities logCheck = new otongadgethubEntities())
{
var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text);
if (userNullCheck == null)
{
openErrorMarquee("Username does not exist");
}
if (userNullCheck != null)
{
nameRecord = userNullCheck.username;
}
if (nameRecord == UsernameField.Text)
{
passRecord = Encrypt.MD5(UserPassField.Password).ToLower();
if (passRecord == userNullCheck.password)
{
//Yay! User logged in!
}
else
{
openErrorMarquee("Password invalid");
}
}
}
}
}
private void openErrorMarquee(string errorMessage)
{
errorMarquee.Visibility = System.Windows.Visibility.Visible;
DoubleAnimation openMarquee = new DoubleAnimation();
openMarquee.From = 0;
openMarquee.To = 17;
openMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0));
openMarquee.Completed += (s, doneEvent) => errorMarqueeScroll(errorMessage);
errorMarquee.BeginAnimation(Rectangle.HeightProperty, openMarquee, HandoffBehavior.Compose);
}
private void errorMarqueeScroll(string errorMessage)
{
errorText.Text = errorMessage;
errorText.Visibility = System.Windows.Visibility.Visible;
double height = errorCanvas.ActualHeight - errorText.ActualHeight;
errorText.Margin = new Thickness(0, height / 2, 0, 0);
DoubleAnimation doubleErrorAnimation = new DoubleAnimation();
doubleErrorAnimation.From = -errorText.ActualWidth;
doubleErrorAnimation.To = errorCanvas.ActualWidth;
//doubleErrorAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleErrorAnimation.Completed += new EventHandler(closeErrorMarquee);
doubleErrorAnimation.Duration = new Duration(TimeSpan.FromSeconds(7.0));
errorText.BeginAnimation(Canvas.RightProperty, doubleErrorAnimation);
}
private void closeErrorMarquee(object sender, EventArgs e)
{
DoubleAnimation closeMarquee = new DoubleAnimation();
closeMarquee.From = 17;
closeMarquee.To = 0;
closeMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0));
closeMarquee.Completed += (s, doneEvent) => {
errorMarquee.Visibility = System.Windows.Visibility.Hidden;
errorText.Visibility = System.Windows.Visibility.Hidden;
};
errorMarquee.BeginAnimation(Rectangle.HeightProperty, closeMarquee, HandoffBehavior.Compose);
}
}
}
And here's the XAML for those that need to see the window too:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="ChatClient.MainWindow"
Title="MainWindow" Height="350" Width="525" Icon="media/favicon.gif" Background="#FF3C3636" Foreground="{x:Null}">
<Window.Resources>
<Storyboard x:Key="logolayer2excompsoundfad_mp4"/>
</Window.Resources>
<Window.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FF6F6D95" Offset="1"/>
</LinearGradientBrush>
</Window.BorderBrush>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource logolayer2excompsoundfad_mp4}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Rectangle x:Name="Menu" Fill="#755E5E83" HorizontalAlignment="Left" Height="273" Margin="35,23,0,0" Stroke="Black" VerticalAlignment="Top" Width="446" RadiusY="27.5" RadiusX="27.5"/>
<Button Content="Log In" HorizontalAlignment="Left" Height="80" Margin="162,200,0,0" Style="{DynamicResource OTonButtonStyle1}" VerticalAlignment="Top" Width="187" FontFamily="Impact" FontSize="26.667" Foreground="#FF1C045B" Click="logIn"/>
<TextBox x:Name="UsernameField" HorizontalAlignment="Left" Height="25" Margin="204,57,0,0" TextWrapping="Wrap" Text="[Username]" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBox.Foreground>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF1E2E95" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TextBox.Foreground>
</TextBox>
<TextBlock HorizontalAlignment="Left" Height="16" Margin="98,57,0,0" TextWrapping="Wrap" Text="Username:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0A1D5F" Offset="0.374"/>
<GradientStop Color="#FF6E7FB9" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<PasswordBox x:Name="UserPassField" HorizontalAlignment="Left" Height="25" Margin="204,99,0,0" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16">
<PasswordBox.Foreground>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF1E2E95" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</PasswordBox.Foreground>
</PasswordBox>
<TextBlock HorizontalAlignment="Left" Height="16" Margin="98,99,0,0" TextWrapping="Wrap" Text="Password:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0A1D5F" Offset="0.374"/>
<GradientStop Color="#FF6E7FB9" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<Canvas ClipToBounds="True" Name="errorCanvas" Width="446" Height="17" Margin="36,152,35,151">
<Rectangle x:Name="errorMarquee" Fill="#FF0A0A0C" HorizontalAlignment="Left" Height="17" Stroke="#FF5B1D1D" VerticalAlignment="Top" Width="446" Canvas.Left="-1" Visibility="Hidden"/>
<TextBlock x:Name="errorText" HorizontalAlignment="Left" Height="16" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="690" FontFamily="Copperplate Gothic Bold" FontSize="16" Foreground="#FF7E0202" Visibility="Hidden"/>
</Canvas>
</Grid>
</Window>
Anyone have any suggestions, perhaps?
you can just use one flag to check this
private static flag = true;
private void logIn(object sender, RoutedEventArgs e)
{
if(flag){
flag=false;
string nameRecord = "";
string passRecord = "";
if (UsernameField.Text == "" || UserPassField.Password == "")
{
openErrorMarquee("Username and password required");
}
else
{
using (otongadgethubEntities logCheck = new otongadgethubEntities())
{
var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text);
if (userNullCheck == null)
{
openErrorMarquee("Username does not exist");
}
if (userNullCheck != null)
{
nameRecord = userNullCheck.username;
}
if (nameRecord == UsernameField.Text)
{
passRecord = Encrypt.MD5(UserPassField.Password).ToLower();
if (passRecord == userNullCheck.password)
{
//Yay! User logged in!
}
else
{
openErrorMarquee("Password invalid");
}
}
}
}
}
else
{
openErrorMarquee("you pressed more one time");
}
}
You can use StopWatch to check fast clicks. In code example given below, try pressing button slow and fast.
Stopwatch w = new Stopwatch();
long milliseconds_prev = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (_checkFastClicks())
{
Debug.WriteLine("Fast click");
}
else
Debug.WriteLine("Slow click");
}
bool _checkFastClicks()
{
bool result = false;
if (!w.IsRunning)
{
w.Start();
}
if (w.IsRunning)
{
if (w.ElapsedMilliseconds - milliseconds_prev < 500)//imp
{
if (w.ElapsedMilliseconds > 0)
{
milliseconds_prev = w.ElapsedMilliseconds;
result = true;
}
else
result = false;
}
else
{
milliseconds_prev = 0;
w.Reset();
w.Stop();
result = false;
}
}
return result;
}

Crop Image using Canvas Rectangle

Cropping the image is not working properly. Where I'm wrong?
My Xaml :
<Grid x:Name="Gridimage1">
<Image Name="image1" Grid.Column="0" Height="317" HorizontalAlignment="Left" Margin="20,67,0,0" Stretch="Fill" VerticalAlignment="Top" Width="331"></Image>
<Canvas x:Name="BackPanel">
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed" />
</Canvas>
</Grid>
<Button Content=">>" Height="23" HorizontalAlignment="Left" Margin="357,201,0,0" Name="Go" VerticalAlignment="Top" Width="41" Click="Go_Click" FontWeight="Bold" Visibility="Hidden" />
<Image Grid.Column="1" Height="317" HorizontalAlignment="Left" Margin="408,67,0,0" Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="331" />
C# :
private bool isDragging = false;
private Point anchorPoint = new Point();
public MainWindow()
{
InitializeComponent();
Gridimage1.MouseLeftButtonDown += new MouseButtonEventHandler(image1_MouseLeftButtonDown);
Gridimage1.MouseMove += new MouseEventHandler(image1_MouseMove);
Gridimage1.MouseLeftButtonUp += new MouseButtonEventHandler(image1_MouseLeftButtonUp);
Go.IsEnabled = false;
image2.Source = null;
}
private void Go_Click(object sender, RoutedEventArgs e)
{
if (image1.Source != null)
{
Rect rect1 = new Rect(Canvas.GetLeft(selectionRectangle), Canvas.GetTop(selectionRectangle), selectionRectangle.Width, selectionRectangle.Height);
System.Windows.Int32Rect rcFrom = new System.Windows.Int32Rect();
rcFrom.X = (int)((rect1.X) * (image1.Source.Width) /(image1.Width));
rcFrom.Y = (int)((rect1.Y) *(image1.Source.Height) / (image1.Height));
rcFrom.Width = (int)((rect1.Width) * (image1.Source.Width) /(image1.Width));
rcFrom.Height = (int)((rect1.Height) * (image1.Source.Height) /(image1.Height));
BitmapSource bs = new CroppedBitmap(image1.Source as BitmapSource, rcFrom);
image2.Source = bs;
}
}
#region "Mouse events"
private void image1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (isDragging == false)
{
anchorPoint.X = e.GetPosition(BackPanel).X;
anchorPoint.Y = e.GetPosition(BackPanel).Y;
isDragging = true;
}
}
private void image1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
double x = e.GetPosition(BackPanel).X;
double y = e.GetPosition(BackPanel).Y;
selectionRectangle.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
selectionRectangle.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));
selectionRectangle.Width = Math.Abs(x - anchorPoint.X);
selectionRectangle.Height = Math.Abs(y - anchorPoint.Y);
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void image1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
isDragging = false;
if(selectionRectangle.Width >0)
{
Go.Visibility = System.Windows.Visibility.Visible;
Go.IsEnabled = true;
}
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void RestRect()
{
selectionRectangle.Visibility = Visibility.Collapsed;
isDragging = false;
}
#endregion
It is cropping the wrong part.
The Margin property was not set properly to the Canvas control. It should be the same as Image control's margin properly value. If we don't set Margin to Canvas, It will take the full window size.
Xaml
<Grid x:Name="Gridimage1" Margin="0,0,411,100">
<Image Name="image1" Grid.Column="0" Height="317" HorizontalAlignment="Left" Margin="20,67,0,0" Stretch="Fill" VerticalAlignment="Top" Width="331">
</Image>
<Canvas x:Name="BackPanel" Margin="20,67,0,0">
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed" />
</Canvas>
</Grid>
<Grid x:Name="other">
<Button Content=">>" Height="23" HorizontalAlignment="Left" Margin="341,152,0,0" Name="Go" VerticalAlignment="Top" Width="41" Click="Go_Click" FontWeight="Bold" />
<Image Height="317" HorizontalAlignment="Left" Margin="403,10,-217,-7" Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="331" />
</Grid>
</Grid>

How to create a WPF Window without a border that can be resized?

Is there a way in WPF where I can remove the main window's border, yet allow that window to be resized (without grip)?
I realized there's a way to do this scenario by setting resize mode to CanResizeWithGrip. However, I want to be able to do it with the resize mode set to CanResize.
I tried setting the following:
ResizeMode="CanResize"
WindowStyle="None"
AllowsTransparency="True"
However, by setting AllowsTransparency, it removes the ability to resize without the grip. Any ideas how I can pull this off?
I also should note that I can't set AllowsTransparency to true anyway, because I am using a winformshost control in my window, which is not shown when AllowsTransparency is true.
I know this is an old question, but I just wanted to put up a working sample for newcomers.
Xaml Window:
<Window x:Class="CustomWindowDemo.DemoCustomWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CustomWindowDemo"
mc:Ignorable="d"
Title="DemoCustomWindow" Height="300" Width="300" Background="{x:Null}" AllowsTransparency="True" WindowStyle="None">
<Window.Resources>
<Style x:Key="BorderThumb" TargetType="Thumb">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Rectangle MinWidth="4" MinHeight="4" StrokeThickness="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.HighlightColorKey}}" Opacity="0.05"/>
</Rectangle.Fill>
</Rectangle>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Border BorderBrush="#55FFFFFF" BorderThickness="1" CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border MouseMove="Header_MouseMove" DockPanel.Dock="Top" Height="32" Grid.Row="1" Grid.Column="1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,3">
<GradientStop Color="#3BB2EA" Offset="0" />
<GradientStop Color="#EFF7FA" Offset="0.3" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Text="{Binding Path=Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
<Button x:Name="btn_Minimize" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Click="btn_Minimize_Click" Grid.Column="1">
<Image Source="Resources/Ahmadhania-Spherical-Minimize.ico"/>
</Button>
<Button x:Name="btn_Maximize" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Grid.Column="2" Click="btn_Maximize_Click">
<Image Source="Resources/1412181205_61002.ico"/>
</Button>
<Button x:Name="btn_Close" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Grid.Column="3" Click="btn_Close_Click">
<Image Source="Resources/Ahmadhania-Spherical-Close(1).ico"/>
</Button>
</Grid>
</Border>
<Thumb x:Name="ThumbBottom" DragDelta="ThumbBottom_DragDelta" HorizontalAlignment="Stretch" Cursor="SizeNS" Grid.Column="0" Background="{x:Null}" Margin="3,0" Grid.ColumnSpan="3" Grid.Row="3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTop" DragDelta="ThumbTop_DragDelta" HorizontalAlignment="Stretch" Cursor="SizeNS" Grid.Column="0" Background="{x:Null}" Margin="3,0" Grid.ColumnSpan="3" Height="4" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbBottomRightCorner" DragDelta="ThumbBottomRightCorner_DragDelta" HorizontalAlignment="Right" Cursor="SizeNWSE" Grid.Row="3" Grid.Column="3" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTopRightCorner" DragDelta="ThumbTopRightCorner_DragDelta" HorizontalAlignment="Right" Cursor="SizeNESW" Grid.Row="0" Grid.Column="2" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTopLeftCorner" DragDelta="ThumbTopLeftCorner_DragDelta" HorizontalAlignment="Left" Cursor="SizeNWSE" Grid.Row="0" Grid.Column="0" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}" />
<Thumb x:Name="ThumbBottomLeftCorner" DragDelta="ThumbBottomLeftCorner_DragDelta" HorizontalAlignment="Left" Cursor="SizeNESW" Grid.Row="3" Grid.Column="0" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}" />
<Thumb x:Name="ThumbRight" DragDelta="ThumbRight_DragDelta" Cursor="SizeWE" Grid.Column="2" Grid.RowSpan="4" Background="{x:Null}" Margin="0,3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbLeft" DragDelta="ThumbLeft_DragDelta" Cursor="SizeWE" Grid.Column="0" Grid.RowSpan="4" HorizontalContentAlignment="Right" Background="{x:Null}" Margin="0,3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Grid x:Name="Grid_Content" Background="#EFF7FA" Grid.Row="2" Grid.Column="1">
</Grid>
</Grid>
</Border>
</Window>
C# code behind:
using System.Windows.Interop;
using winforms = System.Windows.Forms;
namespace CustomWindowDemo
{
/// <summary>
/// Interaction logic for DemoCustomWindow.xaml
/// </summary>
public partial class DemoCustomWindow : Window
{
bool Maximized = false;
int NormalWidth = 0;
int NormalHeight = 0;
int NormalX = 0;
int NormalY = 0;
public DemoCustomWindow()
{
InitializeComponent();
}
#region Header & Resize
void Header_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
this.DragMove();
}
void ThumbBottomRightCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbTopRightCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void ThumbTopLeftCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void ThumbBottomLeftCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbRight_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
}
void ThumbLeft_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
}
void ThumbBottom_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbTop_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void btn_Minimize_Click(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
void btn_Maximize_Click(object sender, RoutedEventArgs e)
{
if (Maximized == true)
{
this.Width = NormalWidth;
this.Height = NormalHeight;
this.Left = NormalX;
this.Top = NormalY;
Maximized = false;
Thumbs();
}
else
{
NormalX = (int)this.Left;
NormalY = (int)this.Top;
NormalHeight = (int)this.Height;
NormalWidth = (int)this.Width;
this.Left = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Left;
this.Top = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Top;
this.Width = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Width;
this.Height = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Height;
Maximized = true;
Thumbs();
}
}
void btn_Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
void Thumbs()
{
if (Maximized == true)
{
ThumbBottom.Visibility = Visibility.Collapsed;
ThumbLeft.Visibility = Visibility.Collapsed;
ThumbTop.Visibility = Visibility.Collapsed;
ThumbRight.Visibility = Visibility.Collapsed;
ThumbTopLeftCorner.Visibility = Visibility.Collapsed;
ThumbTopRightCorner.Visibility = Visibility.Collapsed;
ThumbBottomLeftCorner.Visibility = Visibility.Collapsed;
ThumbBottomRightCorner.Visibility = Visibility.Collapsed;
}
else
{
ThumbBottom.Visibility = Visibility.Visible;
ThumbLeft.Visibility = Visibility.Visible;
ThumbTop.Visibility = Visibility.Visible;
ThumbRight.Visibility = Visibility.Visible;
ThumbTopLeftCorner.Visibility = Visibility.Visible;
ThumbTopRightCorner.Visibility = Visibility.Visible;
ThumbBottomLeftCorner.Visibility = Visibility.Visible;
ThumbBottomRightCorner.Visibility = Visibility.Visible;
}
}
#endregion
}
}
This can happen if ResizeBorderThickness is set to 0.
It can be set to a positive value in XAML like this:
<WindowChrome>
<WindowChrome.ResizeBorderThickness>
<Thickness>1</Thickness>
</WindowChrome.ResizeBorderThickness>
</WindowChrome>
You can use the WPF customizable window library, available here: http://wpfwindow.codeplex.com/
Then, when using the library's window type, you can set the same properties as you listed above
<CustomWindow:EssentialWindow x:Class="CustomWindowDemo.DemoEssentialWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CustomWindow="clr-namespace:CustomWindow;assembly=CustomWindow"
AllowsTransparency="True" ResizeMode="CanResize" WindowStyle="None" Title="EssentialWindow"
Height="300" Width="250">
The user needs something to interact with to resize the window. If you don't like the default border or grip, you'll need to add some other control with a click and drag behavior that resizes the window. Perhaps a line on each edge of the window?
The simplest, but maybe too simple is
this.MouseLeftButtonDown += delegate { this.DragMove(); };

Categories