Transparent rectangle inside window - c#

I have Topmost fullscreen window
AllowsTransparency="True" WindowStyle="None" Topmost="True" WindowState="Maximized" Left="0" Top="0"
OpacityMask="#2B000000" Background="Black" Cursor="Cross"
and I'm drawing rectangle when user holds LMB and moves mouse (it's selection, like on screenshot in this my question Easiest way to select screen region ).
I want to make rectangle completely transparent, to see content behind window. But I can't make it more transparent than parent window. What should I do?

Try something like below and dynamically change the size and location of the second RectangleGeometry (selectRect) in some mouse event handler. And perhaps also adjust the size of the first RectangleGeometry to your screen size.
<Window x:Class="TransparentRectangle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" WindowState="Maximized"
AllowsTransparency="True" Background="Transparent">
<Grid>
<Path Fill="Black" Opacity="0.5">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry x:Name="screenRect" Rect="0,0,2000,2000"/>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry x:Name="selectRect" Rect="100,100,200,100"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
</Grid>
</Window>
A problem might however be that you won't get any mouse events in the excluded part of the CombinedGeometry. To avoid that you could attach the mouse handlers to the Window (instead of the Path) and give it a nearly transparent background.
<Window ... Background="#01000000" MouseMove=... etc>
...
</Window>
EDIT: An even simpler solution might be a Border. You could independently adjust the four components of the BorderThickness.
<Grid ...>
<Border BorderBrush="Black" Opacity="0.5" BorderThickness="100,100,200,400"/>
</Grid>

Related

Tile background - black spaces between tiles

I wanted to experiment with image background of my WPF app. I downloaded a few textures, but unfortunately I have a problem.
Here's my XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="458" Width="473">
<Window.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,0.5,0.5" Stretch="None">
<VisualBrush.Visual>
<Image Source="Images/binding_dark.png" Stretch="None">
<Image.OpacityMask>
<ImageBrush ImageSource="Images/binding_dark.png" Stretch="None" TileMode="Tile"/>
</Image.OpacityMask>
</Image>
</VisualBrush.Visual>
</VisualBrush>
</Window.Background>
<Grid>
</Grid>
</Window>
It's just an empty window, but that's just to see better what the issue is.
Here's the result:
I wanted to get a nice texture as a background of my app, but for some reason the images do not align with each other - there is this strange black spacing between them. What's the reason for this?
//EDIT
Just to clarify:
I'd like to have a background built of many of tiled copies of the same image - not one imgage filling the whole window
To get tiled background without space between you need to add: Stretch="Uniform"
Also you should set Viewportunits to Absolute and size. Change 32 to size of your Image in code below:
ViewportUnits="Absolute" Viewport="0,0,32,32"
Full code:
<Window.Background>
<ImageBrush ImageSource="/TestApp;component/Images/bg.png" ViewportUnits="Absolute" Viewport="0,0,32,32" Stretch="Uniform" TileMode="Tile" />
</Window.Background>
Try to set the background of the grid, not the window, like this:
<Grid>
<Grid.Backgroud>
<ImageBrush Source="Images/binding_dark.png" x:Name="image" Stretch="UniformToFill"/>
</Grid.Background>
</Grid>
You can set the background of the whole window but i'm not sure that this is a good practice

Resize border NOT window in WPF

This is my XAML:
<Window x:Class="IPCapture.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:IPCapture"
mc:Ignorable="d"
Title="IPCapture_GUI" Opacity="0.95" Background="Transparent" Foreground="White" FontFamily="Arial" FontSize="14" FontWeight="Bold" FontStretch="UltraExpanded" TextOptions.TextFormattingMode="Display" BorderThickness="0"
Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" Height="Auto" Width="Auto" Cursor="Arrow" WindowStyle="None" AllowsTransparency="True" MouseLeftButtonDown="Window_MouseLeftButtonDown" Topmost="True" ResizeMode="CanResizeWithGrip">
<Window.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="#B2420000" Offset="1"/>
</LinearGradientBrush>
</Window.OpacityMask>
<Border CornerRadius="5" Background="#FFC20C0C" HorizontalAlignment="Left" VerticalAlignment="Top" Width="Auto" Height="Auto">
<Grid x:Name="GridMain" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0">
<Grid.RowDefinitions>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Keys" Width="Auto"/>
<ColumnDefinition x:Name="Values" Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
<Border.Effect>
<DropShadowEffect Opacity="0.6" BlurRadius="1"/>
</Border.Effect>
</Border>
</Window>
I followed many tutorials on how to achieve the GUI I wanted and I finally succeeded! However, it does not seem to provide the functionality that I need. I want to:
Resize the width of the GUI
A visualisation of my problem:
The large faded blue area is my Window and the small GUI in the top-left corner of that is my actual widget.(That is enclosed in the Border)
As you can see from my code, I have set ResizeMode="CanResizeWithGrip" on the Window. I am able to resize the window perfectly fine BUT resizing it does not resize my actual GUI.(Because of how my XAML is laid out)
So, for this reason, I want to somehow allow resize on the width of the border instead of the Window.
Additions: (if possible)
Is it possible to remove that small black toolbar that's centered on the top of the Window?
I am also confused as to why, because I have set Height and Width of the Window to Auto, is it so large? Shouldn't it only expand as large as it's content?
Let's take it one at a time:
The resize issue is because of HorizontalAlignment="Left" VerticalAlignment="Top" you've set on the Grid and the Border. It means the element will measure its minimum required width & height and align to the top left. If you remove this, the element will (assuming there are no other layout issues) resize to contain the entire window.
Setting Auto for Width and Height (which is the default, by the way) behaves differently on a window - it tells the OS - not WPF - to determine the initial size (using an undisclosed algorithm, so don't rely on it). If you want WPF to resize the window to the minimum required by its content, set SizeToContent="WidthAndHeight".
The small black toolbar is a new VS 2015 feature and only appears during debugging. You can turn it off in the Live Visual Tree panel in VS.
Bonus tips:
I strongly discourage you from applying an Effect on the entire visual tree. It's a huge performance hit. You should look into using SystemDropShadowChrome.
Same goes for OpacityMask. Just use a uniform Opacity unless you really need that gradient... Even then you may be better off using a uniform opacity and a gradient brush as the background.

WPF Cannot scroll an image inside a ScrollViewer

I try to display an image in my window :
<Window x:Class="Problem.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">
<DockPanel>
<StackPanel Orientation="Vertical">
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Image Source="cat.jpg" Stretch="Uniform">
<Image.LayoutTransform>
<RotateTransform Angle="90" />
</Image.LayoutTransform>
</Image>
</ScrollViewer>
</StackPanel>
</DockPanel>
</Window>
where cat.jpg is a 1920x1080 image.
Here is the result :
As you can see, the VerticalScrollbar is disabled although I can't see the full cat head. Moreover, HorisontalScrollBar is Invisible.
My question is : How to enable scrollbar in order to scroll over my image ?
Remove the StackPanel. It gives its content infinite space, so the ScrollViewer has the height of the image. If you need to stack something under the image, create a StackPanel inside the ScrollViewer:
<Window x:Class="Problem.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">
<DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<StackPanel>
<Image Source="cat.jpg" Stretch="Uniform">
<Image.LayoutTransform>
<RotateTransform Angle="90" />
</Image.LayoutTransform>
</Image>
</StackPanel>
</ScrollViewer>
</DockPanel>
I was having the same problem, but with a custom made Image class which I only rendered drawings on by using the DrawingContext in the protected override void OnRender(DrawingContext dc) function. I did not understood then, that I either needed to set the size of the image (set the Width and Height properties) or create a new image from the drawingContext and make it the Source of the image, in order to resize the actual image.
I got my answer from here: Get images from DrawingGroup and the way I solved it was by changing the properties every time I used the Render function of my image:
DrawingImage drawingImage = new DrawingImage(mBackingStore);
Width = drawingImage.Width;
Height = drawingImage.Height;

How to rotate a WPF Window?

Is it possible to rotate a WPF Window by 45 degree, using xaml?
First question: Why do you want to rotate the whole window?
If you really need it:
You can't rotate the normal WPF window. See: Rotate Window
You will have to create a borderless window and provide a UI to it. See: WPF Non-Client Area Design Techniques For Custom Window Frames
For rotated window look:
Set:
AllowTransparency property to
true.
WindowStyle to None to
remove window chrome
Background
to Transparent
Include a border (or anything meaningful like rectangle, circle, ellipse, etc.) as content of the window and following properties of border:
white background (or any non-transparent color)
rotate transformation, and
smaller size (so as to fit when rotated within the window).
Border will provide the UI to your window.
Be aware of cavaets of creating own borderless window, as it requires you to provide the window interface like minimise, maximise, close buttons; and may require some unmanaged code.
Also, in sample code below, the border when rotated has to be kept within the bounds of the window, otherwise it (and your custom window) will be trimmed.
Sample code
<Window x:Class="CustomWindowStyle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AllowsTransparency="True" WindowStyle="None" Background="Transparent"
Title="MainWindow" Height="600" Width="600">
<Border BorderBrush="Green" BorderThickness="2" Background="White" Width="360" Height="360">
<Border.RenderTransform>
<RotateTransform Angle="-45" CenterX="180" CenterY="180"/>
</Border.RenderTransform>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="X" Height="23" Width="23" Name="button1" HorizontalAlignment="Right" VerticalAlignment="Top" Click="button1_Click"/>
<Grid Grid.Row="1">
<!--Main window content goes here-->
<TextBlock Text="Main window content goes here" HorizontalAlignment="Center" />
</Grid>
</Grid>
</Border>
</Window>
As far as I know you can't rotate an entire window, but you could put everything inside the window into a custom control and apply apply a RenderTransform object to the custom control.
Example (somewhat simple):
http://www.codeproject.com/KB/WPF/TransformationsIntro.aspx
-- Dan

Why don't my media elements resize and clip properly when using UniformToFill?

Why don't my media elements fill the screen correctly when I use the UniformToFill stretch? The mediaElement clips at the bottom if the window is wider than the mediaElement, and it clips at the right if the window is taller than the mediaElement.
<Window x:Class="WpfApplication1.Window3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Preview Window" Height="200" Width="600" WindowStyle="None" Background="Black" ResizeMode="CanMinimize" MouseLeftButtonDown="Window3_MouseLeftButtonDown" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid Focusable="False">
<MediaElement Name="mediaElement2" LoadedBehavior="Manual" MediaOpened="mediaElement2_MediaOpened" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="289,-19,-11,-19" />
<MediaElement Name="mediaElement1" LoadedBehavior="Manual" MediaOpened="mediaElement1_MediaOpened" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="-11,0,289,0"/>
</Grid>
In the program I use these commands to stretch it and use visual brushes to apply these videos to another window. The problem occurs in this window where the video/picture clip incorrectly
window3.mediaElement1.Stretch = Stretch.UniformToFill;
window3.mediaElement2.Stretch = Stretch.UniformToFill;
Try setting the Stretch property to Stretch.Uniform instead of Stretch.UniformToFill.
If you want to fill the whole screen without maintaining relative dimensions, also try Stretch.Fill to stop clipping.

Categories