【问题标题】:TextBox with bottom border带下边框的文本框
【发布时间】:2016-07-15 18:55:44
【问题描述】:

我想让TextBox 带有底部边框,但为TextBox 绘制的图形在调整大小时会因为Color.Transparent 而变形/损坏。

使用我找到的代码,我能够创建一个带下划线的文本框(绘制的矩形,顶部、左侧、右侧透明)。问题是当我调整窗体/窗口的大小时:当我将其调整为更小,然后再次调整大小以扩展它时,绘制的图形会失真。 有什么解决办法吗?

这是照片:第二张照片的尺寸已经变小了,然后又变大了。

代码如下:

[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);
    }


编辑:

我已经找到了问题,这是因为Color.Transparent 我通过将其更改为Color.White 来修复它,因为我有一个白色背景。但是,情况并非总是如此,在使用 Color.Transparent 时如何防止“闪烁/撕裂”?

【问题讨论】:

  • TextBox 不喜欢被画在上面;图形将立即消失,所有这些技巧只能起到很大的作用。你看到的效果被称为“撕裂”。你最好用标签和纯文本框创建一个真实的表单..
  • Winforms 并不真正支持透明度。 TextBox 根本不支持。

标签: c# winforms user-interface graphics window-resize


【解决方案1】:

要拥有一个带有底部边框的TextBox,我可以提供的最简单的解决方法是将一个 1 像素高度的标签(或其他控件)停靠到 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 });
    }
}

【讨论】:

  • @Yawz 我看到了你的编辑。您可以使用白色来渲染那些不可见的边框,但是当您将鼠标移到控件上时它也会闪烁。目前我更喜欢使用我分享的这个解决方法。
  • 这并不能直接回答我的问题,但它以不同的方法解决了我的问题,但是如何为文本创建填充?看到这个截图:oi67.tinypic.com/10zvgqu.jpg我希望给它左右两边的padding,还有一个margin来提升文本..
  • 对于 Text 和 Line 之间的填充:将构造函数中的 AutoSize 属性设置为 false 就足够了。 要设置左填充和右填充,您应该发送 EM_SETMARGINS 消息到TextBox。你会发现这篇文章很有帮助:NumericUpDown with Unit 我在答案中设置了左填充,在 cmets 中也添加了右填充。
  • 我是一个新手,实际上不知道如何使用该代码为我的文本框提供左右边距,无论如何我会接受这一点。这是我的代码,我不知道如何实现文本的左右填充.. pastebin.com/3AgtNZqx 我希望得到这样的结果:imgur.com/2In0DQB .. 我试过但我不能实现,我希望你有一个解决方案..
  • @HmH TextBox.Controls[0] 是标签。您还可以创建一个公共属性来公开它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 2011-07-24
相关资源
最近更新 更多