winforms 文本框_在禁用的VB.Net WinForms文本框中自定义颜色的新方法

winforms 文本框

A request I've seen often here on Experts-Exchange and out on the internet is for the ability to customize the BackColor and ForeColor of a Disabled TextBox.  A common complaint is that the text in a disabled TextBox is hard to read because the default forecolor is a gray on top of a light gray background.  A good number of these requests are immediately met with fierce opposition to changing the default colors as it might confuse the user since your disabled TextBox will look different from other standard disabled TextBoxes.  This article will not take a stand on this issue.  Let's assume that you've carefully weighed the drawbacks, or have a valid reason to deviate from the norm, and still want to change the colors of your disabled TextBox.  How, then, can we accomplish our goal?

我在Experts-Exchange上和Internet上经常看到的一个请求是能够自定义禁用文本框的BackColor和ForeColor。 一个常见的抱怨是,禁用的TextBox中的文本难以阅读,因为默认的前色是浅灰色背景之上的灰色。 由于禁用的TextBox看起来与其他标准的禁用TextBox不同,因此立即遇到大量此类请求,强烈反对更改默认颜色,这可能会使用户感到困惑。 本文不会就此问题采取立场。 假设您已经仔细权衡了缺点,或者有正当的理由偏离规范,并且仍然想更改禁用的TextBox的颜色。 那么,我们如何才能实现目标呢?

Let's first take a look at the two most common solutions to this problem...

首先让我们看一下这个问题的两种最常见的解决方案...

Common Solution #1 - The ReadOnly() Property Approach

通用解决方案#1-ReadOnly()属性方法

Many solutions suggest that instead of setting Enabled() to False, we instead set ReadOnly() to True which prevents changes to the TextBox, but allows the BackColor and ForeColor to be customized.  A small caveat to that approach is that the BackColor must be set before changes to the ForeColor are honored.  Setting the BackColor to the already assigned BackColor seems to do the trick:

许多解决方案建议,我们不是将Enabled()设置为False,而是将ReadOnly()设置为True,这样可以防止对TextBox进行更改,但允许自定义BackColor和ForeColor。 该方法的一个小警告是必须先设置BackColor,然后才能更改ForeColor。 将BackColor设置为已分配的BackColor似乎可以解决问题:

        TextBox1.BackColor = TextBox1.BackColor

TextBox1.BackColor = TextBox1.BackColor

        TextBox1.ForeColor = Color.Red

TextBox1.ForeColor =颜色。红色

A problem with the ReadOnly() approach, though, is that the TextBox still responds to interaction from the user.  The cursor changes when the mouse enters, and the text can be selected and copied to the clipboard (using both the mouse and the keyboard).  Setting ShortcutsEnabled() on the TextBox to False prevents the text from being copied to the clipboard, but the text can still be selected by the user.  For many, this approach is good enough, and the issue is deemed resolved.  The ReadOnly() approach gives a functionally "disabled" TextBox since the text within cannot technically be changed by the user.  The fact that the TextBox still responds to user interaction, and the text can be selected, is a minor caveat that many simply choose to ignore.

但是,ReadOnly()方法的一个问题是TextBox仍然响应用户的交互。 当鼠标进入时,光标改变,并且可以选择文本并将其复制到剪贴板(使用鼠标和键盘)。 将TextBox上的ShortcutsEnabled()设置为False可以防止将文本复制到剪贴板,但是用户仍然可以选择文本。 对于许多人来说,这种方法足够好,并且可以认为问题已解决。 ReadOnly()方法提供了一个功能上“禁用”的TextBox,因为其中的文本不能由用户进行技术更改。 TextBox仍然可以响应用户交互,并且可以选择文本,这一事实是一个小警告,许多人只是选择忽略。

Common Solution #2 - The Paint() Event Approach

通用解决方案#2-Paint()事件方法

Another common solution to customizing the colors in a disabled TextBox is to derive from the TextBox class, and then manually draw the text in the desired colors via the Paint() event.  This approach typically boils down to something like this:

自定义禁用的TextBox中的颜色​​的另一种常见解决方案是从TextBox类派生,然后通过Paint()事件以所需的颜色手动绘制文本。 这种方法通常可以归结为以下内容:

Public Class TextBoxEx
    Inherits System.Windows.Forms.TextBox

    ' ... other code ...

    Protected Overrides Sub OnEnabledChanged(ByVal e As System.EventArgs)
        MyBase.OnEnabledChanged(e)

	' *We only UserPaint when in a DISABLED state*
        Me.SetStyle(ControlStyles.UserPaint, Not Me.Enabled)
        Me.Refresh()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        ' *We only UserPaint when in a DISABLED state*
        Using BackBrush As New SolidBrush(Me.BackColorDisabled)
            e.Graphics.FillRectangle(BackBrush, Me.ClientRectangle)
        End Using

        Using ForeBrush As New SolidBrush(Me.ForeColorDisabled)
            Dim sf As New StringFormat
            Select Case Me.TextAlign
                Case HorizontalAlignment.Left
                    sf.Alignment = StringAlignment.Near
                Case HorizontalAlignment.Center
                    sf.Alignment = StringAlignment.Center
                Case HorizontalAlignment.Right
                    sf.Alignment = StringAlignment.Far
            End Select

            e.Graphics.DrawString(Me.Text, Me.Font, ForeBrush, Me.ClientRectangle, sf)
        End Using
    End Sub

    ' ... other code ...
		
End Class

This approach has a slight bug in that the text shifts by a couple pixels between an enabled/disabled state.  The bug is quite noticeable if a larger font size is used (try 48 pt, for instance, and observe what happens).  Additionally, the text will not render correctly when disabled if Multiline() has been set to True and the window has been scrolled.  In that case, disabling the TextBox will result in the text being drawn as if the scroll position were at the top, while the actual scroll position remains in the currently scrolled position.  A normal TextBox stays in the same scroll position when disabled.  A third anomaly in using the Paint() event approach manifests itself when the inherited TextBox control starts in an initially disabled state, and then is switched to an enabled state.  Under those conditions, the enabled state renders the text using the wrong font.  This bug can be fixed with more shenanigans in the OnEnabledChanged() event, but I won't get into that here.  Long story short, the Paint() event approach requires a lot of tweaking that results in a still imperfect control.

此方法有一个小错误,即文本在启用/禁用状态之间移动了几个像素。 如果使用较大的字体,则该错误非常明显(例如,尝试48 pt,观察会发生什么)。 此外,如果将Multiline()设置为True并且滚动了窗口,则禁用后文本将无法正确显示。 在这种情况下,禁用TextBox将导致绘制文本,就像滚动位置在顶部一样,而实际滚动位置仍保持在当前滚动位置。 禁用时,普通的TextBox保持在相同的滚动位置。 当继承的TextBox控件以初始禁用状态启动,然后切换到启用状态时,使用Paint()事件方法的第三种异常现象会显现出来。 在这些情况下,启用状态将使用错误的字体呈现文本。 此错误可以通过在OnEnabledChanged()事件中使用更多的恶作剧来解决,但在此不做介绍。 简而言之,Paint()事件方法需要进行大量调整,从而导致控件仍不完善。

“现在换个完全不同的东西!” -Monty Python ("And now for something completely different!" --Monty Python)

The Suppressed WM_ENABLE Approach

禁止的WM_ENABLE方法

According to MSDN, the EnableWindow() API is used to enable and disable a control:

根据MSDN,EnableWindow()API用于启用和禁用控件:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646291(v=vs.85).aspx http://msdn.microsoft.com/zh-CN/library/windows/desktop/ms646291(v=vs.85).aspx
"Enables or disables mouse and keyboard input to the specified window or control. When input is disabled, the window does not receive input such as mouse clicks and key presses. When input is enabled, the window receives all input."
“启用或禁用对指定窗口或控件的鼠标和键盘输入。禁用输入时,该窗口不接收鼠标单击和按键之类的输入。启用输入后,该窗口接收所有输入。”

Why do we care?  The Enabled() Property of the TextBox follows the same procedure as the EnableWindow() API.  It may even use it directly, I'm not sure!

我们为什么在乎? TextBox的Enabled()属性遵循与EnableWindow()API相同的过程。 我不确定它甚至可以直接使用它!

When the EnableWindow() API is used to disable a control, it takes the following three steps:

当使用EnableWindow()API禁用控件时,它将执行以下三个步骤:

(1) Sends the control a WM_CANCELMODE message.

(1)向控件发送WM_CANCELMODE消息。

(2) Adds WS_DISABLED to the window styles for the control.

(2)将WS_DISABLED添加到控件的窗口样式。

(3) Sends the control a WM_ENABLED message.

(3)向控件发送WM_ENABLED消息。

The WM_CANCELMODE message is used to notify the control that it should no longer process input:

WM_CANCELMODE消息用于通知控件它不再应该处理输入:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632615(v=vs.85).aspx http://msdn.microsoft.com/zh-CN/library/windows/desktop/ms632615(v=vs.85).aspx
"When the WM_CANCELMODE message is sent, the DefWindowProc function cancels internal processing of standard scroll bar input, cancels internal menu processing, and releases the mouse capture."
“发送WM_CANCELMODE消息后,DefWindowProc函数将取消标准滚动条输入的内部处理,取消内部菜单处理,并释放鼠标捕获。”

The WS_DISABLED window style prevents mouse feedback and focus:

WS_DISABLED窗口样式可防止鼠标反馈和聚焦:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx http://msdn.microsoft.com/zh-CN/library/windows/desktop/ms632600(v=vs.85).aspx
"A disabled window cannot receive input from the user."
     
“禁用的窗口无法接收到来自用户的输入。”

The WM_ENABLED message is sent to notify the control that it should change its enabled state:

发送WM_ENABLED消息以通知控件它应该更改其启用状态:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632621(v=vs.85).aspx http://msdn.microsoft.com/zh-CN/library/windows/desktop/ms632621(v=vs.85).aspx
"Sent when an application changes the enabled state of a window. It is sent to the window whose enabled state is changing. This message is sent before the EnableWindow function returns, but after the enabled state (WS_DISABLED style bit) of the window has changed.  A window receives this message through its WindowProc function."
     
“在应用程序更改窗口的启用状态时发送。发送到其启用状态正在更改的窗口。此消息在EnableWindow函数返回之前但在窗口的启用状态(WS_DISABLED样式位)更改后发送窗口通过其WindowProc函数接收此消息。”

It is this step, the WM_ENABLED message, that we are most interested in because that is the action that actually causes the TextBox BackColor and ForeColor to change to a disabled state.  Notice the last part of the WM_ENABLED documentation that states, "a window receives this message through its WindowProc function."  Thus when we derive from the normal TextBox class, we can override WndProc() to trap the desired WM_ENABLED message.  Furthermore, from within WndProc(), we can prevent WM_ENABLED from being processed normally simply by exiting WndProc() without executing "MyBase.WndProc(m)".  This is the crux of my approach as suppressing the WM_ENABLED message prevents the ForeColor/BackColor values from automatically changing to the disabled colors.  The other two steps of the EnableWindow() API process occur normally, though, resulting in a TextBox that is functionally disabled, but behaves as if it were enabled with respect to allowing changes to ForeColor/BackColor.  Visually speaking, the TextBox frame will still subdue if the BorderStyle() is set to Fixed3D.  Having suppressed WM_ENABLED, all we have to do is change the standard BackColor/ForeColor properties and we have achieved our goal of a custom colored disabled TextBox!

这是我们最感兴趣的步骤,即WM_ENABLED消息,因为这实际上是导致TextBox BackColor和ForeColor更改为禁用状态的操作。 请注意WM_ENABLED文档的最后一部分,其中指出:“窗口通过其WindowProc函数接收此消息。” 因此,当我们从常规TextBox类派生时,我们可以重写WndProc()来捕获所需的WM_ENABLED消息。 此外,在WndProc()中,我们可以简单地通过退出WndProc()而不执行“ MyBase.WndProc(m)”来阻止WM_ENABLED正常处理。 这是我方法的症结所在,因为禁止显示WM_ENABLED消息会阻止ForeColor / BackColor值自动更改为禁用的颜色。 但是,EnableWindow()API过程的其他两个步骤通常会发生,从而导致TextBox在功能上被禁用,但是就允许更改ForeColor / BackColor而言,其行为就像已启用一样。 从视觉上讲,如果将BorderStyle()设置为Fixed3D,则TextBox框架仍将消失。 取消了WM_ENABLED之后,我们要做的就是更改标准BackColor / ForeColor属性,并且我们实现了自定义着色的禁用TextBox的目标!

The suppressed WM_ENABLED approach addresses the ReadOnly() shortcoming by not giving any visual feedback with the mouse, and not allowing the TextBox to be focused.  It addresses the Paint() event approach shortcomings because the control paints itself as it normally would.  We are not attempting to recreate how the control should look with Graphics calls, the control simply draws itself as it always did before.

被抑制的WM_ENABLED方法通过不使用鼠标给出任何视觉反馈并不允许TextBox聚焦来解决ReadOnly()的缺点。 它解决了Paint()事件方法的缺点,因为该控件会像往常一样绘制自身。 我们并不是试图通过Graphics调用来重新创建控件的外观,而是像以前一样简单地绘制自身。

Presenting the DisTextBox() Control!

呈现DisTextBox()控件!

Public Class DisTextBox
    Inherits System.Windows.Forms.TextBox

    Private _ForeColorBackup As Color
    Private _BackColorBackup As Color
    Private _ColorsSaved As Boolean = False
    Private _SettingColors As Boolean = False

    Private _BackColorDisabled As Color = SystemColors.Control
    Private _ForeColorDisabled As Color = SystemColors.WindowText

    Private Const WM_ENABLE As Integer = &HA

    Private Sub DisTextBox_VisibleChanged(sender As Object, e As System.EventArgs) Handles Me.VisibleChanged
        If Not Me._ColorsSaved AndAlso Me.Visible Then
            ' Save the ForeColor/BackColor so we can switch back to them later
            _ForeColorBackup = Me.ForeColor
            _BackColorBackup = Me.BackColor
            _ColorsSaved = True

            If Not Me.Enabled Then ' If the window starts out in a Disabled state...
                ' Force the TextBox to initialize properly in an Enabled state,
                ' then switch it back to a Disabled state
                Me.Enabled = True
                Me.Enabled = False
            End If

            SetColors() ' Change to the Enabled/Disabled colors specified by the user
        End If
    End Sub

    Protected Overrides Sub OnForeColorChanged(e As System.EventArgs)
        MyBase.OnForeColorChanged(e)

        ' If the color is being set from OUTSIDE our control,
        ' then save the current ForeColor and set the specified color
        If Not _SettingColors Then
            _ForeColorBackup = Me.ForeColor
            SetColors()
        End If
    End Sub

    Protected Overrides Sub OnBackColorChanged(e As System.EventArgs)
        MyBase.OnBackColorChanged(e)

        ' If the color is being set from OUTSIDE our control,
        ' then save the current BackColor and set the specified color
        If Not _SettingColors Then
            _BackColorBackup = Me.BackColor
            SetColors()
        End If
    End Sub

    Private Sub SetColors()
        ' Don't change colors until the original ones have been saved,
        ' since we would lose what the original Enabled colors are supposed to be
        If _ColorsSaved Then
            _SettingColors = True
            If Me.Enabled Then
                Me.ForeColor = Me._ForeColorBackup
                Me.BackColor = Me._BackColorBackup
            Else
                Me.ForeColor = Me.ForeColorDisabled
                Me.BackColor = Me.BackColorDisabled
            End If
            _SettingColors = False
        End If
    End Sub

    Protected Overrides Sub OnEnabledChanged(e As System.EventArgs)
        MyBase.OnEnabledChanged(e)

        SetColors() ' change colors whenever the Enabled() state changes
    End Sub

    Public Property BackColorDisabled() As System.Drawing.Color
        Get
            Return _BackColorDisabled
        End Get
        Set(ByVal Value As System.Drawing.Color)
            If Not Value.Equals(Color.Empty) Then
                _BackColorDisabled = Value
            End If
            SetColors()
        End Set
    End Property

    Public Property ForeColorDisabled() As System.Drawing.Color
        Get
            Return _ForeColorDisabled
        End Get
        Set(ByVal Value As System.Drawing.Color)
            If Not Value.Equals(Color.Empty) Then
                _ForeColorDisabled = Value
            End If
            SetColors()
        End Set
    End Property

    Protected Overrides ReadOnly Property CreateParams As System.Windows.Forms.CreateParams
        Get
            Dim cp As System.Windows.Forms.CreateParams
            If Not Me.Enabled Then ' If the window starts out in a disabled state...
                ' Prevent window being initialized in a disabled state:
                Me.Enabled = True ' temporary ENABLED state
                cp = MyBase.CreateParams ' create window in ENABLED state
                Me.Enabled = False ' toggle it back to DISABLED state 
            Else
                cp = MyBase.CreateParams
            End If
            Return cp
        End Get
    End Property

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Select Case m.Msg
            Case WM_ENABLE
                ' Prevent the message from reaching the control,
                ' so the colors don't get changed by the default procedure.
                Exit Sub ' <-- suppress WM_ENABLE message

        End Select

        MyBase.WndProc(m)
    End Sub

End Class

Spare me the details!  You've shown me the code; how do I use this thing?

保留我的细节! 您已经给我看了代码; 我怎么用这个东西?

If you just want to use the control without getting into the gory details, paste the code above into your project and re-build it.  You should then see the new DisTextBox control at the top of your ToolBox.  Simply use the new DisTextBox in place of the old TextBox where ever you need it.  The new DisTextBox control has two additional properties, ForeColorDisabled() and BackColorDisabled(), that allow you to set your desired colors for when the TextBox is in a disabled state.  I've set the default ForeColorDisabled() value to Black, which makes it much easier to read.  The default BackColorDisabled() value is the same as the normal disabled TextBox.  To disable the control, use the inherited Enabled() property as usual:

如果您只想使用该控件而不用深入了解细节,请将上面的代码粘贴到您的项目中并重新构建。 然后,您应该在工具箱的顶部看到新的DisTextBox控件。 只需在需要的地方使用新的DisTextBox代替旧的TextBox。 新的DisTextBox控件具有两个附加属性,即ForeColorDisabled()和BackColorDisabled(),使用它们可以设置当TextBox处于禁用状态时所需的颜色。 我已经将默认的ForeColorDisabled()值设置为Black,这使它更易于阅读。 默认的BackColorDisabled()值与普通的禁用的TextBox相同。 要禁用控件,请照常使用继承的Enabled()属性:

	DisTextBox1.Enabled = False ' Disable the control (automatically switches to disabled colors)
	DisTextBox1.Enabled = True ' Enable the control (automatically switches to enabled colors)

If you're interested in the implementation itself, please continue reading below.

如果您对实现本身感兴趣,请继续阅读以下内容。

“细节中有魔鬼”-匿名 ("The Devil is in the Details" --Anonymous)

Swapping Enabled and Disabled Colors

交换启用和禁用的颜色

The first two variables in the class are of type Color and are called "_ForeColorBackup" and "_BackColorBackup".  Since the control never really disables, and simply stays in the enabled state, we are actually changing the normal ForeColor and BackColor Properties when we want to display the disabled colors.  This means we must save the current ForeColor and BackColor values, or they will be lost when we change them to the disabled colors.  The "_ForeColorBackup" and "_BackColorBackup" variables, then, do exactly what their names suggest, and store backups of the enabled colors so we can later switch back to them when necessary.

该类中的前两个变量为Color类型,分别称为“ _ForeColorBackup”和“ _BackColorBackup”。 由于控件从不真正禁用,而只是停留在启用状态,因此,当我们要显示禁用的颜色时,实际上是在更改常规的ForeColor和BackColor属性。 这意味着我们必须保存当前的ForeColor和BackColor值,否则当我们将其更改为禁用的颜色时,它们将会丢失。 然后,“ _ ForeColorBackup”和“ _BackColorBackup”变量完全按照其名称的含义进行操作,并存储已启用颜色的备份,以便以后在需要时可以切换回它们。

The next variable is the "_ColorsSaved" boolean flag, which starts out set to false.  It indicates whether the initial ForeColor and BackColor values have been saved to the backup variables.  These colors are saved in the VisibleChanged() event where the flag is toggled to true.  Also in the VisibleChanged() event, if the control starts in a disabled state, we must toggle the Enabled() property to True and then back to False to correctly initialize the control.  Failure to do so results in the TextBox being displayed in the disabled colors, but still allowing user interaction in an enabled state.  This initial backup of the colors, and toggling of the enabled state, only occur once when the control first appears.

下一个变量是“ _ColorsSaved”布尔标志,其开始设置为false。 它指示初始ForeColor和BackColor值是否已保存到备份变量中。 这些颜色保存在VisibleChanged()事件中,标志被切换为true。 同样在VisibleChanged()事件中,如果控件以禁用状态启动,则必须将Enabled()属性切换为True,然后再切换为False,以正确初始化控件。 否则,将导致TextBox以禁用的颜色显示,但仍允许用户在启用状态下进行交互。 颜色的这种初始备份以及启用状态的切换仅在控件首次出现时发生一次。

Declared next is another boolean flag called "_SettingColors".  It is initially false, and only becomes true when the colors are being set by the SetColors() method.  Since enabled and disabled colors are both displayed with the normal ForeColor/BackColor properties, we need to distinguish whether those values are being set externally, or as a result of being internally changed by the SetColors() method.  This distinction is important because changing the ForeColor/BackColor properties will trigger the OnForeColorChanged()/OnBackColorChanged() methods, which is where we save the new values to the backup variables mentioned previously.  If we are in a disabled state, the new values placed into the the ForeColor/BackColor properties should not be saved, as doing so would cause the enabled colors to be lost.  To prevent this from happening, backups of the colors are only made when "_SettingColors" is false.

接下来声明的是另一个称为“ _SettingColors”的布尔标志。 最初为false,仅在使用SetColors()方法设置颜色时才为true。 由于启用和禁用的颜色都使用普通的ForeColor / BackColor属性显示,因此我们需要区分这些值是在外部设置的还是由SetColors()方法在内部进行更改的结果。 这种区别很重要,因为更改ForeColor / BackColor属性将触发OnForeColorChanged()/ OnBac kColorChan ged()方法,在这里我们将新值保存到前面提到的备份变量中。 如果我们处于禁用状态,则不应保存放置在ForeColor / BackColor属性中的新值,因为这样做会导致启用的颜色丢失。 为了防止这种情况的发生,仅当“ _SettingColors”为false时才进行颜色备份。

The SetColors() method is used to display the correct set of colors based on whether the control is currently enabled or not.  It is a simple routine that first verifies that the enabled colors have been saved to the backup variables, then sets the ForeColor/BackColor properties to the backup colors if the control is enabled, and to the desired disabled colors when the control is in a disabled state.  It wraps the color setting logic in a block that toggles "_SettingColors" to true and then back to false.  When the Enabled() property of the control is set, the OnEnabledChanged() method fires.  This method simply invokes the base class handler, then calls SetColors() to update the control with the desired state colors.

SetColors()方法用于根据控件是否当前启用来显示正确的颜色集。 这是一个简单的例程,首先验证启用的颜色是否已保存到备份变量中,然后在启用了控件的情况下将ForeColor / BackColor属性设置为备份颜色,并在控件处于禁用状态时将其设置为所需的禁用颜色。州。 它将颜色设置逻辑包装在一个块中,该块将“ _SettingColors”切换为true,然后又切换为false。 设置控件的Enabled()属性后,将触发OnEnabledChanged()方法。 此方法仅调用基类处理程序,然后调用SetColors()以使用所需的状态颜色更新控件。

Wrapping up the code related to swapping enabled and disabled colors are the variables that store the desired disabled colors.  These two private variables are called "_BackColorDisabled" and "_ForeColorDisabled".  Not surprisingly, they are wrapped in public properties called BackColorDisabled() and ForeColorDisabled().  When those two properties are set, their new values are stored in their respective private variables and then the control is updated (if necessary) with a call to the SetColors() method.

包装与交换启用和禁用的颜色有关的代码是存储所需的禁用颜色的变量。 这两个专用变量称为“ _BackColorDisabled”和“ _ForeColorDisabled”。 毫不奇怪,它们被包装在称为BackColorDisabled()和ForeColorDisabled()的公共属性中。 设置这两个属性后,它们的新值将存储在它们各自的私有变量中,然后通过调用SetColors()方法来更新控件(如有必要)。

CreateParams() and WndProc()

CreateParams()和WndProc()

The CreateParams() override is necessary only for when DisTextBox() starts out in an initially disabled state.  When starting disabled, we have to switch the Enabled() property to true, call the base class CreateParams() method, then switch Enabled() back to false.  Without this override switcheroo, the control will default to the standard disabled state and ignore our custom disabled colors.

仅当DisTextBox()以初始禁用状态启动时才需要CreateParams()覆盖。 当开始禁用时,我们必须将Enabled()属性切换为true,调用基类CreateParams()方法,然后将Enabled()切换回false。 如果没有此替代开关,则控件将默认为标准禁用状态,并忽略我们的自定义禁用颜色。

Lastly we come to the WndProc() method which processes all standard windows messages for our control.  Remember, the whole premise of this disabled TextBox being able to have custom colors was trapping the WM_ENABLE message and suppressing it.  That is exactly all this method does.  All other messages are processed normally by calling "MyBase.WndProc(m)".  The WM_ENABLE message is suppressed by simply exiting the sub preventing the base class WndProc() from executing.

最后,我们来看WndProc()方法,该方法为我们的控件处理所有标准Windows消息。 请记住,此禁用的TextBox能够具有自定义颜色的整个前提是捕获并抑制了WM_ENABLE消息。 这就是该方法所做的全部。 通过调用“ MyBase.WndProc(m)”可以正常处理所有其他消息。 通过简单地退出子类以阻止执行基类WndProc()来抑制WM_ENABLE消息。

If any of the code seems pointless, it's probably related to getting the control to work when starting in a disabled state.

如果任何代码似乎毫无意义,则可能与在禁用状态下启动控件时起作用有关。

Conclusion

结论

That's it!  Hopefully I've explained the concept and code well enough for everyone to understand it; or at least know why the code was put in place.  The DisTextBox() should give you the ability to customize both the fore and back colors of the standard TextBox when it is in a disabled state.

而已! 希望我已经对概念和代码进行了充分的解释,以使每个人都能理解它。 或至少知道为什么要放置代码。 DisTextBox()应该使您能够自定义标准TextBox处于禁用状态时的前后颜色。

翻译自: https://www.experts-exchange.com/articles/10842/A-New-Approach-for-Custom-Colors-in-a-Disabled-VB-Net-WinForms-TextBox.html

winforms 文本框

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值