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 TextBoxExInherits 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 SubProtected 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 UsingUsing ForeBrush As New SolidBrush(Me.ForeColorDisabled)Dim sf As New StringFormatSelect Case Me.TextAlignCase HorizontalAlignment.Leftsf.Alignment = StringAlignment.NearCase HorizontalAlignment.Centersf.Alignment = StringAlignment.CenterCase HorizontalAlignment.Rightsf.Alignment = StringAlignment.FarEnd Selecte.Graphics.DrawString(Me.Text, Me.Font, ForeBrush, Me.ClientRectangle, sf)End UsingEnd 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).aspxhttp://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).aspxhttp://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).aspxhttp://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).aspxhttp://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 DisTextBoxInherits System.Windows.Forms.TextBoxPrivate _ForeColorBackup As ColorPrivate _BackColorBackup As ColorPrivate _ColorsSaved As Boolean = FalsePrivate _SettingColors As Boolean = FalsePrivate _BackColorDisabled As Color = SystemColors.ControlPrivate _ForeColorDisabled As Color = SystemColors.WindowTextPrivate Const WM_ENABLE As Integer = &HAPrivate Sub DisTextBox_VisibleChanged(sender As Object, e As System.EventArgs) Handles Me.VisibleChangedIf 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 = TrueIf 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 stateMe.Enabled = TrueMe.Enabled = FalseEnd IfSetColors() ' Change to the Enabled/Disabled colors specified by the userEnd IfEnd SubProtected 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 colorIf Not _SettingColors Then_ForeColorBackup = Me.ForeColorSetColors()End IfEnd SubProtected 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 colorIf Not _SettingColors Then_BackColorBackup = Me.BackColorSetColors()End IfEnd SubPrivate 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 beIf _ColorsSaved Then_SettingColors = TrueIf Me.Enabled ThenMe.ForeColor = Me._ForeColorBackupMe.BackColor = Me._BackColorBackupElseMe.ForeColor = Me.ForeColorDisabledMe.BackColor = Me.BackColorDisabledEnd If_SettingColors = FalseEnd IfEnd SubProtected Overrides Sub OnEnabledChanged(e As System.EventArgs)MyBase.OnEnabledChanged(e)SetColors() ' change colors whenever the Enabled() state changesEnd SubPublic Property BackColorDisabled() As System.Drawing.ColorGetReturn _BackColorDisabledEnd GetSet(ByVal Value As System.Drawing.Color)If Not Value.Equals(Color.Empty) Then_BackColorDisabled = ValueEnd IfSetColors()End SetEnd PropertyPublic Property ForeColorDisabled() As System.Drawing.ColorGetReturn _ForeColorDisabledEnd GetSet(ByVal Value As System.Drawing.Color)If Not Value.Equals(Color.Empty) Then_ForeColorDisabled = ValueEnd IfSetColors()End SetEnd PropertyProtected Overrides ReadOnly Property CreateParams As System.Windows.Forms.CreateParamsGetDim cp As System.Windows.Forms.CreateParamsIf 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 statecp = MyBase.CreateParams ' create window in ENABLED stateMe.Enabled = False ' toggle it back to DISABLED state Elsecp = MyBase.CreateParamsEnd IfReturn cpEnd GetEnd PropertyProtected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)Select Case m.MsgCase 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 messageEnd SelectMyBase.WndProc(m)End SubEnd 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 文本框

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

  1. css美观文本框_如何为美观和用户友好的文本使用类型

    css美观文本框 Text is an important, if not the most important element in a design. It conveys the informa ...

  2. java swing 弹出登录框_用JavaSwing制作一个简单的登录框

    我就懒的一条一条注释了,之前已经都讲过了,直接上代码了. 劝一下大家,打代码不要直接复制,这样是永远都学习不会的,要自己动手敲,自己要有思维. 我这个只供你们自己参考吧,请不要盲目复制,要学习精髓,这 ...

  3. fastai 文本分类_使用Fastai v2和多标签文本分类器检查有毒评论

    fastai 文本分类 The internet has become a basic necessity in recent times and a lot of things which happ ...

  4. 在reader中勾选pdf复选框_绝对可勾选的在WORD 2003中加入复选框的方法

    绝对可勾选的在 word 2003 中加入复选框的方法 方法一: 要在 word 2003 中加入复选框,最好是使用"控件工具箱"来完成. 具体方法是: 打开 Word ,依次点击 ...

  5. 百度云盘搜索引擎微信公证号_微信公众号被百度搜索引擎收录?SEO优化诞生新方法!...

    用"site:mp.weixin.qq.com"这条指令,可以检验各大搜索引擎对微信公众平台文章的收录情况. 下面就以百度为例,具体讲讲如何来操作吧. 被百度搜索收录 1.内容源同 ...

  6. facebook 文本分类_如何禁用和自定义Facebook的通知,文本和电子邮件

    facebook 文本分类 Facebook is really keen on keeping you on their platform. One of the ways they do that ...

  7. java如何创建一个文本框_如何创建绑定到对象的文本框

    我使用Entity Framework为我的类生成我的控制器和视图 . 这就是我所拥有的: DemandeController.cs (控制器): public ActionResult Create ...

  8. 文本空格_别敲空格了,Word文本对齐谨记这2招,好用到炸裂!【Word教程】

    点击图片   1元抢购 Excel.Word.PPT全套课程 相信很多老师或文员们都会使用Word来制作测试试卷.大多数情况下,试卷中选择题内容较多,为了版面的美观性,我们通常会将每题的A.B.C.D ...

  9. python进行文本预处理_用python做NLP:中文文本预处理

    数据挖掘入门与实战  公众号: datadw 一 得到原始文本内容 def FileRead(self,filePath): f = open(filePath) raw=f.read() retur ...

  10. 背景宽高随文本变化_「只要功夫深 不用关键帧」之文本图层小技巧

    「只要功夫深 不用关键帧」将不定期更新一些AE表达式和脚本的奇技淫巧,希望能给大家带来一些启发. 上周有朋友遇到这么个问题: 对一段文字,不管文字长度如何变化,想让背景到文字的边距始终保持不变,在 A ...

最新文章

  1. 交易所频频被盗,你该如何保护自己的数字资产?
  2. 教你如何在 AlertManager 报警通知中展示监控图表
  3. SharePoint 状态机工作流解决方案(一):为什么要用状态机
  4. tensorflow学习(3.tensorboard的使用)
  5. 面绘制经典算法:MarchingCube实现(C++ OpenGl代码篇)
  6. 2021年最值得推荐的报表工具,无代码轻松实现可视化开发
  7. Springboot thymeleaf i18n国际化多语言选择
  8. 基于移动互联网的交互式卫星地面管理终端
  9. OKR组织敏捷目标和绩效管理第一课 OKR的价值、战略与生成
  10. 如何画出一张优秀的架构图?(老鸟必备)
  11. Windows 2008 R2、2012 R2 磁盘扩容、新加磁盘
  12. golang go doc 与 godoc 文档生成查看
  13. Linux时间子系统之Tick层
  14. 《计算机视觉》期末考试复习资料
  15. 读懂 diff 命令
  16. 并发编程JUC深度学习(七)无锁(乐观锁)
  17. SQL2005安装步骤
  18. android:ellipsize=end在ConstraintLayout中无效的问题
  19. 软硬兼济,施耐德电气加速工业数字化转型
  20. 加工中心如何对刀步骤详解,会这六步妈妈再也不担心不会对刀了

热门文章

  1. Quorum共识简析
  2. Oracle PL-SQL基础知识
  3. Android 自定义锁屏_开发自定义ROM提速:红米Note 6 Pro等Android Pie内核源代码上线...
  4. UVA 10041-Vito's Family
  5. c语言next函数定义,c语言的数据结构中,next是如何指向下一个元素的?
  6. MySQL闪回工具之my2sql
  7. ESN学习笔记——echotorch(2)narma10
  8. csu1164 Dominating
  9. PHP 实现爱查快递接口
  10. dingo php,Laravel Lumen RESTFul API 扩展包:Dingo API(一) —— 安装配置篇