3

我想制作一个系统托盘应用程序,用于“屏蔽”屏幕的某些区域(这是用于隐藏某些 DJ 软件的部分,例如 BPM 计数器,因此用户可以在练习时隐藏 BPM,然后按一个要揭示的关键。)实际上,这相当于在你的显示器上贴一块胶带,但没有令人讨厌的残留物!

要求是:

  1. 用户应该能够在屏幕上绘制一些他们想要屏蔽的矩形。(也许使用设置/编辑模式)
  2. 矩形需要始终位于顶部(一种模态,但是......)
  3. 用户必须能够与下面的应用程序交互 - 即鼠标点击和按键应该在 DJ 软件上工作
  4. 然后,用户应该能够在显示和隐藏矩形之间切换(无需每次都重新绘制

不确定解决此问题的最佳方法 - 考虑使矩形只是一些没有内容或控件的表单。有没有更好的(图形方式)来实现这一点?面板或矩形或什么的?

4

3 回答 3

3

理想情况下,我希望使用分层表单,但使用标准表单更容易编写并在 StackOverflow 上展示。

用户体验远非伟大,但这没关系,它只是为了给你一个大致的想法。您应该随意采用自己的界面。

在此处输入图像描述

public sealed partial class GafferTape : Form
{
    private Point _startLocation = Point.Empty;
    private Point _cursorLocation = Point.Empty;
    private bool _drawing;
    private Rectangle _regionRectangle;
    private readonly List<Rectangle> _rectangles = new List<Rectangle>();

    public bool AllowDrawing { get; set; }

    public GafferTape()
    {
        InitializeComponent();

        //TODO: Consider letting the designer handle this.
        FormBorderStyle = FormBorderStyle.None;
        WindowState = FormWindowState.Maximized;
        TopMost = true;
        DoubleBuffered = true;
        ShowInTaskbar = false;
        Cursor = Cursors.Cross;
        BackColor = Color.White;
        Opacity = 0.4;
        TransparencyKey = Color.Black;

        //TODO: Consider letting the designer handle this.
        MouseDown += OnMouseDown;
        MouseUp += OnMouseUp;
        MouseMove += OnMouseMove;
        Paint += OnPaint;

        AllowDrawing = true;

    }

    private void OnMouseDown(object sender, MouseEventArgs mouseEventArgs)
    {
        //I don't allow the user to draw after the rectangles have been drawn. See: buttonInvert_Clic
        if (AllowDrawing)
        {
            _startLocation = mouseEventArgs.Location;
            _drawing = true;
        }
    }

    private void OnMouseUp(object sender, MouseEventArgs mouseEventArgs)
    {
        _drawing = false;
        DialogResult = DialogResult.OK;
        _rectangles.Add(_regionRectangle);
    }

    private void OnMouseMove(object sender, MouseEventArgs mouseEventArgs)
    {
        if (_drawing == false)
            return;

        _cursorLocation = mouseEventArgs.Location;

        _regionRectangle = new Rectangle(Math.Min(_startLocation.X, _cursorLocation.X),
                                         Math.Min(_startLocation.Y, _cursorLocation.Y),
                                         Math.Abs(_startLocation.X - _cursorLocation.X),
                                         Math.Abs(_startLocation.Y - _cursorLocation.Y));

        Invalidate();
    }

    private void OnPaint(object sender, PaintEventArgs paintEventArgs)
    {
        foreach (Rectangle rectangle in _rectangles)
            paintEventArgs.Graphics.FillRectangle(Brushes.Black, rectangle);

        paintEventArgs.Graphics.FillRectangle(Brushes.Black, _regionRectangle);
    }

    private void buttonInvert_Click(object sender, EventArgs e)
    {
        Opacity = 100;
        TransparencyKey = Color.White;
        AllowDrawing = false;
        Cursor = Cursors.Default;
    }
}
于 2013-05-14T13:00:58.500 回答
0

以下是我将如何做的概述:

  1. 截取桌面截图。
  2. 以最大化的、无边界的形式显示它。
  3. 允许用户选择其上的矩形;查找“Rubberbanding”和 Paint() 事件以一次绘制多个。
  4. 将选中的 Rectangles 添加到 GraphicsPath 并设置 Form 的 Region() 属性;这将从字面上删除没有矩形的表单部分。
  5. 在 CreateParams() 中,设置 WS_EX_TRANSPARENT 和 WS_EX_NOACTIVATE 标志(这允许鼠标事件“穿过”矩形到达下面的应用程序)。
  6. 将 TopMost() 设置为 True。
  7. 使用 RegisterHotKey() 在按键上切换表单。
于 2013-05-14T12:59:49.083 回答
0

您可以使用弹出窗口。例如,在 wpf 中,您可以执行以下操作:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow">
    <Grid>
        <ToggleButton x:Name="Button" Content="Show / Hide" Height="25"/>
        <Popup Width="300" Height="300" IsOpen="{Binding Path=IsChecked, ElementName=Button}" Placement="Absolute" PlacementRectangle="1,1,1,1"/>
    </Grid>
</Window>

每当您按下按钮时,它将在指定位置(屏幕左上角)显示/隐藏指定大小(300x300)的黑色弹出窗口:在此处输入图像描述

如果您愿意,您可以使其可移动和/或调整大小。我想不出更简单的解决方案。

于 2013-05-14T13:15:53.663 回答