I don't want my window to be resized either "only horizontally" or "only vertically." Is there a property I can set on my window that can enforce this, or is there a nifty code-behind trick I can use?
You could try replicating an effect that I often see on Flash Video websites. They allow you to expand the browser window any way you like, but only stretch the presentation area so that it fits the smallest of the height or width.
For example, if you stretch the window vertically, your application would not resize. It would simple add black bars to the top and bottom of the display area and remain vertically centered.
This may or may not be possible with WPF; I don't know.
You can reserve aspect ratio of contents using WPF's ViewBox with control with fixed width and height inside.
Let's give this a try. You can change "Stretch" attribute of ViewBox to experience different results.
Here is my screeen shot: http://lh6.ggpht.com/_5XDoB4MglkY/SU_uU8IjMHI/AAAAAAAAE1s/Wg5KQ8nrnhg/s800/Untitled.jpg
<Window x:Class="TestWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Viewbox Stretch="Uniform">
<StackPanel Background="Azure" Height="400" Width="300" Name="stackPanel1" VerticalAlignment="Top">
<Button Name="testBtn" Width="200" Height="50">
<TextBlock>Test</TextBlock>
</Button>
</StackPanel>
</Viewbox>
</Window>
I had expected that you could two-way bind the width to the height using a value converter to maintain aspect ratio. Passing the aspect ratio as the converter parameter would make it more general purpose.
So, I tried this - the binding with no converter first:
<Window
...
Title="Window1" Name="Win" Height="500"
Width="{Binding RelativeSource={RelativeSource self},
Path=Height, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<StackPanel>
<TextBlock>Width:</TextBlock>
<TextBlock Text="{Binding ElementName=Win, Path=Width}" />
<TextBlock>Height:</TextBlock>
<TextBlock Text="{Binding ElementName=Win, Path=Height}" />
</StackPanel>
</Window>
Strangely, the binding binding is behaving as if it is one-way and the reported width of the window (as shown in the TextBlock) is not consistent with it's size on screen!
The idea might be worth pursuing, but this strange behavior would need to be sorted out first.
Hope that helps!
This is what my solution was.
You will need to add this to your control/window tag:
Loaded="Window_Loaded"
And you will need to place this in your code behind:
private double aspectRatio = 0.0;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
aspectRatio = this.ActualWidth / this.ActualHeight;
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
if (sizeInfo.WidthChanged)
{
this.Width = sizeInfo.NewSize.Height * aspectRatio;
}
else
{
this.Height = sizeInfo.NewSize.Width * aspectRatio;
}
}
I tried the Viewbox trick and I did not like it. I wanted to lock the window border to a specific size. This was tested on a window control but I assume it would work on a border as well.
You can always handle the WM_WINDOWPOSCHANGING message, this let's you control the window size and position during the resizing process (as opposed to fixing things after the user finished resizing).
Here is how you do it in WPF, I combined this code from several sources, so there could be some syntax errors in it.
internal enum WM
{
WINDOWPOSCHANGING = 0x0046,
}
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
private void Window_SourceInitialized(object sender, EventArgs ea)
{
HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)sender);
hwndSource.AddHook(DragHook);
}
private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
{
switch ((WM)msg)
{
case WM.WINDOWPOSCHANGING:
{
WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
if ((pos.flags & (int)SWP.NOMOVE) != 0)
{
return IntPtr.Zero;
}
Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if (wnd == null)
{
return IntPtr.Zero;
}
bool changedPos = false;
// ***********************
// Here you check the values inside the pos structure
// if you want to override tehm just change the pos
// structure and set changedPos to true
// ***********************
if (!changedPos)
{
return IntPtr.Zero;
}
Marshal.StructureToPtr(pos, lParam, true);
handeled = true;
}
break;
}
return IntPtr.Zero;
}
Can anyone email me information how I can lock a wpf window completerly I want to prevent the wpf window from be moved, resized, minimized and maximized. You can email me at [email protected]
This may be bit late but you can simply put it in your code behind....
Private Sub UserControl1_SizeChanged(ByVal sender As Object, ByVal e As System.Windows.SizeChangedEventArgs) Handles Me.SizeChanged
If e.HeightChanged Then
Me.Width = Me.Height
Else
Me.Height = Me.Width
End If
End Sub