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

Sorry, this blog does not support comments.

I used various blog hosting services since this blog was established in 2005, but unfortunately they turned out to be unreliable in the long term and comment threads were lost in unavoidable transitions. At this time I don't want to enable third-party services for comments since it has become obvious in recent years that these providers invariably monetize information about their visitors and users.

Please use the links in the page footer to get in touch with me. I'm available for conversations on Keybase, Matrix, Mastodon or Twitter, as well as via email.