Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

wpf - Gray out the Desktop screen except a selected control in c#

I want to select a UI control to be clicked and gray out the rest of the desktop screen semi-transparently. I was thinking bitmap painting the whole screen but it is very slow process. I guess someone out there know in WPF how to do that. I don't have experiance in WPF. I wanted to do this on Windows 7.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Basically you want to show a top-level full screen transparent window which is not focusable and doesn't respond to input. You can then use this window to draw the overlay manually. I think the easiest way would be to override OnRender on the Window and to draw a rectangle that fills the whole window but uses a clipping mask (via drawingContext.PushClip) to exclude the area you want to leave uncovered.

EDIT:

Here is an example:

The Window should probably be set up like this:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        AllowsTransparency="True"
        WindowStyle="None"
        WindowState="Maximized"
        Topmost="False"
        Background="{x:Null}"
        IsHitTestVisible="False">
</Window>

The WindowStyle and WindowStatesettings will cause the window to be maximized and overlapping the task bar. Topmost set to true will cause the window to be on top of all other windows and IsHitTestVisible will cause the mouse clicks to 'fall through'.

Warning: If you set this you will be stuck with a topmost window that you can't close since it doesn't listen to keyboard commands. You will need to manually close the window somewhere in your code. Likely you want to create a global mouse hook to listen to mouse up and a keyboard hook to listen to ESC or something.

To save people from themselves I have set TopMost to False in the above example. Only change it to true if you have figured out how/when to close the window in code somewhere.

The Background is set to null so that you can use your custom drawing in code behind.

the code behind similar to this:

public MainWindow()
{
    InitializeComponent();
}

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
    var screenGeometry = new RectangleGeometry(new Rect(0, 0, ActualWidth, ActualHeight));
    var excludeRectangle = new RectangleGeometry(new Rect(200, 200, 150, 150));
    drawingContext.PushClip(CombinedGeometry.Combine(screenGeometry,excludeRectangle, GeometryCombineMode.Exclude,null));
    drawingContext.PushOpacity(.8);
    drawingContext.DrawRectangle(Brushes.Black, null, new Rect(0, 0, ActualWidth, ActualHeight));
    drawingContext.Pop();
    drawingContext.Pop();
}

where you would use the proper location and size for the excludeRectangle.

If you run this code you will see the screen grayed out except for a little rectangle in the top left.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...