2

I want to have TextBox with bottom border but Graphics drawn for TextBox is distorted/broken on resize because of Color.Transparent.

Using an code I found, I was able to create a underlined TextBox (Drawn Rectangle with tranparent top, left, right). The problem is when I resize the form/window: when I resize it to smaller, then resize again to expand it, the graphics drawn is distorted. Any fix for this?

Here are photos: The second photo has been already resized smaller, then back to a larger size. NormalContracted then Expanded

Here's the code:

[DllImport("user32")]
    private static extern IntPtr GetWindowDC(IntPtr hwnd);
    struct RECT {
        public int left, top, right, bottom;
    }
    struct NCCALSIZE_PARAMS {
        public RECT newWindow;
        public RECT oldWindow;
        public RECT clientWindow;
        IntPtr windowPos;
    }

    float clientPadding = 0;
    int actualBorderWidth = 2;
    Color borderColor = Color.Black;
    protected override void WndProc(ref Message m) {
        //We have to change the clientsize to make room for borders
        //if not, the border is limited in how thick it is.
        if (m.Msg == 0x83) { //WM_NCCALCSIZE 
            if (m.WParam == IntPtr.Zero) {
                RECT rect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                rect.left += 2;
                rect.right -= 2;
                rect.top += 0;
                rect.bottom -= 0;// (int)clientPadding;
                Marshal.StructureToPtr(rect, m.LParam, false);
            } else {
                NCCALSIZE_PARAMS rects = (NCCALSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALSIZE_PARAMS));
                rects.newWindow.left += (int)clientPadding;
                rects.newWindow.right -= (int)clientPadding;
                rects.newWindow.top += (int)clientPadding;
                rects.newWindow.bottom -= 2;
                Marshal.StructureToPtr(rects, m.LParam, false);
            }
        }
        if (m.Msg == 0x85) {//WM_NCPAINT    
            IntPtr wDC = GetWindowDC(Handle);
            using (Graphics g = Graphics.FromHdc(wDC)) {
                ControlPaint.DrawBorder(g, new Rectangle(0, 0, Size.Width, Size.Height),
                    Color.Transparent, 1, ButtonBorderStyle.Solid,
                    Color.Transparent, 1, ButtonBorderStyle.Solid,
                    Color.Transparent, 1, ButtonBorderStyle.Solid,
                    borderColor, actualBorderWidth, ButtonBorderStyle.Solid);
            }
            return;
        }
        base.WndProc(ref m);
    }


EDIT :

I already found the issue, it's because of the Color.Transparent I fixed it by changing it to Color.White, since I have a white background. But then, that would not always be the case, how would I prevent that "Flickering/Tearing" while using Color.Transparent?
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Aesthetic
  • 763
  • 1
  • 14
  • 31
  • TextBox doesn't like being drawn on; the graphics will be wiped out pretty much immediately and all those tricks only help so much.. The effect you see is called 'tearing'. You'd better create a real form with Labels and plain TextBoxes.. – TaW Jul 15 '16 at 19:14
  • Transparency is not really supported in Winforms. TextBox doesn't support it at all. – TaW Jul 15 '16 at 19:29

2 Answers2

11

To have a TextBox with bottom border, The most simple workaround that I can offer is docking a 1 pixel height lable (or other control) to bottom of the TextBox:

using System.Drawing;
using System.Windows.Forms;
public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        BorderStyle = System.Windows.Forms.BorderStyle.None;
        AutoSize = false; //Allows you to change height to have bottom padding
        Controls.Add(new Label()
                    { Height = 1, Dock = DockStyle.Bottom, BackColor = Color.Black });
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • @Yawz I saw your edit. You can use White color to render those invisible borders, but It also makes flickering when you move mouse over the control. Currently I prefer to use this workaround which I shared. – Reza Aghaei Jul 15 '16 at 21:54
  • This doesn't answer directly my question, but it's a solves my problem in a different approach, but how can I create a padding for the text? See this Screenshot: http://oi67.tinypic.com/10zvgqu.jpg I hope to give it padding on right and left sides, and a margin to raise the text.. – Aesthetic Jul 16 '16 at 13:48
  • **•** For padding between Text and Line: it's enough to set `AutoSize` property in constructor to false. **•** For setting left padding and right padding, you should send EM_SETMARGINS message to the `TextBox`. You will find this post helpful: [NumericUpDown with Unit](http://stackoverflow.com/a/37949670/3110834) I've set left padding in answer, and in comments added right padding too. – Reza Aghaei Jul 16 '16 at 20:06
  • I'm a newbie and literally don't know how to use that code to give my text box a left and right margin, anyways I will accept this. Here's my code where I don't know how to implement the left and right padding for the text.. http://pastebin.com/3AgtNZqx I am hoping for a result like this: http://imgur.com/2In0DQB .. I tried but I can't implement, I hope you have a solution for this.. – Aesthetic Jul 18 '16 at 10:14
  • http://stackoverflow.com/questions/38448277/textbox-string-texts-padding-for-custom-control – Aesthetic Jul 19 '16 at 01:36
  • The solution is the same way it's done in the numeric updown control which I linked to. That answer is really a good example and I hope you find it useful too. Anyway, I posted an answer for your new question :) – Reza Aghaei Jul 19 '16 at 06:30
  • Nice and simple, but how can I change the label back color dynamically. – HmH May 12 '18 at 12:48
  • 1
    @HmH `TextBox.Controls[0]` is the label. You can also create a public property to expose it. – Reza Aghaei May 12 '18 at 15:40
0
 this.TxtBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
toyota Supra
  • 3,181
  • 4
  • 15
  • 19
  • 3
    Answer needs supporting information Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](https://stackoverflow.com/help/how-to-answer). – moken Aug 04 '23 at 13:50