水印文本框对齐中心

时间:2017-01-05 12:51:37

标签: .net vb.net

我正在使用自定义控件watermark textbox并且它很完美,但问题是我无法将水印textAlign更改为居中或从右到左。 默认情况下,它是从左到右,我怎样才能使它成为中心或从右到左?

这是代码:

Imports System.ComponentModel

Public Class Watermark
Inherits TextBox

'Declare A Few Variables
Dim WaterText As String
Dim WaterColor As Color
Dim WaterFont As Font
Dim WaterBrush As SolidBrush
Dim WaterContainer As Panel

Public Sub New()
    MyBase.New()
    StartProcess()
End Sub

Private Sub StartProcess()
    'Assign Values To the Variables
    WaterText = "Default Watermark"
    WaterColor = Color.Gray
    WaterFont = New Font(Me.Font, FontStyle.Italic)
    WaterBrush = New SolidBrush(WaterColor)

    CreateWatermark()

    AddHandler TextChanged, AddressOf ChangeText
    AddHandler FontChanged, AddressOf ChangeFont
End Sub

Private Sub CreateWatermark()
    WaterContainer = New Panel
    Me.Controls.Add(WaterContainer)
    AddHandler WaterContainer.Click, AddressOf Clicked
    AddHandler WaterContainer.Paint, AddressOf Painted
End Sub

Private Sub RemoveWatermark()
    Me.Controls.Remove(WaterContainer)
End Sub

Private Sub ChangeText(sender As Object, e As EventArgs)
    If Me.TextLength <= 0 Then
        CreateWatermark()
    ElseIf Me.TextLength > 0 Then
        RemoveWatermark()
    End If
End Sub

Private Sub ChangeFont(sender As Object, e As EventArgs)
    WaterFont = New Font(Me.Font, FontStyle.Italic)
End Sub

Private Sub Clicked(sender As Object, e As EventArgs)
    Me.Focus()
End Sub

Private Sub Painted(sender As Object, e As PaintEventArgs)
    WaterContainer.Location = New Point(2, 0)
    WaterContainer.Anchor = AnchorStyles.Left Or AnchorStyles.Right
    WaterContainer.Height = Me.Height
    WaterContainer.Width = Me.Width
    WaterBrush = New SolidBrush(WaterColor)

    Dim Graphic As Graphics = e.Graphics
    Graphic.DrawString(WaterText, WaterFont, WaterBrush, New PointF(-2.0!, 1.0!))
End Sub

Protected Overrides Sub OnInvalidated(e As System.Windows.Forms.InvalidateEventArgs)
    MyBase.OnInvalidated(e)
    WaterContainer.Invalidate()
End Sub

<Category("Watermark Attributes"), Description("Sets Watermark Text")> Public Property WatermarkText As String
    Get
        Return WaterText
    End Get
    Set(value As String)
        WaterText = value
        Me.Invalidate()
    End Set
End Property

<Category("Watermark Attributes"), Description("Sets Watermark Color")> Public Property WatermarkColor As Color
    Get
        Return WaterColor
    End Get
    Set(value As Color)
        WaterColor = value
        Me.Invalidate()
    End Set
End Property
End Class

2 个答案:

答案 0 :(得分:2)

有几点需要注意:

  • 在Windows中已经有一种称为CueBanner的机制,它很容易通过表单代码或作为自定义控件实现
  • 您的实现并不像Native实现那样行事或看起来相同:
    a)在隐藏Panel之前,没有视觉提示(TB Cursor) b)您的Panel / Cue文本在您开始输入之前不会消失。这似乎是你想要的,但它不是原生的通常工作方式(正如Visual Vincent在评论中指出的那样,有一个选项。我个人不记得看到它足以注册我了。) /> c)在本机实现中,Cue Text / Watermark使用与控件相同的字体。只有设置为Combobox的{​​{1}}使用斜体(可能您从未注意到这一点)。
  • 你的应用程序漏洞非常糟糕:DropDownList被重复调用,通过每次创建一个新的CreateWatermark来重新显示Watermark / CueText,但是你没有丢弃旧版本。请记住:如果您在代码中创建控件,则还需要将其置于,而不是仅将其从控件集合中删除。
  • 对于Panel对象也是如此,尽管只有在TextBox上的Font发生变化时才会有效。

首先,回答您提出的问题 - 允许左,右,中心TextAlignment。

Font
  • 这使用Private Sub Painted(sender As Object, e As PaintEventArgs) ' this can all be moved to the CreateWatermark method 'WaterContainer.Location = New Point(0, 0) 'WaterContainer.Anchor = AnchorStyles.Left Or AnchorStyles.Right 'WaterContainer.Height = Me.Height 'WaterContainer.Width = Me.Width Dim rect As New Rectangle(2, 1, Width - 8, Height - 2) Dim TxtFlags As TextFormatFlags Select Case TxtAlign Case HorizontalAlignment.Center TxtFlags = TextFormatFlags.HorizontalCenter Case HorizontalAlignment.Left TxtFlags = TextFormatFlags.Left Case HorizontalAlignment.Right TxtFlags = TextFormatFlags.Right End Select TextRenderer.DrawText(e.Graphics, WatermarkText, WFont, rect, WatermarkColor, TxtFlags) End Sub 来绘制文本,这通常是控件的更好选择(保存TextRenderer以绘制到位图和图像)
  • 此版本根据新的Graphics.DrawString()属性显示该属性,以防您希望它与WatermarkTextAlign不同。如果没有,请使用Visual Vincent的部分版本或组合它们。

Cue Banner

TextBox

用法很简单:

Partial Friend Class NativeMethods
    ...
    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Friend Shared Function SendMessage(hWnd As IntPtr, msg As Integer,
                                       wParam As Integer,
                                       <MarshalAs(UnmanagedType.LPWStr)> lParam As String) As Int32
    End Function

    Private Const EM_SETCUEBANNER As Integer = &H1501
    Private Const CB_SETCUEBANNER As Int32 = &H1703

    Friend Shared Sub SetCueText(ctl As Control, text As String)

        If TypeOf ctl Is ComboBox Then
            SendMessage(ctl.Handle, CB_SETCUEBANNER, 0, text)
        Else
            SendMessage(ctl.Handle, EM_SETCUEBANNER, 0, text)
        End If

    End Sub

End Class

您还可以创建一个从TextBox继承并在那里实现的控件(覆盖NativeMethods.SetCueText(tbPInvWM, "Enter text...") NativeMethods.SetCueText(ComboBox1, "Select...") )。这将允许Cue Text在设计时显示,但代码更少。

最后,使用内部控件有一种更简单的方法:

  • 使用OnHandleCreated而不是Panel。您可以使用标签的LabelFontTextAlignForeColor属性作为您公开的属性的支持字段。 Text设置也可以进行镜像。
  • 要使Watermark / Cue文本/标签根据需要消失,只需将其设置为不可见
  • 即可

这将消除与处理和绘制文本相关的所有问题

RightToLeft

通过使标签可见或不可见来处理提示文本显示:

Public Class TextBoxEx
    Inherits TextBox

    Private WaterCtrl As Label

    ...
    ' Example of using label props as the backing field:
   <Category("Watermark Attributes"),
     Description("Sets Watermark Text"),
     DefaultValue("Watermark Text")>
        Public Property WatermarkText As String
        Get
            If WaterCtrl IsNot Nothing Then
                Return WaterCtrl.Text
            Else
                Return ""
            End If
        End Get
        Set(value As String)
            If WaterCtrl IsNot Nothing Then
                WaterCtrl.Text = value
            End If
        End Set
    End Property

这不是所有的代码,但它应该给你一个开始,它既简单又行为更像本机版本。

答案 1 :(得分:1)

每次绘制水印时都会设置水印的位置。您只需检查TextBox的属性并确定放置水印的位置(但是在设置水印的大小后必须这样做)。

您还必须将水印的宽度设置为实际水印文本的宽度,否则您将无法进行任何对齐。

<input id="col_11" onclick="do_something()">
相关问题