水印文本框对齐中心 [英] watermark Text-box Align Center

查看:117
本文介绍了水印文本框对齐中心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用自定义控件水印文本框,它很完美,但是问题是我无法将水印文本更改为居中或从右向左对齐。
默认情况下它是从左到右,如何使其居中或从右到左?

I'm using custom control watermark textbox and it's perfect, but the problem is that I can't change the watermark textAlign to center or right to left. By default it's left to right, how can I make it center or right to left?

这是代码:

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


推荐答案

有两点需要注意:


  • 在Windows中已经有一种称为<$ c的机制。 $ c> CueBanner 可以很容易地从表单代码或自定义控件中实现

  • 您的实现与行为不完全相同或与本机实现:

    a)在隐藏 Panel

    b)之前没有视觉提示(TB光标)直到您开始输入文字才消失。这似乎是您想要的,但不是本地人通常的工作方式(正如Visual Vincent在评论中指出的那样,有一个选项。我个人不记得看到它足以向我注册。) >
    c)在本机实现中,提示文本/水印使用与控件相同的字体。只有设置为 DropDownList Combobox 使用斜体(也许您从未注意到)。

  • 您的应用程序在某些地方泄漏非常严重: CreateWatermark 被反复调用,以通过创建新的 Panel 每次,但是您不会处理旧的。请记住:如果您用代码创建控件,还需要处理它,而不是仅仅从控件集合中删除它。

  • Font 对象,尽管这只有在TextBox上的 Font 更改时才重要。

  • There is already a mechanism for this in Windows called a CueBanner which is very easy to implement either from form code or as a custom control
  • Your implementation doesn't quite behave or look the same as the Native implementation:
    a) there is no visual cue (TB Cursor) until you hide the Panel
    b) Your Panel/Cue Text doesn't disappear until you start typing. This seems to be what you want, but it is not how the native one typically works (as Visual Vincent points out in a comment, there is an option for this. I personally cant recall seeing it enough to register with me).
    c) In the native implementation, the Cue Text/Watermark uses the same font as the control. Only a Combobox set to DropDownList uses Italic (maybe you never noticed this).
  • Your app is leaking pretty badly in spots: CreateWatermark gets called repeatedly to redisplay the Watermark/CueText by creating a new Panel each time, but you are not disposing of the old one. Remember: If you create a control in code, you also need to dispose of it rather than just removing it from the controls collection.
  • The same is true for the Font object, although that will only matter if the Font on the TextBox changes.

首先,回答您提出的问题-允许向左,向右,居中对齐。

First, an answer to the question you asked - allowing Left, Right, Center TextAlignment.

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




  • 这使用文本渲染器用于绘制文本,通常对于控件来说是更好的选择(保存 Graphics.DrawString()用于绘制位图和图像)

  • 此版本基于新的 WatermarkTextAlign 属性显示它,以防您允许它与 TextBox 。如果没有,请使用Visual Vincent版本的一部分或组合使用。

    • This uses the TextRenderer for drawing the text which is usually a better choice for controls (save Graphics.DrawString() for drawing to bitmaps and images)
    • This version shows it based on a new WatermarkTextAlign property in case you want to allow it to vary from the TextBox. If not, use parts of Visual Vincent's version or combine them.
    • 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
      

      用法很简单:

      NativeMethods.SetCueText(tbPInvWM, "Enter text...")
      NativeMethods.SetCueText(ComboBox1, "Select...")
      

      您还可以创建一个控件从TextBox继承并在其中实现(覆盖 OnHandleCreated )。

      You can also create a control which inherits from TextBox and implement it there (override OnHandleCreated). This would allow the Cue Text to show at design time as your does, but with much less code.

      最后,在那里是使用内部控件进行操作的更简单方法:

      Finally, there is an easier way to do it with an internal control:


      • 而不是 Panel ,使用 Label 。您可以使用标签的字体 TextAlign ForeColor 文本属性作为您公开的属性的后备字段。 RightToLeft 设置也可以被镜像。

      • 要使水印/提示文本/标签根据需要消失,只需将其设置为不可见

      • Rather than a Panel, use a Label. You can use the label's Font, TextAlign, ForeColor and Text properties as the backing fields for the Properties you expose. The RightToLeft setting could also be mirrored.
      • To make the Watermark/Cue Text/Label disappear as needed, just set it to invisible

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

      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
      

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

      The Cue Text display is handled by making the label visible or not:

      ' when they click on the label, hide and
      ' activate the TB like a regular CueBanner does
      Private Sub LblClick(sender As Object, e As EventArgs)
          WaterCtrl.Visible = False
          Me.Select()
      End Sub
      
      Protected Overrides Sub OnLeave(e As EventArgs)
          MyBase.OnLeave(e)
          WaterCtrl.Visible = (Text.Length = 0)
      End Sub
      

      不是全部代码,但它应该为您提供了一个开始,它既简单,又更像本机版本。

      Thats not all the code, but it should give you a start and it's both simpler and acts more like the native version.

      这篇关于水印文本框对齐中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆