使用 ControlStyles.UserPaint 创建带水印的 TextBox 在组件创建时只显示一次水印

编程入门 行业动态 更新时间:2024-10-14 14:19:33
本文介绍了使用 ControlStyles.UserPaint 创建带水印的 TextBox 在组件创建时只显示一次水印的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送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:关键词]

本文发布于:2023-04-30 20:33:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1398905.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:水印   只显示   组件   ControlStyles   UserPaint

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!