#string #vb.net #dll #label
#строка #vb.net #dll #label
Вопрос:
Я написал замену для MsgBox VB, чтобы получить контроль над расположением экрана. В среде Visual Studio это сделало именно то, что я хотел. Я преобразовал ее в библиотеку классов, но строки со встроенными символами 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 amp; 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 amp; Space(5) amp; strLineArr(i) amp; 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) amp; "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
Используя строку «Короткое сообщение» amp; vbCrLf amp; «Вторая строка»:
Левая сторона — это когда код выполняется в среде Visual Studio; правая сторона — это тот же код, который выполняется из .dll.
Любая мысль по этому поводу будет оценена.
Комментарии:
1. Не могли бы вы просто установить
AutoSize
значениеTrue
on theLabel
, присвоить полноеString
значение егоText
свойству, а затем изменить размер формы на основеSize
of theLabel
?2. @jmcilhinney В случае строки «Короткое сообщение» amp; vbCrLf amp; «Вторая строка» AuoSize имеет значение True, а ширина формы никогда не изменяется по сравнению со значением по умолчанию.
Ответ №1:
Я думаю, что вижу вероятного виновника. Это прекрасный пример того, почему вы ВСЕГДА должны иметь Option Strict On
. Эта строка:
strLineArr = strMsg.Split(vbCrLf)
пытается вызвать метод, которого не существует. vbCrLf
является a String
, и нет перегрузки Split
метода, который принимает подобный String
параметр. Если бы вы это сделали Option Strict On
, компилятор сообщил бы вам об этом факте и отказался создавать проект, пока вы его не исправите. С Option Strict Off
помощью компилятора лучше всего угадать, что вы хотите сделать.
Он решает, что вы действительно хотите вызвать перегрузку, которая принимает a ParamArray
Char
значений. Для этого он просто использует первый ваш символ String
и отбрасывает остальные. Это означает, что вы разделяете только символы возврата каретки, и все созданные вами подстроки, кроме первой, имеют ошибочный перевод строки в качестве первого символа.
Позже вы пытаетесь восстановить исходный текст, вставляя разрывы строк между подстроками, что означает, что вы фактически получаете один возврат каретки и два перевода строки между каждой парой подстрок. Я не знаю, почему результат отличается в зависимости от того, где находится код, но код неверен независимо от того, где он находится получение ожидаемого результата — это просто счастливая случайность.
В принципе, ваш код ужасен. Извините, но так оно и есть. Попытка контролировать позицию, добавляя начальные пробелы в каждую строку, просто ужасна. Вы должны либо использовать a Label
для отображения текста, позволяя позиции элемента управления указывать расстояние от края формы, либо использовать GDI , чтобы нарисовать весь текст именно там, где вы этого хотите. То, что вы делаете, является грязным взломом, и вы должны это остановить.
Если вам действительно нужно продолжать делать то, что вы делаете, правильный способ разделения String
на разрывы строк — это использовать другую перегрузку String.Split
, которая на самом деле принимает String
разделители, а не Char
разделители. Во-первых, установите Option Strict On
его на страницах свойств этого проекта, а также установите On
в параметрах IDE, чтобы он был 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 amp; String.Join(Environment.NewLine amp; spaces, strLineArr)
Комментарии:
1. @CPRouse, если вы создаете
Label
в конструкторе, вы можете позволить линиям привязки создавать интервал для вас. Привязка строк работает на основеPadding
свойства элемента управления. Вы можете установить свойство в окне свойств, а затем перетащить элемент управления, и линии привязки создадут отступ. Я бы предложил создать все элементы управления в конструкторе и скрыть те, которые вам не нужны по требованию в коде. Вы можете создать наRectangle
основе размера и расположения элементов управления, которые вам нужно отобразить, и назначить ихClientSize
форме. Выполнено.2. Еще раз спасибо. Я попробовал опцию Strict, и она не обнаружила vbCrLf в операторах разделения, но я понимаю, что вы говорите. Опция Strict обнаружила дюжину неявных преобразований, которые я могу исправить. Обычно я просто использую Explicit . Я привязывал метку к верхней части формы, устанавливая цвет метки BG на белый и используя пробелы для отступа. Мое намерение состояло в том, чтобы имитировать VB MsgBox, но иметь контроль над расположением и шрифтом. Мое решение казалось простым, и оно работало, по крайней мере, до тех пор, пока я не превратил его в библиотеку. ☺ Я ценю ваши отзывы.
3. @CPRouse, «Я попробовал опцию Strict, и она не обнаружила vbCrLf в операторах разделения» . Я не понимаю, как это могло быть. У меня всегда есть
Option Strict On
в свойствах проекта — не только на уровне файла — и если я напишуString.Empty.Split(vbCrLf)
, то получу «Параметр BC30512, строго запрещающий неявные преобразования из ‘String’ в’Char'» . Вы уверены, что включили его неOn
для проекта, а затемOff
для этого конкретного файла кода?4. У меня есть «Параметр Strict On» в строке 1 исходного файла, и я не получаю эту ошибку. Я изменил строки на: «Dim strSeparator() Как String = {vbCrLf} Dim strLineArr() Как String = strMsg.Split(strSeparator, StringSplitOptions . RemoveEmptyEntries), и это решило проблему.
Ответ №2:
Это не ответ на вопрос, который вы задали, но для этого требуется немного кода, поэтому я не хотел публиковать его в качестве комментария. По сути, это другой способ делать такие вещи, что ваш текущий вопрос должен стать спорным.
В новом проекте WinForms я добавил новую форму с именем MessageForm
и добавил Label
к ней a . Я не менял никаких свойств 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
Я добавил a TextBox
и a Button
в свою стартовую форму и установил MultiLine
значение True
on TextBox
. Затем я добавил следующий код:
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
и отобразить этот текст в новой форме точно так, как вы ожидаете. Вы, очевидно, внесли бы определенные коррективы, чтобы форма выглядела лучше, но я не понимаю, почему вы не можете реализовать тот же принцип. Если вам нужен пробел вверху, то не ставьте разрывы строк в тексте. Просто оставьте немного места между верхом формы Label
и ее верхом. И т.д.
Комментарии:
1. Спасибо, что нашли время ответить на этот вопрос. Форма и компоненты (1-метка; до 3-кнопок создаются динамически и выполняются, как и ожидалось, с помощью тестового кода и функции MyMsgBox, скомпилированных вместе. Это когда я помещаю MyMsgBox в . библиотека dll, в которой возникает проблема. Это то, что заставляет меня чесать голову. Я всего лишь добавляю несколько строк, создаю библиотеку, тестирую ее, промываю и повторяю, пока не найду, в чем проблема
2. @CPRouse, но зачем вообще создавать элементы управления динамически? Почему бы не создать их в конструкторе, а затем просто установить их
Visible
свойства во время выполнения? Я считаю, что ваш код для разделения и перестройки текста является проблемой, и, насколько я могу судить, все это совершенно не нужно. Вы создали проблему, выполнив ненужную работу.3. За исключением цветов и начальной позиции, все меняется (ширина, высота, кнопки) при каждом вызове функции. Разница между использованием конструктора и динамическим созданием диалогового окна, по сути, составляет 5 операторов Dim. Вы были правы в отношении разделения на vbCrLf. В результате оставались переводы строк и вставлялись дополнительные vbCrLf. Как вы, вероятно, догадались, я новичок в . Сетевая среда и любитель, хотя я писал игровой код для Konami в 80-х годах на ассемблере 8088. Моим первым языком был ФОРТРАН в 1972 году в UW-Milwaukee, когда я был младшим школьником.