Reputation: 4319
I want to make a system tray app that is used to "mask off" certain areas of the screen (this is for use to hide portions of some DJ software such as BPM counters, so the user can hide the BPM when practising, then press a key to reveal.) Effectively it's the equivalent of sticking a piece of gaffer tape to your monitor, but without the nasty residue!
The requirements are:
Not sure of the best way to approach this - thought about making the rectangles just a number of forms with no content or controls on. Is there a better (graphical way) to acheive this? Panels or rectangles or something?
Upvotes: 3
Views: 360
Reputation: 3333
You can use a popup. For example, in wpf you can do the followning:
<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>
It will show / hide a black popup of specified size (300x300) at the specified location (top left corner of the screen) whenever you press the button:
You can make it movable and/or resizable, if you want to. I cannot think of an easier solution.
Upvotes: 0
Reputation: 7804
Ideally I would have liked to use a layered form but using a standard form is much easier to write and to present here at StackOverflow.
The UX is far from great but that doesn't matter, it's just to give you a general idea. You should feel free to adopt your own interface.
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;
}
}
Upvotes: 3
Reputation: 39142
Here's an overview of how I would do it:
Upvotes: 0