问题描述
限时送ChatGPT账号..我处理继承自 TextBox 的控件.我希望它具有水印属性(您在没有文本时看到的文本).
I work on a control inheriting from TextBox. I want it to feature a watermark property (the text you see when there is no text).
采取的所有步骤:
在一个新的 Visual Studio 实例中,单击创建新项目"链接,选择项目类型 Windows 窗体控件库,将项目命名为 TBW1(带水印的文本框),然后单击确定".将默认控件重命名为 UTextBoxWatermark.
In a new Visual Studio instance, click the link Create New Project, select the project type Windows Forms Control Library, name the project TBW1 (TextBox with Watermark), and click OK. Rename the default control to UTextBoxWatermark.
我想从TextBox控件继承,但是新的用户控件默认继承自UserControl类.这是在设计器中定义的.
I want to inherit from the TextBox control, but new user controls inherit from the UserControl class by default. This is defined in the designer.
要访问和修改设计器,在解决方案资源管理器的顶部,单击显示所有文件.展开 UTextBoxWatermark.vb.双击 CTextBoxWatermark.Designer.vb 在代码编辑器中打开它.
To access and modify the designer, at the top of Solution Explorer, click Show All Files. Expand UTextBoxWatermark.vb. Doubleclick CTextBoxWatermark.Designer.vb to open it in the code editor.
从 UserControl 替换基类 Control
Replace the base class Control from UserControl
Partial Class UTextBoxWatermark
Inherits System.Windows.Forms.UserControl
...
End Class
到文本框
Partial Class UTextBoxWatermark
Inherits System.Windows.Forms.TextBox
...
End Class
在 InitializeComponent 过程中,删除 AutoScaleMode 分配.它不存在于 TextBox 控件中.
In the InitializeComponent procedure, remove the AutoScaleMode assignment. It does not exist in the TextBox control.
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
关闭 CTextBoxWatermark.Designer.vb.使用 Save All 将新项目保存在您的项目主文件夹中.
Close CTextBoxWatermark.Designer.vb. Use Save All to save the new project in your projects main folder.
用户控件设计器不再可用,因为它将从继承的类中绘制,即 TextBox.在代码编辑器中打开 CTextBoxWatermark.vb.正是在这里实现了扩展功能.
The user control designer is not available anymore, because it will be painted from the inherited class, i.e., TextBox. Open CTextBoxWatermark.vb in the code editor. It is here that the extended functionality is implemented.
我想添加 2 个属性:一个用于在 Text 属性包含长度为 0 的字符串时显示的文本,另一个用于绘制此文本的颜色.
I want to add 2 properties: one for the text to be shown when the Text property contains a 0-length string, and one for the color in which this text will be drawn.
Public Class UTextBoxWatermark
'============================================================================
'VARIABLES.
'============================================================================
Private gsWatermarkText As String
Private glWatermarkColor As Color
'============================================================================
'PROPERTIES.
'============================================================================
Public Property WatermarkText As String
Get
Return gsWatermarkText
End Get
Set(sValue As String)
gsWatermarkText = sValue
End Set
End Property
Public Property WatermarkColor As Color
Get
Return glWatermarkColor
End Get
Set(lValue As Color)
glWatermarkColor = lValue
End Set
End Property
End Class
为了绘制文本,OnPaint 事件被覆盖.对于文本框,不会调用此事件,除非在构造函数中将 ControlStyles.UserPaint 属性设置为 True.如果为 true,则控件会绘制自己而不是操作系统这样做.
To draw the text the OnPaint event is overridden. For text boxes, this event is not called, unless the ControlStyles.UserPaint property is set to True in the constructor. If true, the control paints itself rather than the OS doing so.
Public Class UTextBoxWatermark
...
'============================================================================
'CONSTRUCTORS AND DESTRUCTORS.
'============================================================================
Public Sub New()
'This call is required by the designer.
InitializeComponent()
SetStyle(ControlStyles.UserPaint, True)
End Sub
'============================================================================
'EVENT HANDLERS.
'============================================================================
Protected Overrides Sub OnPaint(
ByVal e As System.Windows.Forms.PaintEventArgs)
Dim oBrush As SolidBrush
'If the text is empty now, the watermark text should be written instead.
If Me.Text.Length = 0 Then
oBrush = New SolidBrush(glWatermarkColor)
e.Graphics.DrawString(gsWatermarkText, Me.Font, oBrush, 0, 0)
End If
End Sub
End Class
为了测试组件,它必须立即构建.
In order to test the component, it must be built now.
通过文件">添加">新建项目"向此解决方案添加新项目.选择 Windows Forms App 并将项目命名为 TBW1_Client.在解决方案资源管理器中右键单击它并选择 Set as Startup Project
.
Add a new project to this solution via File > Add > New Project. Select Windows Forms App and name the project TBW1_Client. Right-click it in the solutions explorer and select Set as Startup Project
.
通过 Project > TBW1_Client Properties > References > Add > Browse > [Path to TBW1] > bin > Debug >TBW1.dll > OK 添加对带有水印项目的文本框的引用.
Add a reference to the text box with watermark project via Project > TBW1_Client Properties > References > Add > Browse > [Path to TBW1] > bin > Debug >TBW1.dll > OK.
构建项目.该控件现在在工具箱中可用.双击它以在测试窗口中获得一个控件.它应该看起来和普通的 TextBox 控件完全一样.
Build the project. The control is available in the toolbox now. Doubleclick it to obtain a control in the test window. It should look exactly like an ordinary TextBox control.
单击控件并在属性窗口中检查其属性.两个新定义的属性 WatermarkColor 和 WatermarkText 将显示在属性列表的末尾附近.要测试该功能,请提供不同的颜色(例如红色)和文本阅读(例如在此处键入").
Click on the control and check its properties in the properties window. The two newly defined properties WatermarkColor and WatermarkText will be shown near the end of the properties list. To test the functionality, provide a distinct color, for example red, and a text reading, for instance, "Type here".
它有效!但是,有两个问题:
It works! However, there are two problems:
(1) 当控件第一次显示时它只工作一次.键入内容然后删除文本会使文本框为空.我想再次看到水印文字.
(1) It works just once when the control is shown for the first time. Typing something and then removing the text leaves the text box empty. I would want to see the watermark text again.
(2) 首次显示水印文本时,会显示正确的字体(继承自表单).开始打字时,使用了丑陋的系统字体.
(2) When displaying the watermark text for the first time, the proper font (as inherited from the form) is shown. When starting to type, an ugly system font is used.
我该如何解决这两个问题?
How can I solve these 2 problems?
编辑
根据 VisualVincent 的评论,我改进了 OnPaint:
As per comment from VisualVincent, I improved OnPaint:
Protected Overrides Sub OnPaint(
ByVal e As System.Windows.Forms.PaintEventArgs)
Dim oBrush As SolidBrush
MyBase.OnPaint(e)
'If the text is empty now, the watermark text should be written instead.
If Me.Text.Length = 0 Then
oBrush = New SolidBrush(glWatermarkColor)
e.Graphics.DrawString(gsWatermarkText, Me.Font, oBrush, 0, 0)
Else
oBrush = New SolidBrush(Me.ForeColor)
e.Graphics.DrawString(Me.Text, Me.Font, oBrush, 0, 0)
End If
End Sub
并添加
Private Sub UTextBoxWatermark_TextChanged(sender As Object, e As EventArgs) _
Handles Me.TextChanged
Me.Invalidate()
End Sub
出现水印.开始书写时,文本出现,但仍然是丑陋的系统字体.当我将鼠标悬停在它上面时,文本消失了.
Watermark appears. When starting to write, the text appears, still in ugly System font, though. When I hover with the mouse over it, the text disappers.
当我删除文本时,水印不会重新出现,除非我将鼠标悬停在它上面.
When I remove the text, the watermark does not re-appear, unless I hover with the mouse over it.
推荐答案
由于 OP 放弃自定义前景色要求而复活.
Resurrected due to OP giving up on custom fore color requirement.
WinForm Textbox 类包装的本机编辑控件支持此功能.如果启用视觉样式,它在 Windows Vista 及更高版本中受支持.
This feature is supported by the native edit control that the WinForm Textbox class wraps. It is supported in Windows Vista and greater if visual styles are enabled.
参考:EM_SETCUEBANNER 消息
示例:
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SetWaterMark(TextBox1, "Enter Something Here", True)
End Sub
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Boolean, ByVal lParam As String) As Boolean
End Function
Private Shared Sub SetWaterMark(tb As TextBox, waterMarkText As String, Optional showIfFocused As Boolean = True)
Const ECM_FIRST As Int32 = &H1500
Const EM_SETCUEBANNER As Int32 = ECM_FIRST + 1
If VisualStyles.VisualStyleInformation.IsEnabledByUser Then
SendMessage(tb.Handle, EM_SETCUEBANNER, showIfFocused, waterMarkText)
End If
End Sub
End Class
这篇关于使用 ControlStyles.UserPaint 创建带水印的 TextBox 在组件创建时只显示一次水印的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论