In my WPF program, I want to draw a shape. Then after I press a button, the program plays a video in fullscreen mode. I can't seem to make the video play in fullscreen on the canvas.
my XAML is like below
<Canvas>
<Ellipse Name="face1" Panel.ZIndex="2" Fill="Green" Width="400" Height="400" />
<MediaElement Panel.ZIndex="1000" Name="videoControl1" Stretch="Fill"
Source="C:\Users\videos\carcrash.mp4"
LoadedBehavior="Manual" MediaEnded="videoControl1_MediaEnded">
</MediaElement>
</Canvas>
As you can see, I put the video in front of my shape. as sson as a button is pressed, I then start to play the video. So the video will be in front of the shape. The problem is that the video is very small. How to make it full screen?
Per Dennis Cheng's comment here:
Canvas is a "no-layout" panel so children won't size to parent. Try
Grid if you want children fill or manually Bind to the parent's size
if you must use a Canvas:
<Canvas x:Name="MyCanvas"
Width="300"
Height="300">
<Ellipse Name="face1"
Width="400"
Height="400"
Panel.ZIndex="2"
Fill="Green" />
<MediaElement Name="videoControl1"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualWidth}"
Height="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualHeight}"
Panel.ZIndex="1000"
Source="C:\Users\videos\carcrash.mp4" />
</Canvas>
That scales the video's width to that of the containing Canvas, but it remains in proportion to its original dimensions.
If you use a Grid you can achieve the kind of scaling you're aiming for:
<Grid Width="500" Height="500">
<Ellipse Name="face1"
Width="400"
Height="400"
Panel.ZIndex="2"
Fill="Green" />
<MediaElement Name="videoControl1"
Grid.Row="0"
Panel.ZIndex="1000"
Source="D:\Downloads\The.Strain.S01E13.HDTV.x264-LOL.mp4"
Stretch="Fill" />
</Grid>
Related
I am making a video game and have problem with screen resolutions.
Earlier, a few month ago, I asked very similar question.
Need images with lower resolution "stretched" to screen size
Back then, it seemed the answer I got (using ViewBox) was perfect, but now I am getting problems.
I want every and every image and control in my game to have a few different possible variations fit for resolutions.
For example, if user sets resolution 800x600, all images and buttons are reduced to correct sizes. But I do want my game to be fullscreen only, not windowed.
So, if the resolution is lower then end-user monitor has, all images must be stretched and look "fuzzy". And if higher, part of it must be outside of screen.
For now, my code just sets resolution to end-user monitor, whatever it is. That's absolutely not what I want.
What I get:
A very crude example of what I need:
I'll show xaml as its now. Of course it isn't full, but I'll show the beginning and a few elements, so you'll know how it's built.
<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:Name="wdwMain" x:Class="RealityIncognita.MainWindow"
Height="900" Width="1600" ResizeMode="NoResize" WindowState="Maximized" Cursor="Cross" WindowStyle="None" Loaded="wdwMain_Loaded">
<Viewbox x:Name="viewMain" Stretch="Fill">
<Grid x:Name="areaContainer" HorizontalAlignment="Left" Height="900" VerticalAlignment="Top" Width="1600">
<Grid x:Name="areaMain">
<Grid.Background>
<ImageBrush ImageSource="Resources/Images/Interface/main_interface.jpg"/>
</Grid.Background>
<Label x:Name="lblTextOutput" Content="Label" HorizontalAlignment="Center" Height="52" Margin="55,726,31,0" VerticalAlignment="Top" Width="1514" FontFamily="Arial" FontSize="22" FontWeight="Bold" HorizontalContentAlignment="Center"/>
<Button x:Name="btnExit" HorizontalAlignment="Left" Height="106" Margin="1464,771,0,0" VerticalAlignment="Top" Width="126" Click="btnExit_Click" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}">
<Button.Template>
<ControlTemplate>
<Image Source="/Resources/Images/Interface/Blank.png" Stretch="Fill" Margin="12,0,6,0"/>
</ControlTemplate>
</Button.Template>
</Button>
<Grid x:Name="areaShowers" HorizontalAlignment="Left" Height="700" Margin="1653,790,-1561,-590" VerticalAlignment="Top" Width="1508" IsVisibleChanged="areaShowers_IsVisibleChanged">
<Grid.Background>
<ImageBrush ImageSource="Resources/Images/Rooms/Showers/shower_room.jpg" />
</Grid.Background>
<Button x:Name="objShowersSoap" HorizontalAlignment="Left" Height="29" Margin="613,423,0,0" VerticalAlignment="Top" Width="17" MouseLeave="MouseLeaveAnyObject" RenderTransformOrigin="11.706,1.897" Click="objShowersSoap_Click" MouseEnter="objShowersSoap_MouseEnter">
<Button.Template>
<ControlTemplate>
<Image Source="Resources/Images/Rooms/Showers/soap.png" Stretch="Fill" Margin="0,0,0,0"/>
</ControlTemplate>
</Button.Template>
</Button>
<Image x:Name="imgShowersOpenMachine" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Source="Resources/Images/Rooms/Showers/drying_machine_open.png" RenderTransformOrigin="0.808,0.471" Stretch="Fill"/>
</Button>
</Grid>
<Grid x:Name="areaLockerRoom" Height="700" VerticalAlignment="Top" Width="1508" IsVisibleChanged="areaLockerRoom_IsVisibleChanged" Margin="1653,17,-1561,0" MouseDown="areaLockerRoom_MouseDown" MouseEnter="areaLockerRoom_MouseEnter" MouseMove="areaLockerRoom_MouseMove">
<Grid.Background>
<ImageBrush ImageSource="Resources/Images/Rooms/LockerRoom/locker_room_ready.png"/>
</Grid.Background>
<Button x:Name="objLockerRoomCrowbar" Content="" HorizontalAlignment="Left" Height="243" Margin="604,328,0,0" VerticalAlignment="Top" Width="51" MouseEnter="objCrowbar_MouseEnter" Panel.ZIndex="1" Click="objCrowbar_Click" MouseLeave="MouseLeaveAnyObject">
<Button.Template>
<ControlTemplate>
<Image Source="Resources/Images/Rooms/LockerRoom/crowbar_only.png" Stretch="Fill" Margin="0,0,0,0"/>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="objLockerRoomOdyssey" HorizontalAlignment="Left" Height="53" Margin="797,638,0,0" VerticalAlignment="Top" Width="61" Click="objBookOdyssey_Click" MouseLeave="MouseLeaveAnyObject" MouseEnter="objBookOdyssey_MouseEnter">
<Button.Template>
<ControlTemplate>
<Image Source="Resources/Images/Rooms/LockerRoom/img_book_odyssey.png" Stretch="Fill" Margin="0,0,0,0"/>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="objLockerRoomEdda" HorizontalAlignment="Left" Height="53" Margin="1335,549,0,0" VerticalAlignment="Top" Width="61" MouseLeave="MouseLeaveAnyObject" Click="objBookEdda_Click" MouseEnter="objBookEdda_MouseEnter">
<Button.Template>
<ControlTemplate>
<Image Source="Resources/Images/Rooms/LockerRoom/img_book_edda.png" Stretch="Fill" Margin="0,0,0,0"/>
</ControlTemplate>
</Button.Template>
</Button>
To summarize the structure is like that:
Main Window - Viewbox - areaContainer (main grid) - game areas (grids) - images and buttons for each grid
To summarize:
What I get: game screens are set for end-user monitor resolution.
What I need: game sets all images to specific resolution, makes it "fuzzy" if resolution is LOWER then end-user's, and "cuts" it if it is HIGHER.
Thank you in advance,
Evgenie
ADDED:
If I understand correctly how it works - the container grid that includes all other items should be resized, images should become smaller (by default they are 1600x900), if needed. Then, this container grid must fit user's screen resolution, staying with small images quality.
And to simplify it even more: Can I make large images smaller, then change them to be big again (and lose quality) directly in Visual Studio?
Actually simply adjusting the viewbox did the trick.
<Viewbox x:Name="viewMain" VerticalAlignment="Center" HorizontalAlignment="Center">
And in code, I had to change MaxWidth and MaxHeight, instead of regular ones.
viewMain.MaxWidth = 1024;
viewMain.MaxHeight = 768;
My code for moving the image control is:
<Grid Name="grid" Width="400" Height="400" ManipulationMode="All"
ManipulationDelta="Grid_ManipulationDelta_1" Margin="0,58,0,182">
<Grid.RenderTransform>
<CompositeTransform x:Name="transform" />
</Grid.RenderTransform>
<Image x:Name="Image1" Source="Assets/SmallLogo.png" Stretch="None"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
Manipulation delta has code:
private void Grid_ManipulationDelta_1(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.PointerDeviceType == PointerDeviceType.Touch)
{
this.transform.TranslateX += e.Delta.Translation.X;
this.transform.TranslateY += e.Delta.Translation.Y;
OutText.Text = sender.ToString();
}
else
{
e.Handled = true;
}
}
This works perfect when I move image wherever on my grid.
Now for resizing the image control I have different implementation,
<ScrollViewer x:Name="scrl2" SizeChanged="scrl_SizeChanged" ZoomMode="Enabled"
HorizontalScrollMode="Enabled" VerticalScrollMode="Enabled"
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"
MinZoomFactor="0.1" MaxZoomFactor="10" Margin="0" VerticalAlignment="Bottom">
<Image Source="Assets/SmallLogo.png" Stretch="None"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</ScrollViewer>
The scroll viewer can be resized here and image is child so it also can. And it changes size on runtime perfectly, but note that this is different code.
I want to implement both scenarios on image control, which seems logical, so I edit my xaml like this:
<Grid Name="grid" Width="400" Height="400" ManipulationMode="All"
ManipulationStarted="Grid_ManipulationStarted_1"
ManipulationCompleted="Grid_ManipulationCompleted_1"
ManipulationDelta="Grid_ManipulationDelta_1" Margin="0,58,0,182">
<Grid.RenderTransform>
<CompositeTransform x:Name="transform" />
</Grid.RenderTransform>
<ScrollViewer x:Name="scrl2" SizeChanged="scrl_SizeChanged"
ZoomMode="Enabled" HorizontalScrollMode="Enabled"
VerticalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
MinZoomFactor="0.1" MaxZoomFactor="10" Margin="0" VerticalAlignment="Bottom">
<Image x:Name="Image1" Source="Assets/SmallLogo.png" Stretch="None"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</ScrollViewer>
</Grid>
The RenderTransform should take care of movement and ScrollViewer should do pinch thing. But that does not work. In separate code when image is in scroll viewer only - pinch to zoom works, when image is in grid - drag to move works.
In the above code where I put image in ScrollViewer and that ScrollViewer in grid, only pinch to zoom works, movement does not work. I tried to undo the Horizontal Vertical alignment settings (set them to something null) but that is not possible. The image resizes, but remains always in the position it is set in alignment settings.
What is wrong in this implementation?
I have a ScatterView that contains an image over which I should be able to draw.
<s:ScatterView HorizontalAlignment="Center" Margin="0,0,0,0" Name="desk" VerticalAlignment="Center">
<s:ScatterViewItem Width="200" Height="200">
<Grid>
<Image Name="img1" Source="/Resources/Desert.jpg"/>
<Viewbox>
<s:SurfaceInkCanvas Name="cvs1"/>
</Viewbox>
</Grid>
</s:ScatterViewItem>
</s:ScatterView>
I noticed that whenever I draw an ink trail towards the border of the image, the strokes on the ink canvas are scaled down to make room for more stuff. I do not want these strokes to be zoomed out. How can I change this behavior?
Here is a video that shows what's going on.
I figured it out. This behavior is caused by the fact that I hadn't defined a Width and Height on the SurfaceInkCanvas. This should do the trick:
<s:SurfaceInkCanvas Name="cvs1" Width="200" Height="200" />
I have a canvas in xaml defined as following. However adding a rectangle in it doesn't show any thing.
<lib:DrawingCanvas x:Name="drawingCanvas" Background="White" AllowDrop="True">
<Rectangle Margin="20,20,20,20" Fill="Black" Stroke="White" Width="100" Height="100">
</Rectangle>
</lib:DrawingCanvas>
Can you give me some hints here?
Thanks.
You're not using a Canvas, you're using a "DrawingCanvas", so I can't speak for any differences. But assuming it derives from Canvas:
You need to set the attached properties for the Rectangle. These are Canvas.Left or Canvas.Right, in addition to Canvas.Top or Canvas.Bottom.
For example:
<Rectangle Canvas.Left="50" Canvas.Top="100" Width="100" Height="100" Fill="Black" />
I'm trying to position a rectangle in the center of a grid with a restricted height, like so:
<Grid ClipToBounds="False">
<Grid Background="LightBlue" Height="10" ClipToBounds="False" Margin="0,27,0,79">
<Rectangle Height="40" Width="20" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" ClipToBounds="False"/>
</Grid>
</Grid>
I've expected it to look like that:
But instead it looks like that:
I know the my child rectangle is bigger and it is understandable that it clips, however, my ClipToBounds have no effect of anything. After reading around, I found that indeed Grid does not respect "ClipToBounds".
I tried to use Canvas, as suggested in the aforementioned article by Dr.Wpf but I can't seem to get it right.
Is there anything I can do to make it look like the 1st picture, without resorting to C# code?
Thanks!
It's a little hard to tell exactly what your requirements are here. You said you tried it witha Canvas, but you can't seem to get it right. What didn't work?
I used this code:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestApp.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="175" Height="170" Background="LightGray">
<Grid>
<Canvas Background="LightBlue" Height="10"
Margin="0,27,0,79" VerticalAlignment="Top">
<Rectangle Height="40" Width="20" Fill="Black"
Canvas.Left="66" Canvas.Top="-15" />
</Canvas>
</Grid>
</Window>
and was able to essentially fake what your screenshot looked like. But (as you can tell by the Canvas.Left and Canvas.Top parts of my code) it is sort of hackish. You could get rid of the Canvas.Left by binding to the ActualWidth of the Canvas and using an IValueConverter that converts it to the correct value.
Edit:
After a little further exploration, I came up with a slightly less hackish way of doing it. Though the nesting kind of makes me cringe, the only thing hardcoded is the top margin to get it centered vertically. Again, that can be done with an IValueConverter, but you don't want that. I'm not sure I can get any better than this, unfortunately.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication10.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Grid Background="LightBlue" Height="10" ClipToBounds="False" Margin="0,27,0,79">
<Canvas>
<Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Canvas}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=Canvas}}">
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 -40 0 0">
<Rectangle Height="40" Width="20" Fill="Black" ClipToBounds="False"/>
</Canvas>
</Grid>
</Canvas>
</Grid>
</Grid>
</Window>