Функция Msgbox - не влезает большой текст

Автор Tigrik, 15 июня 2020, 19:06

0 Пользователи и 1 гость просматривают эту тему.

Tigrik

Здравствуйте!

Если эта тема уже где-то обсуждалась, "ткните", пожалуйста.
Очень даже возможно, что некоторые мои вопросы совсем "детские", но, даже, казалось бы очень простая и понятная функция Msgbox, вызвала у меня вопросы.
Понятно, что в этой функции как-то не разумно выводить монографии, поэтому и должны быть ограничения на размер сообщения (наверное?). В руководстве не было ничего об максимальном размере сообщения, при котором ещё можно полноценно пользоваться этой функцией. 49 строк по 55 символов ещё позволяют увидеть самый краешек кнопки, в всяком случае, у меня так получилось. Следующая строка уже полностью "вытесняет" кнопку.
Небольшой код для иллюстрации:

Sub TestMsgbox()
Msgbox String(55*49, "A") '   Можно заметить краешек кнопки
Msgbox String(55*49+1, "A") '   Теперь, кнопку уже не видно
End Sub


Или я что-то не так и не то делаю?

kompilainenn

Цитата: Tigrik от 15 июня 2020, 19:06Или я что-то не так и не то делаю?
используете не по назначению, как по мне
Поддержать разработчиков LibreOffice можно тут, а наш форум вот тут

economist

#2
1) Длинные строки можно сократить, вставить переносы строк +CHR(10)+ - и влезет 500+ символов.

2) Можно использовать "свой" MessageBox, с форматированием, мелким шрифтом итд: https://ask.libreoffice.org/en/question/134656/how-to-change-color-or-font-for-some-part-of-the-text-in-the-msgbox/

3) Если нужно что-то большое пошаговое и с кнопками - можно сразу выбрать Python - язык без ограничений.  Его простые GUI-библиотеки типа TKinter и десятки других (https://techrocks.ru/2018/04/26/13-python-gui-frameworks/)
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

Tigrik

#3
economist, спасибо за ответ.

Мне и не нужно было использовать Msgbox с таким большим текстом. Конечно, если понадобится, я что-нибудь придумаю - уже есть "заготовка".
Хотя, как по мне, основное предназначение функции для вывода текста - это выводить текст на монитор, если есть в этом ограничения, то не плохо бы об этом "проинформировать".

Просто, я, немного, "эксперементировал" с этой функцией и заметил, что максимальное количество строк, когда ещё сохранена функциональность этой процедуры - это 48 строк.
Максимальное количество строк, которые можно увидеть - это 52, каждая строка 55 символов, то есть максимум символов 2860, которые будут видны на мониторе, а остальная часть пропадет.
У функции есть код ошибки - неправильный вызов процедуры, а о том, что не все строки сообщения будут видны - не сообщается.

---------
До "Питона" я ещё, пока, не добрался.

mikekaganski

Цитата: Tigrik от 16 июня 2020, 12:45Хотя, как по мне, основное предназначение функции для вывода текста - это выводить текст на монитор, если есть в этом ограничения, то не плохо бы об этом "проинформировать".

Вы, честно говоря, предлагаете какую-то ерунду.

"Вот функция, которая показывает сообщение (то есть предназначена для короткого текста). Если текста слишком много, так что он не влезет на ваш монитор (на Вашей оси, с Вашим разрешением, в Вашим системным шрифтом), то его слишком много, и он не влезет на ваш монитор".

В принципе справка предполагает некий элементарный уровень соображения у человека, пользующегося программой, тем более для программирования. Да и пример Ваш из начального поста, скажм, на моей системе даёт оба раза нормальный результат - у меня влезает гораздо больше.
С уважением,
Михаил Каганский

Tigrik

Михаил, я никого не собирался обидеть.
Тем более, не собираюсь спорить, советовать и учить профессиональных программистов и опытных пользователей, так как сам "без году неделя", как осваиваю макросы.
Я поделился некой информацией, которая, во всяком случае, на тот момент, показалась мне достойной внимания и поделился о ней на форуме.
Судя по реакции, эта информация только мне показалась достойная внимания, поэтому, скорее всего, обсуждение этого вопроса завершено.

---
Михаил, Вы упомянули про системный шрифт - информацию о нём где лучше взять - в объекте Windows (oWindow = CreateUnoService("com.sun.star.awt.Toolkit")? А какой параметр?
Если эти вопросы стОят более развернутого обсуждения или ответов (возможно, это где-то обсуждалось (не нашёл) или не будет интересно, что бы отвечать), тогда можно открыть новую тему.

Спасибо.

mikekaganski

Цитата: Tigrik от 16 июня 2020, 14:21
Михаил, Вы упомянули про системный шрифт - информацию о нём где лучше взять - в объекте Windows (oWindow = CreateUnoService("com.sun.star.awt.Toolkit")? А какой параметр?

Возможно, с помощью

CreateUnoService("com.sun.star.awt.Toolkit").ActiveTopWindow.StyleSettings.ApplicationFont
С уважением,
Михаил Каганский

Tigrik

Цитата: mikekaganski от 16 июня 2020, 14:45
Цитата: Tigrik от 16 июня 2020, 14:21
Михаил, Вы упомянули про системный шрифт - информацию о нём где лучше взять - в объекте Windows (oWindow = CreateUnoService("com.sun.star.awt.Toolkit")? А какой параметр?
Возможно, с помощью
CreateUnoService("com.sun.star.awt.Toolkit").ActiveTopWindow.StyleSettings.ApplicationFont
Спасибо.


Tigrik

Рискну задать следующие свои вопросы в этой теме, так как он, как и предыдущий, имеет отношение к моему макросу, который некоторый "аналог" обсуждаемой процедуре.

Посоветуйте, пожалуйста, что бы не уплыть на "глубину".

Программно создаются строки текста, которые будут использоваться к различным элементам управления конкретного Диалога (программируемого). И в этом диалоге не будут меняться шрифты - останутся какие есть по умолчанию.
Для определения размеров и координат высчитывается некоторые характеристики текста (сколько строк, длина строк). Для правильного подсчета этих величин, как мне думается, нужно узнать шрифт в диалоге (правильно ли это, что это и есть шрифт, в данный момент, на системе?) и, соответственно этому шрифту, размеры строки по высоте и примерный размер символа по ширине.
Для шрифта с кеглем 8 пунктов (1 пункт = 0.359 мм) получается высота 2,87мм. А размеры окна диалога в каких единицах измерения? Сейчас, я для своих расчётов беру 6 по высоте и 4 по ширине.

Если резюмировать, то у меня два вопроса.
1. Как однозначно узнать шрифт, который по умолчанию установлен для окна диалогов?
По подсказке Михаила:

Dim aFontDecs As New "com.sun.star.awt.FontDescriptor"
aFontDecs = CreateUnoService("com.sun.star.awt.Toolkit").ActiveTopWindow.StyleSettings.ApplicationFont
hFont = aFontDecs.Height

Этого будет достаточно?

2. Как от этого параметра узнать высоту строки и ширину символа (хотя бы приблизительно)?

Спасибо.

rami

Используйте моноширинный шрифт, будет проще подгонять размеры.

Tigrik

#10
Цитата: rami от 16 июня 2020, 21:44
Используйте моноширинный шрифт, будет проще подгонять размеры.
А как это сделать?
Задать в модели диалога соответствующий шрифт?
А как со шрифтом связать размеры?

---
Используя это:
aFontDecs = CreateUnoService("com.sun.star.awt.Toolkit").ActiveTopWindow.StyleSettings.ApplicationFont
задать соответствующий шрифт?

---
Посмотрел, вроде бы, DejaVu Sans Mono и Prestige Elite неплохо выглядят.

rami

Обычно размеры точно под текст не подгоняют, делают размеры с запасом.


Давайте образец диалога со всеми потрохами.

Tigrik

Цитата: rami от 16 июня 2020, 22:29
Обычно размеры точно под текст не подгоняют, делают размеры с запасом.


Давайте образец диалога со всеми потрохами.

Да, конечно, я так и буду делать с запасом.
Когда "соберу" в удобной, для показа, "упаковке", выложу на форум.

Tigrik

Цитата: Tigrik от 16 июня 2020, 22:34
Цитата: rami от 16 июня 2020, 22:29
Обычно размеры точно под текст не подгоняют, делают размеры с запасом.

Давайте образец диалога со всеми потрохами.
Да, конечно, я так и буду делать с запасом.
Когда "соберу" в удобной, для показа, "упаковке", выложу на форум.
В моём макросе нужен был небольшой диалог, где будет только текст и три кнопки со своими событиями. Msgbox - хорошая функция (даже есть четыре кнопки), но нужны были свои надписи на кнопках.
Даже программно такой диалог не долго "строится", но появилась идея сделать универсальный макрос (мне нравится делать универсальные программы).
На входе будет один обязательный параметр - массив текстов для кнопок и два необязательных параметров: заголовок для диалога и строка текста сообщения.
Предлагаю на всеобщее обозрение самый простой вариант этого макроса (надо немного оптимизировать расчеты и убрать лишние параметры - после того, когда макрос будет полностью готов, цвет тоже можно убрать - нужен только, что бы видеть поле текста). Может быть, кому-нибудь пригодится и такой вариант или на основе этого сделать что-то своё.
Другой вариант, чуть посложнее - уже тестируется анализ текстов для сообщения и на кнопках - длинные строки или даже слова разбивать на подстроки.
В основной процедуре закомментированы вводные параметры для отладки - они должны вызывать разные ошибки.

REM  *****  BASIC  *****
Dim oDlg 'Объект Диалог
Sub Start_Dlg_MsgButton()
  Dim aTextButtom(), strDlgTitle$, strDlgMess$, onRezult%
aTextButtom() = Array("ДА", "НЕТ", "Надо подумать!!!")
strDlgTitle = "Окно Диалога с кнопками"
strDlgMess = "Текст сообщения может быть длинным!"  & chr(10) & "А нужно выбрать одну кнопку."
' aTextButtom() = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15") '  Большое кол-во кнопок
' aTextButtom() = Array("ДА", "НЕТ", String(56+1, "A")) '   Большой текст на Кнопке для проверки ошибки
' strDlgMess = String(180+1, "A") '   Большой текст Сообщения для проверки ошибки
' For onRezult = 1 To 45+1 : strDlgMess = strDlgMess & "A" & chr(10) : Next '   Большое кол-во строк Сообщения
' onRezult = Dlg_MsgButton_Light(Array("Запустить какую-то программу", "Взять какие-то данные", "Что-нибудь ещё")) '   Только кнопки
onRezult = Dlg_MsgButton_Light(aTextButtom(), strDlgTitle, strDlgMess)
Select Case onRezult
Case -2 : Msgbox "Большое количество кнопок!", 0, "Ошибка!"
Case -1 : Msgbox "Очень большой текст!", 0, "Ошибка!"
Case 0 : Msgbox "Выход без кнопки!"
Case Else : Msgbox ("Нажата кнопка № " & onRezult)
End Select
End Sub


Sub Dlg_MsgButton_Light(aTextButton(), Optional strDlgTitle$, Optional strDlgMess$) As Integer
  Dim oDlgModel, oModel, oListener, DlgRez
  Dim SizeDlg(1 To 2) As Long '   Размер Окна Диалога
  Dim strFullText$(1), aText(), sTextMesNew, i&, j&, varTemp, strTemp
  Dim DeltaXY& '   Отступ в Окне Диалога
  Dim aTxProp(1, 7) '   0 - Кол-во кнопок (только для 2-го массива); 1 - Кол-во строк; 2 - Макс.длина строки;
' 3 - Ширина; 4 - Высота; 5 - Расст. по X; 6 - Расст. по Y; 7 - всего символов на кнопках (актуально для 2-го массива) или в сообщении
Dim oWindow, ATWSize
oWindow = CreateUnoService("com.sun.star.awt.Toolkit")
ATWSize = oWindow.ActiveTopWindow.Size '   Размеры Окна Windows в пикселях
oDlgModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
oDlgModel.setPropertyValue("Title", strDlgTitle)
'///////////////////////////////////////////
' Попытка поменять шрифт
Dim aFontDecs
Dim sNameFontDlg$
sNameFontDlg = "DejaVu Sans Mono"
aFontDecs = oDlgModel.FontDescriptor
aFontDecs.Name = sNameFontDlg
aFontDecs.Height = 10 : aFontDecs.Slant = 2 : aFontDecs.Weight = 200 : aFontDecs.Kerning = True
oDlgModel.FontDescriptor = aFontDecs
'///////////////////////////////////////////
oDlg = CreateUnoService("com.sun.star.awt.UnoControlDialog")
oDlg.setModel(oDlgModel)
oDlg.createPeer(oWindow, null)
'///////////////////////////////////////////
Dim xD&, yD&, wD&, hD& '   Координаты (X и Y) и размеры (ширина и высота) Окна Диалога
Dim indXY& '   Расстояние (по X и Y) от границы Экрана Монитора до Окна Диалога
Dim maxXD&, maxYD& '   Максимальные размеры Окна Диалога
Dim hStBut& '   Высота одно-строчной кнопки
Dim minCharButt, maxButt% '   Мин. кол-во символов для кнопки и макс. кол-во кнопок
Dim wChar!, hChar! '   Ширина и Высота Символа
Dim maxCharX%(1), maxCharY%(1) '   Макс.кол-во символов в строке и макс.кол-во строк в Сообщении и на Кнопке
Dim ConvSize, wCWin%, hCWin% '   Размеры (ширина и высота) Окна Windows после Конвертации от Размеров Монитора в пикселях
   ConvSize = oDlg.convertSizeToLogic(ATWSize, 18)
wCWin = ConvSize.Width : hCWin = ConvSize.Height
DeltaXY = 12 : indXY = 24
wChar = 5 : hChar = 8 : hStBut = 3 * hChar / 2
maxXD = wCWin - indXY * 2 : maxYD = hCWin - indXY * 2
maxCharX(0) = maxXD / wChar : maxCharY(0) = (maxYD - DeltaXY - hStBut) / hChar  ' Пока, ориентировочные формулы
maxCharX(1) = (maxXD - (UBound(aTextButton()) + 2) * DeltaXY) / (UBound(aTextButton()) + 1) / wChar : maxCharY(1) = 1
minCharButt = 8 : maxButt = (maxXD - DeltaXY) / (DeltaXY + minCharButt * wChar)
'///////////////////////////////////////////
If IsMissing(strDlgTitle) Then strDlgTitle = ""
If IsMissing(strDlgMess) Then strDlgMess = "" Else strDlgMess = Join(Split(strDlgMess, chr(13)), chr(10))
If UBound(aTextButton()) + 1 > maxButt Then Dlg_MsgButton_Light=-2 : Exit Sub 'Ошибка - превышено кол-во кнопок
REM   =========   По максимальной длине строки (сообщения или текстов кнопок) вычисляются ширины (текста или кнопок)
Dim nn%
strFullText(0) = strDlgMess : strFullText(1) = Join(aTextButton(), chr(10))
For i = 0 To 1
aText() = Split(Trim(strFullText( i )), chr(10))
nn = UBound(aText())
If i = 0 Then If nn+1 > maxCharY(0) Then Dlg_MsgButton_Light=-1 : Exit Sub 'Ошибка - превышена длина строк (в сообщении или на кнопке)
aTxProp(i, ((i+1) Mod 2)) = nn + 1 '   Кол-во Строк для Сообщения или кол-во Кнопок
For j = LBound(aText()) To nn
  strTemp = Trim(aText( j )) : aText( j ) = strTemp : varTemp = Len(strTemp)
If varTemp > maxCharX( i ) Then Dlg_MsgButton_Light=-1 : Exit Sub'Ошибка - превышено кол-во символов в строке (в сообщ-ии, на кнопке)
'aTxProp(i, 7) = aTxProp(i, 7) + varTemp '   Всего кол-во символов: в Сообщении или на Кнопках == пока не используется
     aTxProp(i, 2) = IIf(aTxProp(i, 2) < varTemp, varTemp, aTxProp(i, 2))' Макс. длина строки в строках Сообщения или на Кнопках
Next
If i = 0 Then sTextMesNew = Join(aText(), chr(10)) Else aTextButtonNew() = Split(Join(aText(), chr(10)), chr(10))
Next
REM   =========   Координаты и размеры текста, кнопок, окна диалога
aTxProp(0, 1) = UBound(Split(sTextMesNew, chr(10))) + 1 '   0, 1 - кол-во Строк Сообщения
aTxProp(1, 0) = UBound(aTextButtonNew()) + 1 '   1, 0 - кол-во Кнопок
  aTxProp(1, 1) = 1 '   Пусть, пока, будет одна строка текста на кнопке
aTxProp(0, 4) = (aTxProp(0, 1)) * (hChar) : aTxProp(1, 4) = (aTxProp(1, 1)) * hChar + hChar/2 ' Высота Текста Сообщ-я и Высота Кнопки
aTxProp(0, 3) = aTxProp(0, 2) * wChar      : aTxProp(1, 3) = aTxProp(1, 2) * wChar ' Ширина Текста Сообщения и Ширина Кнопки
SizeDlg( 2 ) = aTxProp(0, 4) + aTxProp(1, 4) + DeltaXY    '   2 - Высота Диалога
'   Если текст шире, чем все кнопки
If (aTxProp(1, 3) * aTxProp(1, 0) + DeltaXY * (aTxProp(1, 0) - 1)) < aTxProp(0, 3) Then
aTxProp(0, 5) = DeltaXY '   0, 5 - расст. до текста = DeltaX (по оси X)
SizeDlg( 1 ) = aTxProp(0, 5) * 2 + aTxProp(0, 3) '   1 - Ширина Диалога
aTxProp(1, 5) = (SizeDlg( 1 ) - aTxProp(1, 3) * aTxProp(1, 0)) / (aTxProp(1, 0) + 1) '1, 5 - расстояние до Кнопки (по оси X)
Else
aTxProp(1, 5) = DeltaXY '   1, 5 - расст. до кнопки = DeltaX (по оси X)
SizeDlg( 1 ) = aTxProp(1, 3) * aTxProp(1, 0) + DeltaXY * (aTxProp(1, 0) + 1) '   1 - Ширина Диалога
aTxProp(0, 5) = (SizeDlg( 1 ) - aTxProp(0, 3)) / 2 '   0, 5 - расстояние до Текста (по оси X)
EndIf
aTxProp(0, 6) = 0 '   0, 6 - расст. до Текста (по оси Y)
varTemp = (SizeDlg( 2 ) - (aTxProp(0, 6) + aTxProp(0, 4) + aTxProp(1, 4))) / 2
aTxProp(1, 6) = aTxProp(0, 6) + aTxProp(0, 4) + varTemp '   1, 6 - расст. до Кнопки (по оси Y)
REM   =========   Координаты и Размеры Окна Диалога
xD = (wCWin - SizeDlg( 1 )) / 2 : yD = (hCWin - SizeDlg( 2 )) / 2
wD = SizeDlg( 1 ) : hD = SizeDlg( 2 )
oDlgModel.setPropertyValue("PositionX", Clng(xD)) : oDlgModel.setPropertyValue("PositionY", Clng(yD))
oDlgModel.setPropertyValue("Width", wD) : oDlgModel.setPropertyValue("Height", hD)
REM   =========   Установить модель элемента управления (текстовой сообщение) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlFixedTextModel")
oModel.setPropertyValues( Array("PositionX", "PositionY", "Width", "Height", "Label", "Align", "VerticalAlign", "BackgroundColor"), _
Array(Clng(aTxProp(0, 5)), Clng(aTxProp(0, 6)), Clng(aTxProp(0, 3)), Clng(aTxProp(0, 4)), sTextMesNew, 1, 1, &HFFFF00 ) )
oDlgModel.insertByName("TextMessage",oModel)
oListener = CreateUnoListener("Button_", "com.sun.star.awt.XActionListener") '  Установить Обработчик Событий (для кнопки)
REM   =========   Задать свойства элемента управления (кнопки) в Модель Диалога
  For i = 1 To aTxProp(1, 0)
varTemp = Clng(aTxProp(1, 5)  * i + aTxProp(1, 3) * ( i - 1 )) : strTemp = aTextButtonNew( i - 1)
my_createInsertControl(oDlgModel, Array("Type", "com.sun.star.awt.UnoControlButtonModel", "Name", "ComButton" + i, _
"Label", strTemp, "BackgroundColor", &HFFA500, _
"PositionX", varTemp, "PositionY", aTxProp(1, 6), "Width", aTxProp(1, 3), "Height", aTxProp(1, 4), "TabIndex", i,  _
"Align", 1, "VerticalAlign", 1, "Tabstop", True, "PushButtonType", com.sun.star.awt.PushButtonType.STANDARD))
oDlg.getControl("ComButton" & i).addActionListener(oListener)
  Next
Dlg_MsgButton_Light = oDlg.execute()
End Sub


Sub Button_actionPerformed(ActionEvent)
oDlg.endDialog(ActionEvent.Source.Model.TabIndex)
End Sub


Из нерешенного - не получается придать шрифт всей модели диалога и, затем, ещё найти возможность поточнее считать знакоместо (высоту и ширину) для символа (сейчас, эти значения - подобраны эмпирическим методом).

И, конечно, хотелось бы услышать замечания и поправки - ошибки и неточности, наверняка, где-нибудь "притаились".

rami

Цитата: Tigrik от 18 июня 2020, 03:49... но появилась идея сделать универсальный макрос (мне нравится делать универсальные программы).
В данном случае это плохая идея, чтобы написать хорошую универсальную программу нужно сначала написать несколько (желательно много) программ с общим функционалом и какими-нибудь различиями, а затем уже пытаться делать что-то универсальное. Да и исполнение в стиле говнокода, тяжело разбираться с таким кодом. Самое тяжёлое и неоправданное это размещение нескольких строк кода на одной физической строке с помощью двоеточия. А с учётом других "особенностей" кода, лучше не надо...

Старайтесь писать код проще, без "наворотов".