Обработчик нажатия клавиши в Диалоге

Автор Tigrik, 14 февраля 2022, 02:08

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

Tigrik

Здравствуйте!
Есть макрос, который запускает Диалог: текстовое поле для ввода небольшого текста, который определенным образом обрабатывается на листе (код в разработке); слева Метка для счётчика шагов; под текстовым полем - Метка для небольшого сообщения после обработки текста; кнопка Остановки Макроса ("Cancel" - по 0 закрывает Диалог).
Именно в этой версии макроса, который предоставлен на рассмотрение, задействована ещё одна кнопка со свойством "OK"(возвращает 1), которая и перезапускает Диалог для следующего шага. Но вместо этой кнопки я хочу попробовать использовать обработку нажатия клавиш, чтобы по нажатию клавиши «ENTER» («RETURN») происходил бы тот же самый перезапуск Диалога (в каждом шаге будет только одно нажатие клавиши «ENTER»).
Вот код этого макроса:

Global oDlg As Object '  Объект Диалог

Sub ProgDialogForum
  Dim oDlgModel, oModel, DlgRez, CountStep%
  Dim oTextEdit, oLabelCountStep, oLabelMess

CountStep = 1
REM Создание модели диалога; самого ДИАЛОГА; установка МОДЕЛЬ ДИАЛОГА в ДИАЛОГ и использовать для Диалога созданное Окно
oDlgModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
oDlgModel.setPropertyValue("Title", "Заголовок")
oDlg = CreateUnoService("com.sun.star.awt.UnoControlDialog")
oDlg.setModel(oDlgModel)
oDlg.createPeer(CreateUnoService("com.sun.star.awt.Toolkit"), null)
REM   =========   Задать свойства Диалога в Модель Диалога
oDlgModel.setPropertyValue("PositionX", 191) : oDlgModel.setPropertyValue("PositionY", 180)
oDlgModel.setPropertyValue("Width", 384) : oDlgModel.setPropertyValue("Height", 84)
REM   =========   Задать свойства элемента управления (Метка - Надпись ---> для счётчика шагов) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlFixedTextModel")
oModel.setPropertyValues( Array("PositionX", "PositionY", "Width", "Height", "Label", "Align", "VerticalAlign", "BackgroundColor"), _
Array(12, 12, 48, 24, cstr(CountStep), 1, 1, RGB(51,255,153) ) )
oDlgModel.insertByName("LabelCountStep",oModel)
oLabelCountStep = oDlgModel.getByName("LabelCountStep")
REM   =========   Задать свойства элемента управления (Метка - Надпись ---> для сообщения) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlFixedTextModel")
oModel.setPropertyValues( Array("PositionX", "PositionY", "Width", "Height", "Label", "Align", "VerticalAlign"), _
Array(12, 48, 360, 24, "проба", 1, 1) )
oDlgModel.insertByName("LabelMess",oModel)
oLabelMess = oDlgModel.getByName("LabelMess")
REM   =========   Задать свойства элемента управления (кнопки - OK) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oModel.setPropertyValues( _
Array("PositionX", "PositionY", "Width", "Height", "Label", "PushButtonType", "Align", "VerticalAlign", "BackgroundColor"),_
Array(264, 12, 48, 24, "OK", com.sun.star.awt.PushButtonType.OK, 1, 1, RGB(153,153,255)) )
oDlgModel.insertByName("ButtonOK", oModel)
REM   =========   Задать свойства элемента управления (кнопки - Остановка Макроса) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oModel.setPropertyValues(_
Array("PositionX", "PositionY", "Width", "Height", "Label", "PushButtonType", "Align", "VerticalAlign", "BackgroundColor", "MultiLine"),_
Array(324, 12, 48, 24, "Остановка Макроса", com.sun.star.awt.PushButtonType.CANCEL, 1, 1, RGB(255,153,204), True) )
oDlgModel.insertByName("ButtonStopMacro", oModel)
'REM   =========   Задать свойства элемента управления (Поле редактирования текста - текстовое поле) в Модель Диалога
oModel = oDlgModel.createInstance("com.sun.star.awt.UnoControlEditModel")
oModel.setPropertyValues( Array("PositionX", "PositionY", "Width", "Height", "Text", "Align", "VerticalAlign"), _
Array(132, 12, 120, 24, "ТЕКСТ", 0, 1) )
oDlgModel.insertByName("TextFieldText",oModel)
oTextEdit = oDlgModel.getByName("TextFieldText")
REM   =========   Запуск самого Диалога
DlgRez = oDlg.execute()
Do While DlgRez
oLabelMess.Label = oTextEdit.Text & CountStep
oTextEdit.Text = ""
CountStep = CountStep + 1
oLabelCountStep.Label = CountStep
DlgRez = oDlg.execute()
Loop
oDlg.endExecute()
End Sub


По "мотивам" макроса для обработки нажатий клавиш, найденного на этом форуме, получен небольшой модуль, который реагирует только на клавишу «ENTER» - и там всё прекрасно работает:

REM  *****  BASIC  *****
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'––––––––––––––––––––––––––––––––– XKeyHandler –––––––––––––––––––––––––––––––––
Global oXKeyHandlerRET As Object

Sub StartXKeyHandlerRET()
    If IsNull(oXKeyHandlerRET) Then  'только если ещё не запущен
        oXKeyHandlerRET = CreateUnoListener("XKeyHandlerRET_", "com.sun.star.awt.XKeyHandler")
        ThisComponent.GetCurrentController.AddKeyHandler(oXKeyHandlerRET)
    End If
End Sub

Sub StopXKeyHandlerRET()
    If Not IsNull(oXKeyHandlerRET) Then  'только если всё ещё работает
        ThisComponent.GetCurrentController.removeKeyHandler(oXKeyHandlerRET)
        oXKeyHandlerRET = Nothing  'чтобы узнать позже, что этот обработчик остановлен
    End If
End Sub

Sub XKeyHandlerRET_disposing(oEvent)
    Call StopXKeyHandlerRET
End Sub

Function XKeyHandlerRET_keyPressed(oEvent) As Boolean
    XKeyHandlerRET_keyPressed = False  'Don't cancel this‼
'если нажата клавиша "ВВОД", то ...
    If oEvent.KeyCode = com.sun.star.awt.Key.RETURN Then
    MsgBox "Нажата клавиша «ENTER»!!!"
        ' Ваш код...
    End If
End Function

Function XKeyHandlerRET_keyReleased(oEvent) As Boolean
    XKeyHandlerRET_keyReleased = False  'Don't cancel this‼
End Function


Но я никак не могу понять как их "подружить".
Сделать обработчик событий для текстового поля?

oListener = CreateUnoListener("TextField_", "com.sun.star.awt.XActionListener")
oDlg.getControl("TextFieldText").addActionListener(oListener)

И как-то "привязать" к обработки нажатий клавиш?

Или сначала запустить этот обработчик для клавиш, а после задействовать реализацию Диалога?

Помогите, пожалуйста, разобраться!

economist

Выглядит очень сложно, а когда еще и куча листнеров - будет глючно. Сделаю одну попытку вас отговорить :-)

Для "пошагового визарда", вместо диалога с кучей кнопок и кода на них - намного проще использовать несколько листов Calc, шагая макросом по ним слева направо. Заодно реализовать всю логику обработки, проверок, форматирования базовыми возможностями Calc (формулами, усл. форматированием, проверкой данных итп). Огромное число небольших бизнес-приложений пошло именно по этому пути, и ведь работают.

Имитировать диалог в листе несложно, нужно просто больше серого цвета. А кнопок достаточно две: < и > Ненужные листы можно просто скрыть. С т. зр. UX это даже проще. Не надо гадать с разрешениями экранов и читаемостью шрифтов, кому мелко - увеличат. Защиту легко реализовать штатными способами. И в Calc будет куча помощников с опытом Excel, а листнеры вы будете тащить в одиночку. 

Даже если делать Form (форму) в Calc/Writer/Basе - она все равно проще чем программирование навороченного диалога с нуля.   
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

Tigrik

Большое спасибо за желание помочь мне.
Моя ошибка, что в этой теме я не полностью обрисовал всю задачу, для которой и "строится" этот макрос - это было сказано в предыдущей моей теме «Переключение задач в Windows» https://forumooo.ru/index.php/topic,9029.0.html
На экране монитора будет два окна: большую часть занимает определенная страница Интернета, а под ним - окно Диалога, которое запустил макрос.
Считывается информация из браузера и предполагалось, что по нажатию клавиши «ENTER» будет переключение в окно Диалога.
Какая-то информация заносится в текстовое поле Диалога и, опять же, по нажатию «ENTER» определенным кодом обрабатывается и результат определяется в поле "Метка" (Надпись) и снова АКТИВИРУЕТСЯ окно браузера.
Всё это очень желательно делать быстро (без лишних движений) и будет достаточно долго.
На текущий момент сделан макрос (по своим старым наработкам), который представлен в заглавном сообщение этой темы и он полностью соответствует поставленной задачи, за исключением переключением между окнами Браузера и Диалога.
Если возврат из Браузера в Диалог с помощью макроса LO, пока, скорее всего, невозможно, то хотелось бы найти решение как в Диалоге "поймать" нажатие «ENTER», чтобы можно "прицепить" метод AppActivate, который предложил Владимир (sokol92) - большое ему спасибо за это.

Я не совсем понял о каких нескольких листах Вы говорите, но делать Форму в Calc - это я буду тренироваться чуть позже.
Мой опыт с макросами очень близкий к нулю, но для меня этот макрос не кажется очень сложным. Если ещё добавить пару вспомогательных подпрограмм, которые будут минимизировать задание свойств элементам управления (как у Питоньяка), то и визуально макрос будет смотреться совсем просто.

Очень надеюсь, что кто-нибудь сможет подсказать как мне реализовать в своём макросе обработчик событий для нажатия клавиш.

sokol92

#3
Добрый день!
Лучше начинать учить алгебру с формул сокращенного умножения, чем сразу с теории Галуа.  :)

Откройте в книге А.Питоньяка OOME_4_0.odt в библиотеке OOME40 диалог OOMESample и посмотрите как он устроен, пользуясь текстом книги, где про него рассказывается. Создавать и сопровождать такой диалог гораздо удобнее, чем "динамический", который приведен в Вашем стартовом сообщении. На создание диалога, подобного диалогу А.Питоньяка, требуется совсем немного времени.
Владимир.

Tigrik

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

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

Скорее всего, economist прав:
Цитата: economist от 14 февраля 2022, 09:39а листнеры вы будете тащить в одиночку
Обработчики событий, наверное, не пользуются особой популярностью.

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

sokol92

#5
Для макроса из стартового сообщения этой темы слушатели не нужны. Просто добавьте в список свойств для кнопки "OK" свойство "DefaultButton" со значением True. После этого нажатие "Enter" на клавиатуре вызовет то же действие, что и нажатие кнопки "OK".
Владимир.

Tigrik

Владимир, видимо, все-таки, я что-то пропустил у Питоньяка.
Огромное спасибо.
Сейчас попробую это применить.