[WPF] Draw a hole in a semi-transparant canvas
Hi,
I am creating a small application for my own use which overlays a semi-transparant black window on top of my whole screen. I can then draw a 'selection rectangle' on top of that window, and when I release the mouse, a screenshot is made from the region underneath the rectangle and immediately uploaded to my webserver and the link is copied to my clipboard.
Now instead of just having a white line that defines the selection I'd like to actually 'cut a hole' through the canvas, so that the screen is (semi-transparent) black except for my selection, which should be completely transparant and show the desktop underneath.
How can I achieve this?
At the moment I merely have a Canvas that handles some mouse properties:
csharp Code:
public partial class MainWindow : Window
{
private Rectangle rectangle;
private Point clickLocation;
public MainWindow()
{
InitializeComponent();
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
this.Close();
}
}
private Rectangle CreateRectangle()
{
var rect = new Rectangle();
rect.Stroke = Brushes.White;
rect.StrokeThickness = 2;
return rect;
}
private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
rectangle = this.CreateRectangle();
clickLocation = e.GetPosition(canvas);
Canvas.SetLeft(rectangle, clickLocation.X);
Canvas.SetTop(rectangle, clickLocation.Y);
rectangle.Width = 0;
rectangle.Height = 0;
canvas.Children.Add(rectangle);
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (rectangle == null) return;
var location = e.GetPosition(canvas);
var width = location.X - clickLocation.X;
var height = location.Y - clickLocation.Y;
if (width < 0)
{
Canvas.SetLeft(rectangle, location.X);
width = -width;
}
if (height < 0)
{
Canvas.SetTop(rectangle, location.Y);
height = -height;
}
rectangle.Width = width;
rectangle.Height = height;
}
private void canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var rect = new Rect();
rect.X = Canvas.GetLeft(rectangle);
rect.Y = Canvas.GetTop(rectangle);
rect.Width = rectangle.Width;
rect.Height = rectangle.Height;
this.HandleScreenGrab(rect);
canvas.Children.Clear();
rectangle = null;
}
private void HandleScreenGrab(Rect region)
{
//...
}
}
I have read in the past about being able to 'cut' geometries by combining them in an exclude combination, or something, but I cannot figure it out... This seems to be close:
http://stackoverflow.com/questions/7...background-wpf
But I cannot figure out how to apply it in my case. I've tried creating a RectangleGeometry from the canvas, as well as from the 'rectangle' (which is the selection) and combining them, but the results varied from nothing at all (no change) to a completely transparant window everywhere. Basically everthing except what I want: a rectangular 'hole' (completely transparent) through an otherwise semi-transparent canvas.
Thanks!
Re: [WPF] Draw a hole in a semi-transparant canvas
Hi Nick,
I'm a real beginner in WPF but I thought it would be a good exercise to try solving this. I managed to punch a transparent rectangular hole in an inherited canvas like this (please excuse the vb.net):
Code:
Protected Overrides Sub OnRender(dc As System.Windows.Media.DrawingContext)
Dim bounds As New RectangleGeometry(New Rect(0, 0, Me.Width, Me.Height))
Dim hole As New RectangleGeometry(New Rect(30, 30, Me.Width - 60, Me.Height - 60))
Dim combined As Geometry = Geometry.Combine(bounds, hole, GeometryCombineMode.Exclude, Nothing)
Me.Clip = combined
MyBase.OnRender(dc)
End Sub
I hope it helps.
BB