在C#中创建浮动对象的最佳方法

3
我希望制作一个系统托盘应用程序,用于“遮蔽”屏幕上的某些区域(这是为了隐藏一些DJ软件的部分功能,例如BPM计数器,以便用户在练习时隐藏BPM,然后按下键来显示)。实际上,它相当于将一块胶带粘贴在您的监视器上,但不会留下残留物!
要求如下: 1. 用户应该能够在屏幕上绘制多个矩形,以遮蔽他们想要的区域。(可以使用设置/编辑模式) 2. 矩形需要始终置顶(有点像模态,但...) 3. 用户必须能够与下面的应用程序进行交互 - 即鼠标点击和按键操作应该在DJ软件上起作用。 4. 然后,用户应该能够在显示和隐藏矩形之间切换(无需每次重新绘制)。
不确定最好的方法是什么 - 考虑将矩形只制作成没有内容或控件的表单。是否有更好的(图形化的)方法来实现此目的?面板或矩形或其他什么东西?
3个回答

3
理想情况下,我希望使用分层表单,但是使用标准表单更容易编写和在StackOverflow中展示。用户体验远非完美,但这并不重要,只是为了让您有一个大致的了解。您应该自由采用自己的界面。

enter image description here

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

太棒了!唯一的问题是,我看不到按钮在哪里绘制。 - Ben
我使用设计器放置了按钮,并使用了“Anchor”属性“Top, Left”。抱歉忘记提到了 :c - User 12345678
太准确了!感谢这个 - 正是我需要的。 - Ben
干得不错,但那些 On... 方法应该是重写方法,这意味着你就不需要 MouseDown += OnMouseDown; 这些语句了。确保在这些语句中添加基础调用。 - LarsTech

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)的黑色弹出窗口:enter image description here

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


0

以下是我如何实现它的概述:

  1. 截取桌面的屏幕截图。
  2. 在最大化、无边框的窗体中显示它。
  3. 允许用户选择其上的矩形;查找“橡皮筋”和Paint()事件以同时绘制多个矩形。
  4. 将所选矩形添加到GraphicsPath中,并设置Form的Region()属性;这将从字面上删除不包含矩形的窗体部分。
  5. 在CreateParams()中,设置WS_EX_TRANSPARENT和WS_EX_NOACTIVATE标志(这允许鼠标事件“穿透”矩形到下面的应用程序)。
  6. 将TopMost()设置为True。
  7. 使用RegisterHotKey()在按键时切换窗体。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接