Archives for: October 2006, 13
13/10/06
Drawing a selection rubber band, take 3
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 picture:

So, 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.


