0

my Problem is, that i want to draw a rectangle over an existing Textbox.

I have a solution now, but the Textbox is always redrawing, which is a behavior i do not want.

here is the code

private bool isDragging = false;

void Form2_MouseMove(object sender, MouseEventArgs e)

{
    if (isDragging)
    {
        endPos = e.Location;
        Rectangle rect;
        if (endPos.Y > startPos.Y)
        {
              rect = new Rectangle(startPos.X, startPos.Y,
              endPos.X - startPos.X, endPos.Y - startPos.Y);
        }
        else
        {
              rect = new Rectangle(endPos.X, endPos.Y,
              startPos.X - endPos.X, startPos.Y - endPos.Y);
        }
        Region dragRegion = new Region(rect);
        this.Invalidate();
    }
}

void Form2_MouseUp(object sender, MouseEventArgs e)
{
    isDragging = false;
    this.Invalidate();
}
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp;
        cp = base.CreateParams;
        cp.Style &= 0x7DFFFFFF; //WS_CLIPCHILDREN
        return cp;
    }
}


void Form2_MouseDown(object sender, MouseEventArgs e)
{
    isDragging = true;
    startPos = e.Location;
}

// this is where we intercept the Paint event for the TextBox at the OS level  
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case 15: // this is the WM_PAINT message  
                 // invalidate the TextBox so that it gets refreshed properly  
            Input.Invalidate();
            // call the default win32 Paint method for the TextBox first  
            base.WndProc(ref m);
            // now use our code to draw extra stuff over the TextBox  

            break;
        default:
            base.WndProc(ref m);
            break;
    }
}



protected override void OnPaint(PaintEventArgs e)

{
    if (isDragging)
    {
        using (Pen p = new Pen(Color.Gray))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            e.Graphics.DrawRectangle(p,
            startPos.X, startPos.Y,
            endPos.X - startPos.X, endPos.Y - startPos.Y);
        }
    }
    base.OnPaint(e);
}


the problem here is, the textbox is flickering, and the Rectangle is not set in front of the textbox after finish dragging.

How do i solve this ?

Pretasoc
  • 1,116
  • 12
  • 22
  • The problem you have is with the Z index of your rectangle. You need to move the text box behind your rectangle. This may give you a few hints: https://stackoverflow.com/questions/3213270/how-to-set-z-order-of-a-control-using-winforms – Steve Todd Jun 03 '19 at 12:58
  • ok, added this to th eForm2_MouseMove ``` int zIndex = this.Controls.GetChildIndex(this.Input); this.Controls.SetChildIndex(this.Input, zIndex-1); ``` but the rectangle itself is behind the boxes. After i have no access, on that rectangle, how do i set it to front ? – overload_of_HJT Jun 03 '19 at 13:28
  • Looking at your code a little deeper, you're drawing your rectangle directly onto the window canvas, which will always be behind the text box. If you're trying to use the rectangle to select one or more controls then see this: https://stackoverflow.com/questions/10308906/how-to-select-multiple-controls-by-mouse-dragging-over-them, otherwise use a Panel control rather than a rectangle – Steve Todd Jun 03 '19 at 14:18
  • [ControlPaint.DrawReversibleFrame](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.controlpaint.drawreversibleframe). – Jimi Jun 03 '19 at 15:26

1 Answers1

0

You are turning off the flag: WS_CLIPCHILDREN in WndProc.

WS_CLIPCHILDREN value is 0x02000000 and you are turning it off in your code:

cp.Style &= 0x7DFFFFFF; //WS_CLIPCHILDREN

WS_CLIPCHILDREN flag is set by default, it prevents flickering of child controls. If you will not turn off the flag, the flickering will stop.

According to the documentation on WS_CLIPCHILDREN: Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating the parent window.

Side Note: when turning off a flag, it is more clear to use the flag value you want to turn off:

cp.Style &= ~0x02000000; //WS_CLIPCHILDREN
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37