Ändern der Rahmenart eines TextBox-Steuerelements ohne Auslösen von
Ereignissen
<URL:https://dotnet.currifex.org/dotnet/faqs/textboxborderstyle/de/>
----------------------------------------------------------------------------
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>