WPF Zoom to Rectangle with RenderTransform - c#

I have a question about a WPF zooming question. This question is really about a Kinect application, but I have tried to generalise it here.
I have the following XAML:
`<Window x:Class="RenderTransformViewboxTest.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:RenderTransformViewboxTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border x:Name="borderContainer" ClipToBounds="True">
<Viewbox x:Name="contentViewbox">
<Grid>
<Image x:Name="imageMoose" Source="Images\Moose.jpg" />
<Canvas x:Name="canvasContainer">
<Rectangle x:Name="TestRectangle" Height="600" Width="200" Canvas.Left="250" Canvas.Top="150" Stroke="Black" Fill="Yellow" Opacity="0.5" />
</Canvas>
</Grid>
</Viewbox>
</Border>
<StackPanel Grid.Column="1">
<Button x:Name="btnZoomToRectangle" Content="Zoom to Rectangle" Click="btnZoomToRectangle_Click" />
</StackPanel>
</Grid>
This looks like this:
I am having trouble writing the correct code to:
Scale the whole Viewbox (the canvas and image) inside the border until the rectangle appears to be at the full height of the border control.
Then, translate the whole Viewbox (the canvas and image) inside the border so that the rectangle appears to be in the centre of the border control.
Since translating the Viewbox may introduce "gaps" on the left/right of the border, I'd like to trim the other side somehow so that there is an equal amount of image on the left and the right hand side of the rectangle.
The result of these steps should make the screen look like this:
Notice how that because the image was translated right, we introduced a gap at the left hand side of the frame. As per requirement 3, I introduce the same amount of gap on the right hand side.
(I apologise for my skills with Paint here).
I've been banging my head against a wall with this for ages and am having trouble. I have sort of managed to scale the image applying a Matrix Transform in the centre of the image but can't seem to do much else with it after! Any help would be gladly appreciated.

Related

WPF Resize Window proportionally ie. No stretching or distorting?

I have a WPF Window which contains a Grid. It's set up to look like a Checkers board, so I need the squares of the grid to stay square when the window is resized.
I've tried many things but nothing seems to work. I hope it's just a matter of getting the right attribute, and not something complicated, but I need it to resize proportionally either way.
I'm also not sure if this should happen in the Grid or in the Window. I would assume the Window because that's the controller for resizing, but I could be wrong.
Any suggestions?
xaml for Window:
<Window x:Class="TicTacToeClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TicTacToeClient"
Title="Mini-Checkers V1.1" Height="600" Width="600"
MinHeight="200" MinWidth="200" MaxHeight="600" MaxWidth="600" >
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Game">
<MenuItem Header="Set Ip Address" Name="IPAddressMenuItem"/>
<MenuItem Header="Set Name" Name="SetNameMenuItem"/>
</MenuItem>
</Menu>
<TextBlock DockPanel.Dock="Bottom" Text ="Status: " Name="GameStatusBar" />
<local:TicTacToeBoard x:Name="GameBoard" />
</DockPanel>
xaml for Grid:
<UserControl x:Class="TicTacToeClient.TicTacToeBoard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="600">
<Grid Name="MainGrid">
<Grid.RowDefinitions>
....
I would suggest DataBinding the Width of your Grid to the Height (or vice-versa). This will make sure that it always grows proportionally. Something as simple as this should work:
<Grid x:Name="Checkerboard" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="{Binding RelativeSource={RelativeSource Self}} Path=ActualHeight}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- Grid Contents -->
</Grid>
And if you want your cells to all remain square, just make sure they're all * sized, so they will be spread out equally.
Alternatively, you can put yor grid inside a Viewbox with Stretch="Uniform"
You can try enclosing yourGameBoard in a ViewBox with Stretch Property set to Uniform and StretchDirection set to Both. like this. It wont keep the Form's Aspect ratio uniform but will keep your GameBoard Proportions Uniform.
<Viewbox Stretch="Uniform" StretchDirection="Both">
<local:TicTacToeBoard x:Name="GameBoard" />
</Viewbox>

create the same effect on a text as the title of windows

I create a transparency window with different textblock but my text isn't always readable because it's depends of colors user's window.
So I want apply the same effect on a text like the effect of my title window,
It's like a white shadow.
Thank you
The best way to do this would be to use a shader effect. I tried to do this with the built in Blur effect but it seems they don't blend with Alpha.
Below is an example of how I would start and doesn't represent an end product. HLSL border effect based off of Emboss effect.
View the full image for a better understanding. This effect only adds like 2 px border so the scaling makes it look even worse.
I'm pretty bad at writing HLSL the code on the right is just copy-pasted from http://brooknovak.wordpress.com/2008/09/16/simple-image-filters-written-as-hlsl-pixel-shaders/ with modification.
I'm sure someone who knew HLSL / GLSL could write a blur effect that works correctly. Note that this effect works across a full image and thus needs to know the image size. You should put them in a constant buffer and use them instead of the hardcoded 500.0 for width and height. They need to be the width/height of the rendered object. In my example it is actually the entire left half side of the window not just the size of the text because my XAML looks like this...
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Loaded="Window_Loaded" Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="264*" />
<ColumnDefinition Width="239*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="218*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="The quick brown fox jumped over the lazy dog." Foreground="White" Background="Transparent" Grid.RowSpan="3" x:Name="PART_TextBlock"/>
<TextBox x:Name="PART_TextBox" Grid.Column="1" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" AcceptsTab="True" />
<TextBlock x:Name="PART_Error" Grid.Column="1" Grid.Row="1"/>
<Button Content="Compile & Apply" Grid.Column="1" Grid.Row="2" Padding="4,1" Margin="4" HorizontalAlignment="Center" Click="Button_Click" />
</Grid>
</Window>

MediaElement in Canvas doesnt Strech to Fill

I want to view a fullscreen video and thought this works like this:
<Window x:Class="test.Overlay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Overlay" Height="300" Width="300" WindowState="Maximized">
<Grid>
<Canvas Name="lightCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<MediaElement Name="lightMovie" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="C:\knoblauch\lights\1.wmv" Stretch="Fill" />
</Canvas>
</Grid>
but for some reason the video, in this case 1.wmv, doesnt fill up the screen.
Why?
Elements added to a Canvas will not be sized relative to the Canvas. They will be their non stretched size or a size which has been explicitly set (through setting Width, Height, etc). To get items to stretch you need containers that support that functionality suach as a Grid.
For instance:
<Grid>
<MediaElement Name="lightMovie" Source="C:\knoblauch\lights\1.wmv" Stretch="Fill" />
</Grid>
works as you are expecting.

How to set a .PNG image as a TILED background image for my WPF Form?

I'm learning WPF on my own and I can't seem to find a way to make this work.
Here's my code:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="600" Width="800" >
<DockPanel>
<Menu DockPanel.Dock="Right"
Height="30"
VerticalAlignment="Top"
Background="#2E404B"
BorderThickness="2.6">
<Menu.BitmapEffect>
<DropShadowBitmapEffect Direction="270" ShadowDepth="3" Color="#2B3841"/>
</Menu.BitmapEffect>
</Menu>
</DockPanel>
How can I make a tiled background image appear?
Set the ViewportUnits to absolute, which will allow you to define the pixel size of your image in the Viewport. In my example the image size is 32x32.
<Window.Background>
<ImageBrush ImageSource="image.png" TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,32,32"/>
</Window.Background>
Or, perhaps, you could use Visual Brush:
<Window
x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="600" Width="800">
<Window.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,0.5,0.5">
<VisualBrush.Visual>
<Image Source="image.png"></Image>
</VisualBrush.Visual>
</VisualBrush>
</Window.Background>
</Window>
The Viewport property sets the position and dimensions of the base tile. Have a look at examples here.
Basically, "0,0,0.5,0.5" means that the base tile will take space from point (0,0) to (0.5,0.5) - i.e. from the upper left corner of the output area to centre. (1,1) is the lower right corner. You should make use of MSDN Library. It's really useful. All the answers are there.

WPF ViewBox Zoom

Is there a way to zoom a viewbox content, excpet for one control?
I have a viewbox with a grid, and in this grid I have some controls and I'm trying to zoom all the controls in the viewbox except one, is it possible?
Many thanks,
Paulo
You can use a grid to add layers to your layout. That way, you can zoom one set of items, and leave another set un-zoomed.
<Grid>
<Viewbox>
<!-- Controls to zoom -->
</Viewbox>
<!-- Control to exclude from zoom -->
</Grid>
The order of the view box and the other controls in XAML will depend upon which layer appears on top.
If that doesn't quite do what you want, leave a comment and I'll revisit the answer.
EDIT You want the unzoomed control to be positioned relative to the (0,0) of the Viewbox. That will happen in this situation because both children of the grid are in cell (0,0) which means that their top-left corners are aligned. Can you give an example of what you have in XAML, and what's wrong with it (perhaps edit your original question)?
Here's some XAML to try:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Background="Green">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox>
<Rectangle Fill="Yellow" Width="10" Height="10" />
</Viewbox>
<TextBlock>I am positioned at (0,0)</TextBlock>
<TextBlock Margin="50,50">I am positioned at (50,50)</TextBlock>
</Grid>
</Page>
That gives a layout like this:
http://img20.imageshack.us/img20/2045/layout1m.png
But note that when the height is reduced, the grid becomes wider than the view box, and so the content is layed out like this:
http://img20.imageshack.us/img20/9397/layout2i.png
I guess that's not what you want. In that case, you use a canvas and go for something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Background="Green">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox>
<Rectangle Fill="Yellow" Width="10" Height="10" />
</Viewbox>
<Canvas>
<TextBlock>I am positioned at (0,0)</TextBlock>
<TextBlock Margin="50,50">I am positioned at (50,50)</TextBlock>
</Canvas>
</Grid>
</Page>
Which looks like this:
http://img20.imageshack.us/img20/6743/layout3i.png

Categories

Resources