Как мне остановить строки с вложенным vbCrLf, помещенным в myLabel.Текст от добавления пустой строки при преобразовании в library .DLL

#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 the Label , присвоить полное String значение его Text свойству, а затем изменить размер формы на основе Size of the Label ?

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, когда я был младшим школьником.