Changing the border style of a textbox control without raising events
Changing the border style of a textbox control without raising events <URL:http://dotnet.mvps.org/dotnet/faqs/?id=textboxborderstyle&lang=en> ---------------------------------------------------------------------------- Changing the border style of a textbox control without raising events When changing the border style of a textbox control in .NET 1.0 and .NET 1.1, the original 'EDIT' window is destroyed and a new window is created. This causes some issues, for example, changing the border style fires the control's 'Enter' event. The sample "Adding a standard border to a control" (<URL:http://www.bobpowell.net/addborder.htm>) written by Bob Powell [MVP] suffers from the same problem. The following listing shows a reworked version of the listing given in the referenced article: \\\ Private m_BorderStyle As BorderStyle Public Property BorderStyle() As BorderStyle Get Return m_BorderStyle End Get Set(ByVal Value As BorderStyle) m_BorderStyle = Value Me.RecreateHandle() Me.Invalidate() End Set End Property Protected Overrides ReadOnly Property CreateParams() As CreateParams Get Const WS_BORDER As Int32 = &H800000 Const WS_EX_STATICEDGE As Int32 = &H20000 Dim cp As CreateParams = MyBase.CreateParams Select Case m_BorderStyle Case BorderStyle.FixedSingle cp.Style = cp.Style Or WS_BORDER Case BorderStyle.Fixed3D cp.ExStyle = cp.ExStyle Or WS_EX_STATICEDGE 'Case BorderStyle.None ' ' End Select Return cp End Get End Property /// Instead of adjusting the window styles with p/invoke on 'GetWindowLong', the 'RecreateHandle' method is called which causes the 'Get' procedure of the 'CreateParams' property to be called. There, the style bits are adjusted according to the selected border style. The solution shown above is fully managed, nevertheless it causes wrong behavior, or in other words, "buggy" behavior. The class 'ExtendedTextBox' does not have this problem and does not make use of unmanaged code too: \\\ Imports System Imports System.ComponentModel Imports System.Windows.Forms ''' <summary> ''' An extended textbox control that fixes a bug in the implementation ''' of the textbox's <c>BorderStyle</c> property. ''' <summary> Public Class ExtendedTextBox Inherits TextBox Private Const WS_BORDER As Int32 = &H800000 Private Const WS_EX_CLIENTEDGE As Int32 = &H200 Private m_BorderStyle As BorderStyle = BorderStyle.Fixed3D Protected Overrides ReadOnly Property CreateParams() As CreateParams Get ' Adjust window styles to reflect border style selected for ' this class. Dim cp As CreateParams = MyBase.CreateParams Dim dwStyle As Int32 = cp.Style Dim dwExStyle As Int32 = cp.ExStyle BorderStyleToWindowStyle(Me.BorderStyle, dwStyle, dwExStyle) cp.Style = dwStyle cp.ExStyle = dwExStyle Return cp End Get End Property ''' <summary> ''' Gets or sets the border style of the textbox. ''' </summary> ''' <value>The border style of the textbox.</value> ''' <remarks> ''' This property behaves slightly differently from the original ''' implementation. If the border is changed on the framework's ''' textbox control, the control's size is adjusted. This is not ''' the case for this control. ''' </remarks> < _ Category("Appearance"), _ Description("Gets or sets the border style of the textbox."), _ DefaultValue(GetType(BorderStyle), "Fixed3D") _ > _ Public Shadows Property BorderStyle() As BorderStyle Get Return m_BorderStyle End Get Set(ByVal Value As BorderStyle) If Value <> Me.BorderStyle Then m_BorderStyle = Value ' Calls 'CreateParams' and updates the window styles ' accordingly. Me.UpdateStyles() End If End Set End Property Private Sub BorderStyleToWindowStyle( _ ByVal BorderStyle As BorderStyle, _ ByRef dwStyle As Int32, _ ByRef dwExStyle As Int32 _ ) dwStyle = dwStyle And Not WS_BORDER dwExStyle = dwExStyle And Not WS_EX_CLIENTEDGE Select Case BorderStyle Case BorderStyle.Fixed3D dwExStyle = dwExStyle Or WS_EX_CLIENTEDGE Case BorderStyle.FixedSingle dwStyle = dwStyle Or WS_BORDER 'Case BorderStyle.None ' ' End Select End Sub End Class /// The code below can be used to check if changing the control's border style causes a change of the control's handle. If the handle is different from the handle obtained before changing the border style, the control was recreated: \\\ Dim Handle As IntPtr ' Original textbox. Dim TextBox1 As New TextBox() Handle = TextBox1.Handle TextBox1.BorderStyle = BorderStyle.FixedSingle MsgBox(Handle.Equals(TextBox1.Handle)) ' Textbox with fix applied. Dim TextBox2 As New ExtendedTextBox() Handle = TextBox2.Handle TextBox2.BorderStyle = BorderStyle.FixedSingle MsgBox(Handle.Equals(TextBox2.Handle)) /// There is a known issue for the textbox replacement described above. When changing the border stye to 'FixedSingle' at designtime and then rebuilding the solution, the border will be shown incorrectly. This does not occur at runtime. An article about designable borders for Windows Forms controls can be found here: Adding designable borders to user controls <URL:http://www.thecodeproject.com/cs/miscctrl/CsAddingBorders.asp>