水印文本框对齐中心 [英] watermark Text-box Align Center
问题描述
我正在使用自定义控件水印文本框
,它很完美,但是问题是我无法将水印文本更改为居中或从右向左对齐。
默认情况下它是从左到右,如何使其居中或从右到左?
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 $ c重新显示Watermark / CueText。 $ c>每次,但是您不会处理旧的。请记住:如果您用代码创建控件,还需要处理它,而不是仅仅从控件集合中删除它。
-
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 thePanel
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 aCombobox
set toDropDownList
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 newPanel
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 theFont
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 (saveGraphics.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 theTextBox
. 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 aLabel
. You can use the label'sFont
,TextAlign
,ForeColor
andText
properties as the backing fields for the Properties you expose. TheRightToLeft
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屋!