在转换为库 .DLL 时,如何阻止 MyLabel.Text 中带有嵌入式 vbCrLf 的字符串添加空行
How do I stop Strings with an ebedded vbCrLf placed in MyLabel.Text from adding a blank line when converted to a library .DLL
我为 VB 的 MsgBox 写了一个替代品来获得对屏幕位置的控制。在 Visual Studio 环境中,它完全符合我的要求。我将其转换为 class 库,但嵌入 vbCrLf 字符的字符串会添加一个空行并丢失插入行中的五个空格以进行缩进。
我试过将 MyLabel 的宽度加倍。表单变宽了,因为它基于 MyLabel.Width 但额外的行仍然存在。我的文本行和标签构建如下:
'split the string on vbCrLf with some leading spaces on each line to indent the message
strLineArr = strMsg.Split(vbCrLf)
Dim intMaxLength As Integer = 0
Dim intIndex As Int16 = 0
Dim ctrLine As Int16 = 0
strMsg = vbCrLf & vbCrLf 'put some space at the top
For i = 0 To strLineArr.Length - 1
If strLineArr(i).Length > intMaxLength Then
intMaxLength = strLineArr(i).Length 'width of label is based on longest line
intIndex = i 'keep tack of which line
End If
strMsg = strMsg & Space(5) & strLineArr(i) & vbCrLf 'add five leading space for an indent
ctrLine += 1 'line counter for the height of the label
Next
'set up the label and message
Dim lblMsg As New Label()
lblMsg.Font = New Drawing.Font("Arial", 10, FontStyle.Regular)
lblMsg.Text = strLineArr(intIndex) & "cccccccccc" 'longest line; add 10 'c' spaces for margin
Dim g As Graphics = lblMsg.CreateGraphics()
lblMsg.Width = CInt(g.MeasureString(lblMsg.Text, lblMsg.Font).Width)
lblMsg.Height = CInt(g.MeasureString(lblMsg.Text, lblMsg.Font).Height) * (ctrLine + 3)
lblMsg.Text = strMsg
使用字符串 "Short Message" & vbCrLf & "Second row":
左边是代码在Visual Studio环境下运行时;右侧是从 .dll.
中执行的相同代码
如有任何想法,我们将不胜感激。
这不是您提出的问题的答案,但它需要一些代码,所以我不想 post 它作为评论。这基本上是一种不同的做事方式,因此您当前的问题应该变得没有实际意义。
在一个新的 WinForms 项目中,我添加了一个名为 MessageForm
的新表单,并向其中添加了一个 Label
。我没有更改 Label
的任何属性,这意味着 AutoSize
是 True
而 Location
是 {0,0}。然后我添加了以下代码:
Public Class MessageForm
Public Sub New(message As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Label1.Text = message
End Sub
Private Sub MessageForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ClientSize = Label1.Size
End Sub
End Class
我在启动表单中添加了 TextBox
和 Button
,并在 TextBox
上将 MultiLine
设置为 True
。然后我添加了以下代码:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Call New MessageForm(TextBox1.Text).ShowDialog()
End Sub
End Class
当我 运行 我的项目时,我能够在 TextBox
中键入任何文本,单击 Button
并让该文本完全按照您希望的方式显示在新表单中预计。您显然会进行某些调整以使表单看起来更好,但我不明白为什么您不能实施相同的原则。如果您希望 space 在顶部,则不要在文本中放置换行符。只需在 Label
顶部和表单顶部之间留一些 space 即可。等等
我想我看到了一个可能的罪魁祸首。这是一个完美的例子,说明为什么你应该总是 Option Strict On
。这一行:
strLineArr = strMsg.Split(vbCrLf)
正在尝试调用不存在的方法。 vbCrLf
是一个 String
并且 Split
方法没有像这样接受 String
参数的重载。如果你有 Option Strict On
,编译器会通知你这个事实并拒绝构建项目,直到你修复它。使用 Option Strict Off
,编译器可以最好地猜测您想做什么。
它决定的是您实际上想要调用接受 ParamArray
个 Char
值的重载。为此,它只使用 String
的第一个字符并丢弃其余字符。这意味着您仅在回车符 return 字符上拆分,并且除了您创建的第一个子字符串之外,所有子字符串的第一个字符都有错误的换行符。
您稍后尝试通过在子字符串之间插入换行符来重建原始文本,这意味着您实际上以一个回车符 return 和每对子字符串之间的两个换行符结束。我不知道为什么根据代码的位置结果会有所不同,但是代码是错误的,无论它在哪里获得预期的结果只是一个快乐的意外。
基本上,您的代码很糟糕。抱歉,事情就是这样。试图通过在每一行中添加前导空格来控制位置是非常糟糕的。您应该使用 Label
来显示文本并让控件的位置提供距窗体边缘的间距,或者使用 GDI+ 将所有文本准确地绘制在您想要的位置。你正在做的是一个肮脏的黑客行为,你应该停止它。
如果你真的必须继续做你正在做的事情,在换行符上拆分 String
的正确方法是使用不同的 String.Split
重载,它实际上接受 String
分隔符而不是 Char
分隔符。首先在本项目的属性页面设置Option Strict On
,在IDE选项中设置On
,以后的项目默认为On
。如果您在其他地方使用后期绑定或隐式转换,您可能必须修复其他错误。现在,如果您确实知道 String
将始终具有当前平台的默认换行符,请执行以下操作:
strLineArr = strMsg.Split({Environment.NewLine}, StringSplitOptions.None)
如果您不知道换行符是 Windows (CR-LF) 还是 UNIX (LF),那么您可以这样做:
strLineArr = strMsg.Split({ControlChars.CrLf, ControlChars.Lf}, StringSplitOptions.None)
后者会优先将两个字符拆分在一起,但也会在单独的换行符上拆分。
如果你真的想重建原文但每行前有 5 个空格,我建议如下:
Dim spaces = New String(" "c, 5)
strMsg = spaces & String.Join(Environment.NewLine & spaces, strLineArr)
我为 VB 的 MsgBox 写了一个替代品来获得对屏幕位置的控制。在 Visual Studio 环境中,它完全符合我的要求。我将其转换为 class 库,但嵌入 vbCrLf 字符的字符串会添加一个空行并丢失插入行中的五个空格以进行缩进。
我试过将 MyLabel 的宽度加倍。表单变宽了,因为它基于 MyLabel.Width 但额外的行仍然存在。我的文本行和标签构建如下:
'split the string on vbCrLf with some leading spaces on each line to indent the message
strLineArr = strMsg.Split(vbCrLf)
Dim intMaxLength As Integer = 0
Dim intIndex As Int16 = 0
Dim ctrLine As Int16 = 0
strMsg = vbCrLf & vbCrLf 'put some space at the top
For i = 0 To strLineArr.Length - 1
If strLineArr(i).Length > intMaxLength Then
intMaxLength = strLineArr(i).Length 'width of label is based on longest line
intIndex = i 'keep tack of which line
End If
strMsg = strMsg & Space(5) & strLineArr(i) & vbCrLf 'add five leading space for an indent
ctrLine += 1 'line counter for the height of the label
Next
'set up the label and message
Dim lblMsg As New Label()
lblMsg.Font = New Drawing.Font("Arial", 10, FontStyle.Regular)
lblMsg.Text = strLineArr(intIndex) & "cccccccccc" 'longest line; add 10 'c' spaces for margin
Dim g As Graphics = lblMsg.CreateGraphics()
lblMsg.Width = CInt(g.MeasureString(lblMsg.Text, lblMsg.Font).Width)
lblMsg.Height = CInt(g.MeasureString(lblMsg.Text, lblMsg.Font).Height) * (ctrLine + 3)
lblMsg.Text = strMsg
使用字符串 "Short Message" & vbCrLf & "Second row":
左边是代码在Visual Studio环境下运行时;右侧是从 .dll.
中执行的相同代码如有任何想法,我们将不胜感激。
这不是您提出的问题的答案,但它需要一些代码,所以我不想 post 它作为评论。这基本上是一种不同的做事方式,因此您当前的问题应该变得没有实际意义。
在一个新的 WinForms 项目中,我添加了一个名为 MessageForm
的新表单,并向其中添加了一个 Label
。我没有更改 Label
的任何属性,这意味着 AutoSize
是 True
而 Location
是 {0,0}。然后我添加了以下代码:
Public Class MessageForm
Public Sub New(message As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Label1.Text = message
End Sub
Private Sub MessageForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ClientSize = Label1.Size
End Sub
End Class
我在启动表单中添加了 TextBox
和 Button
,并在 TextBox
上将 MultiLine
设置为 True
。然后我添加了以下代码:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Call New MessageForm(TextBox1.Text).ShowDialog()
End Sub
End Class
当我 运行 我的项目时,我能够在 TextBox
中键入任何文本,单击 Button
并让该文本完全按照您希望的方式显示在新表单中预计。您显然会进行某些调整以使表单看起来更好,但我不明白为什么您不能实施相同的原则。如果您希望 space 在顶部,则不要在文本中放置换行符。只需在 Label
顶部和表单顶部之间留一些 space 即可。等等
我想我看到了一个可能的罪魁祸首。这是一个完美的例子,说明为什么你应该总是 Option Strict On
。这一行:
strLineArr = strMsg.Split(vbCrLf)
正在尝试调用不存在的方法。 vbCrLf
是一个 String
并且 Split
方法没有像这样接受 String
参数的重载。如果你有 Option Strict On
,编译器会通知你这个事实并拒绝构建项目,直到你修复它。使用 Option Strict Off
,编译器可以最好地猜测您想做什么。
它决定的是您实际上想要调用接受 ParamArray
个 Char
值的重载。为此,它只使用 String
的第一个字符并丢弃其余字符。这意味着您仅在回车符 return 字符上拆分,并且除了您创建的第一个子字符串之外,所有子字符串的第一个字符都有错误的换行符。
您稍后尝试通过在子字符串之间插入换行符来重建原始文本,这意味着您实际上以一个回车符 return 和每对子字符串之间的两个换行符结束。我不知道为什么根据代码的位置结果会有所不同,但是代码是错误的,无论它在哪里获得预期的结果只是一个快乐的意外。
基本上,您的代码很糟糕。抱歉,事情就是这样。试图通过在每一行中添加前导空格来控制位置是非常糟糕的。您应该使用 Label
来显示文本并让控件的位置提供距窗体边缘的间距,或者使用 GDI+ 将所有文本准确地绘制在您想要的位置。你正在做的是一个肮脏的黑客行为,你应该停止它。
如果你真的必须继续做你正在做的事情,在换行符上拆分 String
的正确方法是使用不同的 String.Split
重载,它实际上接受 String
分隔符而不是 Char
分隔符。首先在本项目的属性页面设置Option Strict On
,在IDE选项中设置On
,以后的项目默认为On
。如果您在其他地方使用后期绑定或隐式转换,您可能必须修复其他错误。现在,如果您确实知道 String
将始终具有当前平台的默认换行符,请执行以下操作:
strLineArr = strMsg.Split({Environment.NewLine}, StringSplitOptions.None)
如果您不知道换行符是 Windows (CR-LF) 还是 UNIX (LF),那么您可以这样做:
strLineArr = strMsg.Split({ControlChars.CrLf, ControlChars.Lf}, StringSplitOptions.None)
后者会优先将两个字符拆分在一起,但也会在单独的换行符上拆分。
如果你真的想重建原文但每行前有 5 个空格,我建议如下:
Dim spaces = New String(" "c, 5)
strMsg = spaces & String.Join(Environment.NewLine & spaces, strLineArr)