自定义水印文本框表现奇怪(Custom Watermarked Textbox behaving strangely)

编程入门 行业动态 更新时间:2024-10-28 05:15:53
自定义水印文本框表现奇怪(Custom Watermarked Textbox behaving strangely)

解:

感谢下面的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

我正在构建一个自助服务终端应用程序,为了保持美观,我决定实现一个带水印的文本框作为输入字段。 我在CodeProject上找到了这个项目 ,将其转换为VB.NET并将其放入我的应用程序中。 它起作用,因为它水印并清除它们就好了,但是当我去输入文本时会发生这种情况:

空:

填充:

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

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事件中使用我设置的字体大小,但没有运气。 还有其他一些我想念的东西让它变得比它应该更难吗?

谢谢!

SOLUTION:

Thanks to Patrick below, I have refactored the C# CodeProject version into a VB.NET version that works for me. Hopefully it can help you guys as well:

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

I am building a kiosk application, and in order to keep it aesthetically pleasing I decided to implement a watermarked textbox as the entry fields. I found this project on CodeProject, converted it over to VB.NET and put it into my application. It works, in the sense that it watermarks and clears them just fine, but when I go to enter text this happens:

Empty:

Filled:

So basically it is not clearing the whole watermark, just the space appropriated for the default height of a textbox. here is the converted code:

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

I attempted to force the class to use my set font size in the OnPaint event, but no luck with that. Is there something else that I am missing that is making this more difficult than it should be?

Thanks!

最满意答案

你只是在DisableWaterMark子的末尾错过了一个Refresh:

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

You're just missing a Refresh at the end of the DisableWaterMark 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 Refresh() End Sub

EDIT:

Rather than using the UserPaint control style, you can handle the WM_PAINT message in WndProc, and only print the watermark if the text is empty. The result is basically the same though.

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

更多推荐

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

发布评论

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

>www.elefans.com

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