How to keep Font in inherited TextBox?
Asked Answered
F

5

4

I'm using the following code to get a TextBox that is not drawing its borders:

public partial class CustomTextBox : TextBox
{
    public CustomTextBox()
    {
        InitializeComponent();
        SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        int borderWidth = 1;

        ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle,
            Color.Transparent, borderWidth, ButtonBorderStyle.Solid,
            Color.Transparent, borderWidth, ButtonBorderStyle.Solid,
            Color.Transparent, borderWidth, ButtonBorderStyle.Solid,
            Color.Transparent, borderWidth, ButtonBorderStyle.Solid);
    }
}

I seem to miss something inside of OnPaint() because my Font is not the default Font for a textBox anymore (perhaps I have to override another event).

When checking CustomTextBox.Font property it shows me the default "Microsoft SansSerif in 8,25" but when typing text into my textBox the Font definitely looks bigger and bold.

Hope you can help me!

Regards,

inno

[EDIT]

I should mention that if I don't override OnPaint the Font of my CustomTextBox is correct. Only when overriding OnPaint my Font is incorrect (when typing text the font is bigger and seems to be bold). So I think I have to do something to initialize the font correctly inside of OnPaint (but ATM I have no idea how to do this).

Felicle answered 3/8, 2009 at 12:17 Comment(1)
Don't set UserPaint to true in the constructor, do it in OnControlCreated() instead. That will fix the font issue.Wobbling
G
6

Don't call SetStyle if the handle for the textbox is not yet created, and it won't ever change to that 'big bold' font:

if (IsHandleCreated)
{
     SetStyle(ControlStyles.UserPaint, true);
}
Grog answered 1/2, 2012 at 15:3 Comment(1)
Great answer, it was the missing piece for me to figure it out. Setting UserPaint style in constructor broke it, but calling it in OnControlCreated() worked.Wobbling
B
2

Two options for you to look at... In my base-class, I'm forcing a read-only font definition... similar for other controls, so other developers with the class can't change it --- PERIOD.

[ReadOnly(true)]
public override Font Font
{
    get
    {
        return new Font("Courier New", 12F, FontStyle.Regular, GraphicsUnit.Point);
    }
}

Second option, and I did not actually use is during the serialization of the form. I can't take credit, nor remember where I found elsewhere in this forum, but may help too. Apparenty, by hidding the serialization visibility, it doesn't FORCE each individual control's property (in this case, apply for your font) [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

HTH

Briarwood answered 3/8, 2009 at 12:30 Comment(1)
Added both approaches into my CustomTextBox class without success. thanks, anyway.Felicle
M
2

If you don't explicitely set the font of a TextBox, it gets its font from its parent and ancestors, so if the TextBox is on a Panel, it gets its font from that Panel, or from the parent Form.

Marje answered 3/8, 2009 at 12:32 Comment(1)
Parent has same Font "Microsoft SansSerif 8,25" but when typing I don't think it's this Font.Felicle
L
1

I think this will solve your problem

  protected override void OnGotFocus(EventArgs e)
{
    base.OnGotFocus(e);

    SetMultiline(true);
    SetFontFamilyAndStyle(Font.FontFamily.Name);
}

public void SetFontFamilyAndStyle(string fontFamilyName)
{
    // Get the existing font style
    FontStyle currentFontStyle = Font.Style;

    // Create a new font with the specified font family and the existing font style
    Font newFont = new Font(fontFamilyName, Font.Size, currentFontStyle);

    // Set the new font
    SendMessage(Handle, WM_SETFONT, newFont.ToHfont(), (IntPtr)1);
    Font = newFont;

    // Redraw the control
    Invalidate();
}
private const int WM_SETFONT = 0x30;
private const int EM_SETOPTIONS = 0x2003;
private const int ECOOP_SET = 0x0002;

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

public void SetMultiline(bool multiline)
{
    int options = multiline ? ECOOP_SET : 0;
    SendMessage(Handle, EM_SETOPTIONS, (IntPtr)options, IntPtr.Zero);
    Multiline = multiline;
    // Redraw the control
    Invalidate();
}
Leucas answered 9/2 at 12:0 Comment(0)
B
0

Using SetStyle on a Textbox will always mess up the painting, according to this answer.

However ... is there any reason why you can't simply set it's BorderStyle to None?

If you need to, you can even modify the BorderStyle so that it's default value is None, like this:

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace MyControls
{
  // Apply ToolboxBitmap attribute here
  public class CustomTextBox : TextBox
  {
    public CustomTextBox()
    {
      BorderStyle = BorderStyle.None;
    }

    [DefaultValue(typeof(System.Windows.Forms.BorderStyle),"None")]
    public new BorderStyle BorderStyle
    {
      get { return base.BorderStyle; }
      set { base.BorderStyle = value; }
    }
  }
}
Broadspectrum answered 28/6, 2011 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.