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:
  1. public partial class MainWindow : Window
  2.     {
  3.         private Rectangle rectangle;
  4.         private Point clickLocation;
  5.  
  6.         public MainWindow()
  7.         {
  8.             InitializeComponent();
  9.         }
  10.  
  11.         private void Window_KeyUp(object sender, KeyEventArgs e)
  12.         {
  13.             if (e.Key == Key.Escape)
  14.             {
  15.                 this.Close();
  16.             }
  17.         }
  18.  
  19.         private Rectangle CreateRectangle()
  20.         {
  21.             var rect = new Rectangle();
  22.             rect.Stroke = Brushes.White;
  23.             rect.StrokeThickness = 2;
  24.             return rect;
  25.         }
  26.  
  27.         private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  28.         {
  29.             rectangle = this.CreateRectangle();
  30.  
  31.             clickLocation = e.GetPosition(canvas);
  32.             Canvas.SetLeft(rectangle, clickLocation.X);
  33.             Canvas.SetTop(rectangle, clickLocation.Y);
  34.             rectangle.Width = 0;
  35.             rectangle.Height = 0;
  36.  
  37.             canvas.Children.Add(rectangle);
  38.         }
  39.  
  40.         private void canvas_MouseMove(object sender, MouseEventArgs e)
  41.         {
  42.             if (rectangle == null) return;
  43.  
  44.             var location = e.GetPosition(canvas);
  45.             var width = location.X - clickLocation.X;
  46.             var height = location.Y - clickLocation.Y;
  47.  
  48.             if (width < 0)
  49.             {
  50.                 Canvas.SetLeft(rectangle, location.X);
  51.                 width = -width;
  52.             }
  53.             if (height < 0)
  54.             {
  55.                 Canvas.SetTop(rectangle, location.Y);
  56.                 height = -height;
  57.             }
  58.  
  59.             rectangle.Width = width;
  60.             rectangle.Height = height;
  61.         }
  62.  
  63.         private void canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  64.         {
  65.             var rect = new Rect();
  66.             rect.X = Canvas.GetLeft(rectangle);
  67.             rect.Y = Canvas.GetTop(rectangle);
  68.             rect.Width = rectangle.Width;
  69.             rect.Height = rectangle.Height;
  70.  
  71.             this.HandleScreenGrab(rect);
  72.  
  73.             canvas.Children.Clear();
  74.             rectangle = null;
  75.         }
  76.  
  77.         private void HandleScreenGrab(Rect region)
  78.         {
  79.             //...
  80.         }
  81.     }
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!