2013-07-04 20 views
6

Ho il seguente codice:Cambia Colore bordo in TextBox C#

public class OurTextBox : TextBox 
{ 
    public OurTextBox() 
     : base() 
    { 
     this.SetStyle(ControlStyles.UserPaint, true); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     Pen penBorder = new Pen(Color.Gray, 1); 
     Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1); 
     e.Graphics.DrawRectangle(penBorder, rectBorder); 
    } 
} 

Questo è il lavoro perfetto, ma non mostra il testo fino a quando si arriva a fuoco.

Qualcuno può aiutarmi? Che c'è?

Grazie in anticipo.

+0

non si dovrebbe usare 'OnPaint' per il disegno di frontiera per' TextBox'. Invece dovresti gestire il messaggio 'WM_NCPAINT' in' WndProc' e disegnare il bordo nell'area non client, come [this] (http://stackoverflow.com/questions/17466067/change-border-color-in-textbox-c -sharp/39420512 # 39420512). –

risposta

5

È necessario disegnare manualmente il testo.

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 
    Pen penBorder = new Pen(Color.Gray, 1); 
    Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1); 
    e.Graphics.DrawRectangle(penBorder, rectBorder); 

    Rectangle textRec = new Rectangle(e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1); 
    TextRenderer.DrawText(e.Graphics, Text, this.Font, textRec, this.ForeColor, this.BackColor, TextFormatFlags.Default); 
} 

In alternativa si può provare ad usare e.Graphics.DrawString() metodo se TextRenderer non sta dando risultati desiderati (ho sempre risultati migliori con questo approccio tu).

+2

Non si deve sovrascrivere 'OnPaint' perché è necessario disegnare la stringa, il segno di omissione lampeggiante, l'evidenziazione della selezione e così via. Invece dovresti gestire il messaggio 'WM_NCPAINT' in' WndProc' e disegnare il bordo nell'area non client, come [this] (http://stackoverflow.com/questions/17466067/change-border-color-in-textbox-c -sharp/39420512 # 39420512). –

1

Ci sono diversi modi per farlo e nessuno è l'ideale. Questa è solo la natura di WinForms. Tuttavia, hai alcune opzioni. Riassumo:

Un modo in cui è possibile ottenere ciò che si desidera è incorporando unoin un Panel come segue.

public class BorderedTextBox : Panel 
{ 
    private TextBox textBox; 
    private bool focusedAlways = false; 
    private Color normalBorderColor = Color.Gray; 
    private Color focusedBorderColor = Color.Red; 

    public BorderTextBox() 
    { 
     this.DoubleBuffered = true; 
     this.Padding = new Padding(2); 

     this.TextBox = new TextBox(); 
     this.TextBox.AutoSize = false; 
     this.TextBox.BorderStyle = BorderStyle.None; 
     this.TextBox.Dock = DockStyle.Fill; 
     this.TextBox.Enter += new EventHandler(this.TextBox_Refresh); 
     this.TextBox.Leave += new EventHandler(this.TextBox_Refresh); 
     this.TextBox.Resize += new EventHandler(this.TextBox_Refresh); 
     this.Controls.Add(this.TextBox); 
    } 

    private void TextBox_Refresh(object sender, EventArgs e) 
    { 
     this.Invalidate(); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     e.Graphics.Clear(SystemColors.Window); 
     using (Pen borderPen = new Pen(this.TextBox.Focused || FocusedAlways ? 
      focusedBorderColor : normalBorderColor)) 
     { 
      e.Graphics.DrawRectangle(borderPen, 
       new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1)); 
     } 
     base.OnPaint(e); 
    } 

    public TextBox TextBox 
    { 
     get { return textbox; } 
     set { textbox = value; } 
    } 

    public bool FocusedAlaways 
    { 
     get { return focusedAlways; } 
     set { focusedAlways = value; } 
    } 
} 

È anche possibile eseguire questa operazione senza escludere alcun controllo, ma il metodo precedente è migliore. Quanto sopra disegnerà un bordo quando il controllo diventa attivo. se si desidera che il bordo sia permanentemente impostato, impostare la proprietà FocusedAlways su True.

Spero che questo aiuti.

+1

Wow, una quantità incredibile di lavoro per un semplice confine. Questo è il motivo per cui si dovrebbe sempre usare wpf, suppongo :) –

+1

Mi sono appena trasferito a WPF. Mi sto divertendo, ma è difficile venire dal background di WinForms - vorrei averlo iniziato. MVVM è una cosa difficile da farti andare in testa, ma l'intera cosa è sicuramente meglio! Ora ho un progetto WinForm con un sacco di questi tipi di soluzioni che ho raccolto nel corso degli anni. – MoonKnight

+1

Grazie. Sono d'accordo con Nick ... È incredibile lavorare così tanto per cambiare un confine –

1

box set di testo Stile bordo su Nessuno poi scrivere questo codice in forma contenitore di eventi "dipingere"

private void Form1_Paint(object sender, PaintEventArgs e) 
     { 
System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X, TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height); 

       rect.Inflate(1, 1); // border thickness 
       System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect, Color.DeepSkyBlue, ButtonBorderStyle.Solid); 

} 
19

Per modificare il colore del bordo di TextBox è possibile ignorare WndProc metodo e gestire WM_NCPAINT messaggio. Quindi ottenere il contesto del dispositivo della finestra del controllo utilizzando GetWindowDC perché vogliamo disegnare nell'area di controllo non client. Quindi, per disegnare, è sufficiente creare un oggetto Graphics da quel contesto, quindi disegnare il bordo per il controllo.

Per ridisegnare il controllo quando si modifica la proprietà BorderColor, è possibile utilizzare il metodo RedrawWindow.

Codice

Ecco un TextBox che ha una proprietà BorderColor. Il controllo utilizza BorderColor se i valori delle proprietà sono diversi da Color.Transparent e BorderStyle è il valore predefinito Fixed3d.

using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 
public class MyTextBox : TextBox { 
    const int WM_NCPAINT = 0x85; 
    const uint RDW_INVALIDATE = 0x1; 
    const uint RDW_IUPDATENOW = 0x100; 
    const uint RDW_FRAME = 0x400; 
    [DllImport("user32.dll")] 
    static extern IntPtr GetWindowDC(IntPtr hWnd); 
    [DllImport("user32.dll")] 
    static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); 
    [DllImport("user32.dll")] 
    static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprc, IntPtr hrgn, uint flags); 
    Color borderColor = Color.Blue; 
    public Color BorderColor { 
     get { return borderColor; } 
     set { borderColor = value; 
      RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero, 
       RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE); 
     } 
    } 
    protected override void WndProc(ref Message m) { 
     base.WndProc(ref m); 
     if (m.Msg == WM_NCPAINT && BorderColor != Color.Transparent && 
      BorderStyle == System.Windows.Forms.BorderStyle.Fixed3D) { 
      var hdc = GetWindowDC(this.Handle); 
      using (var g = Graphics.FromHdcInternal(hdc)) 
      using (var p = new Pen(BorderColor)) 
       g.DrawRectangle(p, new Rectangle(0, 0, Width - 1, Height - 1)); 
      ReleaseDC(this.Handle, hdc); 
     } 
    } 
    protected override void OnSizeChanged(EventArgs e) { 
     base.OnSizeChanged(e); 
     RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero, 
       RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE); 
    } 
} 

Risultato

Ecco il risultato utilizzando diversi colori e diversi stati.Tutti gli stati di border-style è supportato come si può vedere nella immagine qui sotto ed è possibile utilizzare qualsiasi colore per il bordo:

enter image description here

+0

So che questa domanda è stata fatta 3 anni fa, ma sono lottando con lo stesso problema adesso. Ho usato il tuo metodo, ma ho un problema di sfarfallio del bordo: http://imgur.com/RmkvXT0 Forse hai avuto lo stesso problema? Grazie per i suggerimenti! – Misiu

+0

@Misiu Posso confermare il problema e cercherò di risolverlo. –

+0

@Misiu È possibile sovrascrivere 'OnSizeChanged' e chiamare' RedrawWindow' nello stesso modo in cui è stato chiamato 'BorderColor'. –