views:

58

answers:

1

I'm trying to integrate a screenshot grabbing feature in my WPF app and I'd like it to look like snipping tool.

So far I've managed accomplish something similar by creating a fullscreen window (with a canvas) with opacity set to 0.5 and dark background. When I click somewhere and start dragging, a white rectangle is drawn, generating an effect similar to this.

What I'd like to have is the inner part of that rectangle opening a opacity hole in the background canvas, so that I could see through the selected area - just like snipping tool.

Problem is, being fairly new to .NET, I have no idea how or where to start. Did some research and tests on the OpacityMask field of the screenshot window but got nowhere.

Here's a little vid to show the current effect.

Edit: Also, as bonus question, is there an easy way to grab a screenshot that spans across multiple monitors (virtual screen)? Graphics.CopyFromScreen() only seems to work for 1 screen.
Already fixed this and seems to work for all possible weird virtual desktop layouts:

// Capture screenie (rectangle is the area previously selected
double left = Canvas.GetLeft(this.rectangle);
double top = Canvas.GetTop(this.rectangle);

// Calculate left/top offset regarding to primary screen (where the app runs)
var virtualDisplay = System.Windows.Forms.SystemInformation.VirtualScreen;
var primaryScreen = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
if (virtualDisplay.Left < primaryScreen.Left)
{
    left -= Math.Abs(virtualDisplay.Left - primaryScreen.Left);
}
if (virtualDisplay.Top < primaryScreen.Top)
{
    top -= Math.Abs(virtualDisplay.Top - primaryScreen.Top);
}
+1  A: 

You can have a CombinedGeometry with GeometryCombineMode="Exclude" creating a "punched" effect. Sample:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" AllowsTransparency="True" 
    WindowStyle="None" Background="Transparent">
    <Canvas >
        <Path Stroke="Black" Fill="White" Opacity=".5">
            <Path.Data>
                <CombinedGeometry GeometryCombineMode="Exclude">
                    <CombinedGeometry.Geometry1>
                        <RectangleGeometry Rect="0,0,800,600" >
                        </RectangleGeometry>
                    </CombinedGeometry.Geometry1>
                    <CombinedGeometry.Geometry2>
                        <RectangleGeometry  Rect="50,50,100,100" >
                        </RectangleGeometry>
                    </CombinedGeometry.Geometry2>
                </CombinedGeometry>
            </Path.Data>
        </Path>
    </Canvas>
</Window>
Eduardo Molteni
This works nicely but has a little problem: when the mouse moves to the "punched" area, you lose MouseMove events. I guess I'd have to mix this solution with the one pointed out by Hans Passant. Nice effect, though!
brunodecarvalho
I've played around with this and, if used in conjunction with the approach of grabbing a screenshot and using it as window background, it produces the desired effect, so I'm marking this one as right - even though I wanted to keep a "live" view of what was happening on the desktop (i.e. no screenshot before the selection).
brunodecarvalho
Well, good for you. As nice as keeping a live view would be, I think no user would care or notice. In fact, I found that the snipping tool was grabbing a screenshot because I look into it, and I use the tool all the time.
Eduardo Molteni