【问题标题】:Gray out the Desktop screen except a selected control in c#除了 c# 中的选定控件外,桌面屏幕变灰
【发布时间】:2011-08-15 02:16:36
【问题描述】:

我想选择一个 UI 控件被单击,然后将桌面屏幕的其余部分半透明地变灰。我在想位图绘制整个屏幕,但这是一个非常缓慢的过程。我想有人知道 WPF 中如何做到这一点。我没有WPF的经验。我想在 Windows 7 上执行此操作。

【问题讨论】:

  • 喜欢 vista/7 中的 UAC 弹出窗口吗?
  • 是的。像 Windows 7 的截图工具

标签: wpf c#-3.0 wpf-controls bitmap uicontrol


【解决方案1】:

基本上,您希望显示一个不可聚焦且不响应输入的顶级全屏透明窗口。然后,您可以使用此窗口手动绘制覆盖。我认为最简单的方法是在 Window 上覆盖 OnRender 并绘制一个填充整个窗口但使用剪贴蒙版(通过 drawingContext.PushClip)排除您想要不覆盖的区域的矩形。

编辑:

这是一个例子:

窗口应该是这样设置的:

<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>

WindowStyleWindowState设置将导致窗口最大化并与任务栏重叠。 Topmost 设置为 true 将导致窗口位于所有其他窗口的顶部,IsHitTestVisible 将导致鼠标单击“落空”。

警告:如果您设置此选项,您将遇到无法关闭的最顶层窗口,因为它不听键盘命令。 您需要在代码中的某处手动关闭窗口。您可能想要创建一个全局鼠标挂钩来监听鼠标向上,并创建一个键盘挂钩来监听 ESC 或其他内容。

在上面的示例中,为了让人们远离自己,我将 TopMost 设置为 False。只有在您知道如何/何时在代码中某处关闭窗口时才将其更改为 true。

Background 设置为 null,以便您可以在后面的代码中使用自定义绘图。

后面的代码类似这样:

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();
}

您将在哪里为 excludeRectangle 使用正确的位置和大小。

如果您运行此代码,您将看到屏幕显示为灰色,除了左上角的一个小矩形。

【讨论】:

  • 这很酷。谢谢。是否可以在 C# 代码中添加 Xaml 或在 Xaml 中使用 OnRender 事件添加整个代码隐藏文件。我需要的原因是我正在尝试使用 Add-type 将其添加到 powershell 中
  • 我不了解 powershell,但您可以在没有 XAML 的 C# 中轻松完成此操作。简单地创建一个继承自 Window 的类(System.Windows.Window - 您需要引用 PresentationFramework.dll)并在那里覆盖 OnRender。然后在 C# 中设置我在 XAML 中设置的属性并通过 Show() 手动显示窗口...
  • 并且由于您是新来的,如果它回答了您的问题,请确保接受它作为答案。 - 欢迎来到 stackoverflow。
  • 如果你想要的只是windows snip工具体验,覆盖渲染有点过头了......它通过截取窗口并用它覆盖整个屏幕来工作。
  • 取决于用例。他没有说他想创建一个屏幕截图应用程序,我认为除了显示静态屏幕截图的屏幕截图应用程序之外的任何东西都是不可取的。您不会在后台看到任何更新(除非您更新屏幕截图),但是当您可以轻松地在 OnRender 中编写 10 行代码时,经历所有这些麻烦并处理更高的内存消耗和图像管理似乎有点过头了.
【解决方案2】:

我使用了这个代码。但看起来它没有使用 OnRender。它只是显示白色窗口。

namespace GrayOutTEST
{
   class MainWindow1 : Window
   {
       private Window window;
       public MainWindow1() { }
       public void CreateWindow()
    {
        window = new Window();
        window.Title = "WIndow Title";
        window.Height = Screen.PrimaryScreen.Bounds.Height;
        window.Width = Screen.PrimaryScreen.Bounds.Width;
        window.Topmost = false;
        window.IsHitTestVisible = false;
        window.AllowsTransparency = true;
        window.WindowStyle = WindowStyle.None;
        window.WindowState = WindowState.Maximized;
      //  window.Background = null;
        window.Show();
    }
    public void CloseWindow()
    {
        window.Close();
    }
    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(System.Windows.Media.Brushes.Black, null, new Rect(0, 0, ActualWidth, ActualHeight));
        drawingContext.Pop(); drawingContext.Pop();
    } 
    [STAThread]
    static void Main(string[] args)
    {
        MainWindow1 w = new MainWindow1();
        w.CreateWindow();
        Console.Read();
    }

}
}

【讨论】:

  • 您正在显示一个新窗口而不是 MainWindow1。您必须显示 MainWindow1,因为这是您实现 OnRender 方法的地方。还将背景设置为 null。
  • 您可以使用整个 CreateWindow 的东西,并对您的 w 变量(类型为 MainWindow1)执行相同的操作,然后取消注释 background=null;位,它应该可以工作。
【解决方案3】:

如果你想模糊 MainWindow 并专注于新的 Popup 窗口,你可以检查这个:

System.Windows.Media.Effects.BlurEffect objBlur = new System.Windows.Media.Effects.BlurEffect();
((MainWindow)App.Current.MainWindow).Effect = objBlur;

mainFrame.Navigate(new PopUp_page1());

您也可以使用 Window 代替 Popup 窗口。

移除效果:

((MainWindow)App.Current.MainWindow).Effect = null;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多