In two previous posts (here and here) I have previously posted about how to draw rubber band selection rectangles similar to what Explorer does. Now a reader contacted me by email and asked for an extension: he wants to have a reverse selection, similar to this image:
No problem, of course :-)
I started out from the improved version of the first demo and made a few changes — all you have to do is replace the SelectionPanel.OnPaint
method with this:
protected override void OnPaint(PaintEventArgs e) {
ColorMatrix colorMatrix = new ColorMatrix(new float[][] {
new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
new float[] {0.0f, 0.0f, 0.0f, 0.3f, 0.0f},
new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
});
ImageAttributes imageAttributes = new ImageAttributes( );
imageAttributes.SetColorMatrix(
colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
Point[] destPoints = new Point[] {
new Point(ClientRectangle.Left, ClientRectangle.Top),
new Point(ClientRectangle.Right, ClientRectangle.Top),
new Point(ClientRectangle.Left, ClientRectangle.Bottom)
};
e.Graphics.DrawImage(backgroundBitmap, destPoints,
usableRect, GraphicsUnit.Pixel, imageAttributes);
if (mouseDownPos != Point.Empty) {
Point mousePos = PointToClient(MousePosition);
Rectangle selectedRect = new Rectangle(
Math.Min(mouseDownPos.X, mousePos.X),
Math.Min(mouseDownPos.Y, mousePos.Y),
Math.Abs(mousePos.X - mouseDownPos.X),
Math.Abs(mousePos.Y - mouseDownPos.Y));
Point srcRectLocation = selectedRect.Location;
srcRectLocation.Offset(usableRect.Location);
Rectangle srcRect = new Rectangle(srcRectLocation,
selectedRect.Size);
e.Graphics.DrawImage(backgroundBitmap, selectedRect,
srcRect, GraphicsUnit.Pixel);
using (Pen pen = new Pen(Color.Black)) {
pen.DashPattern = new float[] { 2f, 2f };
int thirdOfHeight = selectedRect.Height / 3;
int thirdOfWidth = selectedRect.Width / 3;
e.Graphics.DrawRectangle(Pens.White, selectedRect);
e.Graphics.DrawLine(Pens.White,
selectedRect.Left,
selectedRect.Top + thirdOfHeight,
selectedRect.Right,
selectedRect.Top + thirdOfHeight);
e.Graphics.DrawLine(Pens.White,
selectedRect.Left,
selectedRect.Bottom - thirdOfHeight,
selectedRect.Right,
selectedRect.Bottom - thirdOfHeight);
e.Graphics.DrawLine(Pens.White,
selectedRect.Left + thirdOfWidth,
selectedRect.Top,
selectedRect.Left + thirdOfWidth,
selectedRect.Bottom);
e.Graphics.DrawLine(Pens.White,
selectedRect.Right - thirdOfWidth,
selectedRect.Top,
selectedRect.Right - thirdOfWidth,
selectedRect.Bottom);
e.Graphics.DrawRectangle(pen, selectedRect);
e.Graphics.DrawLine(pen,
selectedRect.Left,
selectedRect.Top + thirdOfHeight,
selectedRect.Right,
selectedRect.Top + thirdOfHeight);
e.Graphics.DrawLine(pen,
selectedRect.Left,
selectedRect.Bottom - thirdOfHeight,
selectedRect.Right,
selectedRect.Bottom - thirdOfHeight);
e.Graphics.DrawLine(pen,
selectedRect.Left + thirdOfWidth,
selectedRect.Top,
selectedRect.Left + thirdOfWidth,
selectedRect.Bottom);
e.Graphics.DrawLine(pen,
selectedRect.Right - thirdOfWidth,
selectedRect.Top,
selectedRect.Right - thirdOfWidth,
selectedRect.Bottom);
}
}
}
The result is this (I got rid of my main form drawing routine and inserted a nice background picture instead). Very nice!
Update: As requested, I’m making the complete sample project available. Here’s the download.