vb.net - 自定义水印文本框表现异常

标签 vb.net visual-studio-2008 custom-controls

解决方案:

感谢Patrick下面,我将 C# CodeProject 版本重构为适合我的 VB.NET 版本。希望对大家也有帮助:

Partial Public Class WatermarkedTextBox
    Inherits TextBox

    Private _waterMarkColor As Color = Color.LightGray
    Public Property WaterMarkColor() As Color
        Get
            Return _waterMarkColor
        End Get
        Set(ByVal value As Color)
            _waterMarkColor = value
        End Set
    End Property
    Private _waterMarkText As String = "Watermark"
    Public Property WaterMarkText() As String
        Get
            Return _waterMarkText
        End Get
        Set(ByVal value As String)
            _waterMarkText = value
        End Set
    End Property
    Sub New()

    End Sub
    Protected Overloads Overrides Sub OnCreateControl()
        MyBase.OnCreateControl()
    End Sub
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        Const WM_PAINT As Integer = &HF
        If m.Msg = WM_PAINT Then
            If Text.Length <> 0 Then
                Return
            End If
            Using g As Graphics = Me.CreateGraphics
                g.DrawString(WaterMarkText, Me.Font, New SolidBrush(WaterMarkColor), 0, 0)
            End Using
        End If
    End Sub
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
        MyBase.OnTextChanged(e)
        Invalidate()
    End Sub
    Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
        MyBase.OnLostFocus(e)
        Invalidate()
    End Sub
    Protected Overrides Sub OnFontChanged(ByVal e As System.EventArgs)
        MyBase.OnFontChanged(e)
        Invalidate()
    End Sub
    Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
        '' added so the watermark is not cleared until text is entered
        MyBase.OnGotFocus(e)
        Invalidate()
    End Sub
End Class

我正在构建一个信息亭应用程序,为了保持美观,我决定实现一个带有水印的文本框作为输入字段。我找到了 this projectCodeProject ,将其转换为 VB.NET 并将其放入我的应用程序中。从某种意义上说,它可以很好地加水印并清除它们,但是当我输入文本时,会发生这种情况:

空的:

alt text

填充:

alt text

所以基本上它并没有清除整个水印,只是为文本框的默认高度分配的空间。这是转换后的代码:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Drawing


Partial Public Class WatermarkedTextBox
    Inherits TextBox
    Private oldFont As Font = Nothing
    Private waterMarkTextEnabled As Boolean = False

#Region "Attributes"
    Private _waterMarkColor As Color = Color.LightGray
    Public Property WaterMarkColor() As Color
        Get
            Return _waterMarkColor
        End Get
        Set(ByVal value As Color)
            _waterMarkColor = value
            Invalidate()
        End Set
    End Property
    Private _waterMarkText As String = "Water Mark"
    Public Property WaterMarkText() As String
        Get
            Return _waterMarkText
        End Get
        Set(ByVal value As String)
            _waterMarkText = value
            Invalidate()
        End Set
    End Property
#End Region

    Public Sub New()
        JoinEvents(True)
    End Sub  
    Protected Overloads Overrides Sub OnCreateControl()
        MyBase.OnCreateControl()
        WaterMark_Toggle(Nothing, Nothing)
    End Sub
    Protected Overloads Overrides Sub OnPaint(ByVal args As PaintEventArgs)
        'Dim drawFont As New System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
        Dim drawFont As New Font("Arial", 28, FontStyle.Bold) 'New System.Drawing.Font(oldFont.FontFamily, oldFont.Size, oldFont.Style, oldFont.Unit)
        Dim drawBrush As New SolidBrush(WaterMarkColor)
        args.Graphics.DrawString((If(waterMarkTextEnabled, WaterMarkText, Text)), drawFont, drawBrush, New PointF(0.0F, 0.0F))
        MyBase.OnPaint(args)
    End Sub

    Private Sub JoinEvents(ByVal join As Boolean)
        If join Then
            AddHandler Me.TextChanged, AddressOf WaterMark_Toggle
            AddHandler Me.LostFocus, AddressOf Me.WaterMark_Toggle
            AddHandler Me.FontChanged, AddressOf Me.WaterMark_FontChanged
        End If
    End Sub

    Private Sub WaterMark_Toggle(ByVal sender As Object, ByVal args As EventArgs)
        If Me.Text.Length <= 0 Then
            EnableWaterMark()
        Else
            DisableWaterMark()
        End If
    End Sub

    Private Sub EnableWaterMark()
        oldFont = New System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.waterMarkTextEnabled = True
        Refresh()
    End Sub

    Private Sub DisableWaterMark()
        Me.waterMarkTextEnabled = False
        Me.SetStyle(ControlStyles.UserPaint, False)
        If oldFont IsNot Nothing Then
            Me.Font = New System.Drawing.Font(oldFont.FontFamily, oldFont.Size, oldFont.Style, oldFont.Unit)
        End If
    End Sub

    Private Sub WaterMark_FontChanged(ByVal sender As Object, ByVal args As EventArgs)
        If waterMarkTextEnabled Then
            oldFont = New System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
            Refresh()
        End If
    End Sub
End Class

我试图强制类在 OnPaint 事件中使用我设置的字体大小,但没有成功。是否还有其他我遗漏的东西使这比应该的更困难?

谢谢!

最佳答案

您只是在 DisableWaterMark 子末尾缺少刷新:

Private Sub DisableWaterMark()
    Me.waterMarkTextEnabled = False
    Me.SetStyle(ControlStyles.UserPaint, False)
    If oldFont IsNot Nothing Then
        Me.Font = New System.Drawing.Font(oldFont.FontFamily, oldFont.Size, oldFont.Style, oldFont.Unit)
    End If
    Refresh()
End Sub

编辑:

您可以在 WndProc 中处理 WM_PAINT 消息,而不是使用 UserPaint 控件样式,并且仅在文本为空时才打印水印。结果基本相同。

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    MyBase.WndProc(m)
    Const WM_PAINT As Integer = &HF
    If m.Msg = WM_PAINT Then
        If Text.Length <> 0 Then
            Return
        End If
        Using g As Graphics = Me.CreateGraphics
            g.DrawString("Water Mark", Me.Font, Brushes.LightGray, 0, 0)
        End Using
    End If
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
    MyBase.OnTextChanged(e)
    Invalidate()
End Sub

Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
    MyBase.OnLostFocus(e)
    Invalidate()
End Sub

Protected Overrides Sub OnFontChanged(ByVal e As System.EventArgs)
    MyBase.OnFontChanged(e)
    Invalidate()
End Sub

关于vb.net - 自定义水印文本框表现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/658428/

相关文章:

VB.NET 如何检查网页是否存在

Android - 在 TextView 上显示带边框的文本的方式?

asp.net - 建立与 ADO.NET 命令对象一起使用的连接的最佳方法

asp.net - 在 Visual Studio 2008 中 - 在 web.config 更改 "takes"之前多久?

ios - XCode 如何设置 UISlider.setMinimumTrackImage 进行裁剪,而不是缩放

delphi - 如何在delphi控件中实现接口(interface)

.net - 检查网络可用性 VB.net

asp.net - VB.NET Web 服务 - 从继承类返回只读属性

vb.net - 如何确定事件的发送者是什么类型的对象?

c++ - 如何在我的二进制文件中包含调试信息?