Программы с графическим интерфейсом на Visual Prolog

      Комментарии к записи Программы с графическим интерфейсом на Visual Prolog отключены

Главная Форумы Программирование Помощь с решением задач на Prolog Общие вопросы Программы с графическим интерфейсом на Visual Prolog

Помечено: , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 1 месяц назад.

  • Автор
    Сообщения
  • #3477

    Создание окна в Visual Prolog

    Проект создается по уже известной вам схеме, но вместо стратегии EasyWin необходимо использовать стратегию VPI. Она упрощает построение оконных приложений, которые запускаются под 16- и 32-разрядной Windows.

    Все компоненты приложения зарегистрированы в окне проекта (Project Window). Кнопками на левой стороне окна проекта выбирают тип компонентов :

    1. исходный модуль – Module,
    2. диалоговое окно – Dialog,
    3. меню – Menu,
    4. панель инструментов – Toolbar,
    5. пиктограмма – Bitmap и т.д.

    Все компоненты выбранного типа будут перечислены в центральной части окна проекта. Кнопки на правой стороне окна проекта выполняют действия над выбранным компонентом:

    1. New – добавить новый компонент выбранного типа,
    2. Edit – отредактировать выбранный компонент,
    3. Delete – удалить выбранный компонент и т.д. Окно проекта представлено на рисунке:

    Для создания формы необходимо нажать на кнопку Window на левой стороне в окне проекта и затем нажать кнопку New (наверху справа). Появится диалоговое окно Window Attributes. В этом окне нужно набрать имя окна (Name) и установить различные атрибуты окна, а также щелчком мыши по полю Storing in Separate File определить размещение файла окна в проекте, нажать OK:

    Когда диалоговое окно Window Attributes закроется, автоматически появится редактор окон (Window Editor). Он используется для размещения средств управления в окнах или изменения размера окна и атрибутов:

    Далее для созданного окна нужно сгенерировать его стандартный исходный код Visual Prolog. Исходный код даст следующее:

    • код, фактически создающий окно с указанными атрибутами размещения;
    • предикат обработчика событий, делающий возможной реакцию окна на события, которые система GUI посылает, когда что-либо происходит с окном.

    Простой способ создавать и управлять исходным кодом Visual Prolog для окна состоит в том, чтобы использовать эксперт окон и диалоговых окон. Для его активизации нужно нажать кнопку Code Expert, когда окно выбрано в окне проекта:

    После активизации эксперта окон и диалоговых окон необходимо выбрать исходный модуль (в данной системе Uroglot.pro). Затем нужно нажать кнопку Default Code. Когда код будет сгенерирован, кнопка Edit Code станет доступной. Нажатие кнопки Edit Code вызовет редактор сгенерированного кода:

    После окончания создания окна необходимо его активизировать. Для начала необходимо добавить дополнительный пункт меню. Для этого в окне проекта необходимо нажать кнопку Menu на левой панели инструментов. Когда в окне появиться список меню, зарегистрированный в проекте, нужно дважды щелкнуть мышью на пункте Task Menu или нажать на пункт меню Edit с правой панели инструментов для активизации редактора меню:

    Для добавления нового пункта меню верхнего уровня необходимо нажать кнопку New.

    Символ &, который встречается в именах некоторых пунктов меню, определяет, что при отображении меню символ, следующий за &, отображается подчеркнутым. Это используется для определения «горячих» клавиш. Для создания подменю необходимо стать курсором на нужное меню, внутри которого нужно сделать новый пункт, и нажать на кнопку Submenu. А затем нажать на New для создания нового подменю.

    В диалоговом окне Menu Item Attributes можно определить, будет ли пункт меню неактивным (Disabled) или отмечен галочкой (Checked). Если необходимо, можно определить «горячую» клавишу, напечатав символ в поле Accelerator и выбрав соответствующую комбинацию клавиш < Shift >, < Alt > или < Ctrl >:

    Теперь необходимо добавить созданный пункт меню в проект. Для этого необходимо нажать на кнопку Code Expert на правой панели инструментов в окне проекта (или использовать комбинацию клавиш <Ctrl> + <W>) для вызова эксперта окон и диалоговых окон:

    Нужно выбрать пункт Menu в списке Event Type слева. Выделить строку id_file_start или другую константу, которую в качестве идентификатора ресурса можно связать с пунктом меню.

    Далее нужно нажать на кнопку Add Clause, чтобы сгенерировать Пролог-предложение для события. Название кнопки Add Clause изменится на Edit Clause, когда код для события будет создан.

    Нажатие на кнопку Edit Clause вызовет редактор. Он позиционируется на соответствующем предложении обработчика событий. В результате можно наблюдать, что к предикату обработчика событий для окна Task было добавлено новое предложение:

    %BEGIN Task Window, id_file_start
    task_win_eh(_Win, e_Menu(id_file_start, _ShiftCtlAlt), 0):– !, !.
    %END Task Window, id_file_start

    Комментарии %BEGIN – %END анализируются экспертом окон и диалоговых окон, чтобы определять положение кода для компонентов пользовательского интерфейса.

    Здесь (в начале второй строки добавленного предложения) нажимаем правую кнопку мыши и выбираем пункт меню Insert | Predicate Call | Window, Dialog or Toolbar (или нажать комбинацию < Ctrl > + < Shift > + < W >). Эти действия активизируют диалоговое окно:

    В окне нужно выбрать переключатель User Defined Window. После этого будет вызов предиката для создания окна main:

    task_win_eh(_Win,e_Menu(id_file_start,_ShiftCtlAlt),0):-!,
      win_main_Create(_Win), !.

    Предикат win_Create используется для создания как окон верхнего уровня, так и дочерних окон:

    Window = win_Create (Windowtype, Rct, Title, Menu, ParentWindow, WSFlags, EventHandler,CreationData)

    Параметр Windowtype определяет вид окна. Параметр Rct определяет размер нового клиентского окна. Значение параметра Title будет отображено в строке заголовка окна (если окно имеет строку заголовка). Для окон верхнего уровня параметр Menu может использоваться для определения, какое меню должно иметь окно. ParentWindow содержит дескриптор родительского окна, которое для окон верхнего уровня должно быть окном Screen или окном Task, а для дочерних окон — окном верхнего уровня или другим дочерним окном. WSFlags — это список значений флагов, которые определяют внешний вид и поведение окна. EventHandler определяет предикат, который должен быть вызван, когда приходит событие для окна. CreationData — значение long, которое будет передано обработчику событий как часть события e_Create.

    Элементы управления

    Пришло время познакомиться со средствами управления. Средства управления – это специализированные дочерние окна, которые обычно используются в диалоговых окнах для выполнения различных задач ввода/вывода.

    Элементы управления не имеют собственных обработчиков событий. События от элементов управления вызывают отправление уведомительных сообщений обработчику событий родительского окна. Предопределенные классы элементов управления перечислены ниже.

    тип элемента управления класс окна
    командная кнопка wc_pushbutton
    переключатель wc_radiobutton
    флажок wc_checkbox
    горизонтальная полоса прокрутки wc_hscroll
    вертикальная полоса прокрутки wc_vscroll
    поле редактирования wc_edit
    статический текст wc_text
    список wc_lbox
    раскрывающийся список wc_lboxbutton
    редактируемый список wc_lboxedit
    элемент группировки wc_groupbox
    пиктограмма wc_lcon

    Поскольку элементы управления являются окнами, приложение может управлять ими, используя функции управления окнами. Оконный дескриптор для элемента управления всегда может быть получен по родительскому окну и идентификатору ресурса элемента управления:

    CtrlHndl = win_GetCtlHandle (ParentWindow, CtrlId)

    Далее приведены часто используемые предикаты для работы с элементами управления:

    Создание элементов управления может быть автоматическим – как часть создания диалогового окна по его описанию, определенному в сегменте ресурсов приложения, или динамически – во время работы приложения.

    Диалоговые окна разрабатываются и размещаются в файлах ресурсов в редакторе диалоговых окон VDE, а затем, они создаются (показываются) во время исполнения вызовом предиката win_CreateResDialog, а диалоговые окна, не размещенные в файлах ресурсов, могут быть созданы динамически во время исполнения вызовом предиката win_CreateDynDialog, но все параметры должны быть определены во время создания.

    Для создания в окне нового элемента управления используют предикат win_CreateControl. Для создания в окне нескольких элементов управления, определенных в структуре Windef_list, — предикат win_CreateDynControl. Для того чтобы добавить дополнительные элементы управления к обычному окну или диалоговому окну, создают невидимый элемент управления, который затем делается видимым.

    Изучив параметры предиката win_CreateControl, вы сможете создавать элементы управления с различными возможностями.

    CtrlWin = win_CreateControl(
      Windowtype, % Тип элемента управления
      Rct, % Размер и позиция
      string Title, % Заголовок
      window Parent, % Родительское окно элемента управления
      Wsflags, % Флаги стилей для элемента управления
      integer CtrlId % Значение, передаваемое событию e_Create
    ) 

    CtrlWin = win_CreateDynControl(
      Windef_list, % Определение структуры
      window Parent % Значение, передаваемое событию e_Create
    ) 

    Использование списка

    Список — это особая форма часто используемого элемента управления. Список показывает набор строковых элементов, которые можно прокручивать для просмотра. Подробное описание списков дано в интерактивной справке.

    Если список содержит больше элементов, чем может быть отображено в окне, и установлен флаг wsf_Vscroll, то автоматически появится вертикальная полоса прокрутки. Списки обычно содержат строки, но, используя стиль wsf_OwnerDraw, можно создавать списки с произвольным типом данных.

    В VPI есть несколько предикатов для работы со списками. Все они имеют префикс lbox_. Эти предикаты требуют идентификатор списка, который может быть получен вызовом предиката win_GetCtlHandle, дескриптор родительского окна и рекурсивный идентификатор списка. Индекс 0 определяет первый элемент списка, 1 – второй и т.д. Значение индекса –1 используется для добавления элемента в конец списка:

    • lbox_Add(Window, integer Index, string Str). Этот предикат добавляет новую строку в список и отображает ее, если она находится внутри списка. Новый элемент будет размещен в строке, следующей за строкой с индексом Index. Если Index = –1, то строка будет добавлена в конец списка, а текущая строка останется выделенной;
    • lbox_Clear(Window). При помощи этого предиката можно очистить окно списка и удалить все элементы;
    • lbox_Delete(Window, integer Index). Этот предикат может быть использован для удаления конкретного элемента из списка. Значение –1 будет проигнорировано;
    • lbox_GetItem(Window, integer Index). Этот предикат используется для получения конкретного элемента в списке. Значение –1 будет проигнорировано;
    • lbox_GetSelIndex(Window). Этот предикат возвращает индекс выбранного элемента. Предикат завершится неудачно, если никакой элемент в списке не будет выбран;
    • lbox_SetSel(Window, integer Index, Boolean Select). Этот предикат используется для выбора элементов в списке. При возможности множественного выбора из списка этот предикат будет влиять только на один элемент. При одиночном выборе из списка выбор одного элемента автоматически будет отменять выбор других элементов в списке.

    Примеры работы со списком:

    • Занесение новых строк в список по номерам:
      Lb1=win_GetCtlHandle(_Win, idc_main_1),
      lbox_Add(Lb1, 0, "Нет данных"),
      lbox_Add(Lb1, 1, "Ост. пиелонифрит или МКБ Ост. пилонифрит"),
      lbox_Add(Lb1, 2, "Хр. пиелонифрит или МКБ Хр. пилонифрит"),
      lbox_SetSel(Lb1, 1, b_true),
    • Взятие номера индекса выбранного элемента и преобразование его в строку:
      Lb1 = win_GetCtlHandle(_Win,idc_main_1),
      Index1 = lbox_GetSelIndex(Lb1),
      str_int(Str1, Index1),

      где: str_int() – предикат преобразования целочисленного типа в строковый.

    Примеры создания окон

    Окно часов

    Попробуем создать окно, которое отображает текущее время.

    • Создайте новый исходный модуль Clock.pro.
    • Добавьте пункт Clock Window в подменю Test меню Task.
    • Создайте новое окно Clock.
    • Зайдите в эксперт окон и диалоговых окон и добавьте код по умолчанию для окна Clock в модуль Clock.pro.
    • Используйте эксперт окон и диалоговых окон, чтобы добавить предложение для
      вызова окна Clock из окна Task при выборе команды Test | Clock Window.
    • Запустите программу и посмотрите, создается ли окно при вызове команды Test | Clock Window.
    • Вернитесь в эксперт окон и диалоговых окон и добавьте предложение для события e_Update в окне Clock.

    Использование таймеров

    Использовать таймер очень просто. Вы можете в любое время создать новый таймер для окна вызовом предиката timer_Set (window, Milliseconds). Как только предикат timer_Set был вызван, окно в указанные интервалы времени будет получать событие e_Timer.

    Событие e_Update для окна часов

    На событие обновления e_Update мы будем выводить текущее время, центрированное в окне. Мы можем получить время запросом к предикату time/4. Первые три целых числа, возвращенные time/4, затем преобразуются в строку предикатом format. Наконец, строка выводится в центре окна предикатом draw_TextInRect, которому передается полный клиентский прямоугольник для вывода текста по центру этого прямоугольника:

    win_clock_eh(_Win,e_Update(_),0):-!,
      win_Clear(_Win,color_White),
      RCT=win_GetClientRect(_Win),
      time(Hours,Minutes,Seconds,_),
      format(Str,"%02:%02:%02",Hours,Minutes,Seconds),
      draw_TextInRect(_Win, RCT, Str, -1, [dtext_center,dtext_vcenter,dtext_singleline]).

    Событие e_Size для окна часов

    Каждый раз, когда окно изменяет свои размеры, изображение нужно перерисовывать. Правильнее будет не перерисовывать при событии изменения размера окна e_Size, а вызывать новое событие e_Update для всего окна:

    win_clock_eh (_Win, e_Size(_Width, _Height) ,0):-
      !, win_Invalidate (_Win).

    Событие е_Create для окна часов

    На событие е_Create мы запускаем таймер. Значение интервала в 1000 миллисекунд означает, что мы будем получать событие таймера каждую секунду:

    win_clock_eh (_Win, e_Create(_), 0):-!,
      _NewTimerId = timer_Set(_Win, 1000).

    Событие e_Timer для окна часов

    На событие е_Timer мы будем объявлять окно недействительным. Это вызовет обновление окна в том случае, если оно не свернуто и не закрыто другим окном. (Вы найдете событие e_Timer под группой Misc в эксперте окон и диалоговых окон).

    win_clock_eh (_Win, e_Timer (_TimerId),0):-
      !, win_Invalidate(_Win).

    Обратите внимание, что в реальном приложении вы, вероятно, не стали бы объявлять недействительным целое окно, т. к. слишком много времени может потребоваться на то, чтобы перерисовать его. Если вы хотите, чтобы программа была быстрой и выглядела профессионально, нужно стараться не объявлять окно недействительным. Правда, это потребует дополнительных усилий уже после того, как основные функциональные возможности будут реализованы.

    Таймеры — ограниченный ресурс системы. В реальном приложении идентификатор таймера, возвращаемый timer_set, должен быть сохранен для освобождения в событии e_destroy, где он будет использоваться в качестве аргумента в предикате timer_Kill/1.

    Добавление элементов управления в окно часов

    Для начала мы добавим два средства управления к нашему окну Clock:

    1. кнопку, которая запускает/останавливает время;
    2. переключатель для определения, показывать время или нет.

    Разместить эти элементы управления в окне Clock можно, используя редактор окон и диалоговых окон. В окне проекта выберите пункт меню Window, выделите окно Clock и нажмите кнопку Edit.

    После того как откроется редактор окна, на экране отобразится панель инструментов Controls. На этой панели инструментов вы можете нажимать на соответствующие кнопки элементов управления и перетаскивать их в окно Clock. Если отпустить кнопку мыши в окне, элемент управления будет помещен в выбранную позицию. Если отметить прямоугольник, элемент управления будет помещен в отмеченный прямоугольник. Когда вы отпустите кнопку мыши, активизируется диалоговое окно Control Attributes (диалоговое окно PushButton Attributes показано ниже), в котором вы можете определить атрибуты для элемента управления. Теперь нужно ввести имя элемента управления; оно должно быть определено в управляющем элементе редактирования (на рисунке имя кнопки — Start).

    Для элементов управления нужно определить параметры в полях Text и Constant:

    1. для кнопки: в поле Text значение Start, в поле Constant значение idc_startstop;
    2. для переключателя: в поле Text значение Show Date, в поле Constant значение
      idc_show_date.

    Сейчас вы могли бы проверить несколько различных функций размещения/компоновки редактора окон и диалоговых окон. Рисуя охватывающий
    прямоугольник или удерживая клавишу <Ctrl> щелчком мыши, вы можете отмечать группу элементов управления и изменять их расположение при помощи меню Layout или панели инструментов:

    Если вы теперь попытаетесь запустить приложение и откроете окно Clock, то увидите, что часы идут как раньше, а два элемента управления показаны, но пока не функционируют.

    После того как вы выполните команду Project | Run, эксперт кода автоматически обновит код для окна Clock. Вы можете посмотреть код для события e_Create окна Clock и обнаружите, что, как только родительское окно было создано, эксперт кода добавил следующие два вызова для создания двух элементов управления:

    win_CreateControl (wc_PushButton, rct (73,29,193,59), "Start", _Win, [wsf_Group, wsf_TabStop], idc_startstop),
    win_CreateControl (wc_CheckBox, ret (45,91,165,116), "Show Date", Win, [wsf_Group, wsf_TabStop, wsf_Auto], idc_show_date)

    Когда вы хотите добавить какую-либо функциональность для элемента управления, нужно войти в эксперт окон и диалоговых окон и выбрать строку Control в списке Event Type. Затем можно добавить события, чтобы управлять действиями
    элементов управления в окне:

    Чтобы добавить предложение для каждого элемента управления, используем кнопку Add Clause.

    Сначала добавим код для управления запуском/остановкой таймера. Чтобы сделать это проще в обработчике события, мы определим два маленьких вспомогательных предиката: startTimer и stopTimer, а также локальную базу данных clock:

    facts - clock
      timer (window, long TimerId)
    predicates
      startTimer (window)
      stopTimer (window)
    clauses
      startTimer (Win):-
        TimerId = timer_Set (Win, 1000),
        assert (timer (Win, TimerId)).
      stopTimer (Win):-
        retract (timer (Win, TimerId)), !,
        timer_Kill (TimerId).

    Теперь нужно изменить событие e_Create для окна Clock:

    1. удалите прежний код для запуска таймера;
    2. добавьте код, обеспечивающий ручной запуск/останов таймера при нажатии кнопки Start.

    Выберите предложение обработчика для кнопки (используйте кнопку Add Clause/Edit Clause) и добавьте следующий код для запуска/останова таймера:

    win_clock_eh (_Win, e_Control(idc_startstop, _, _CtrlWin, _CtlInfo), 0 ):-
      Title = win_GetText(_CtrlWin),
      Title = "Start",
      stopTimer (_Win),
      win_SetText (_CtrlWin,"Stop"), !.
    win_clock_eh (_win, e_Control (idc_startstop, _, _CtrlWin, _CtlInfо) , 0):-
      !, startTimer(_Win), win_SetText(_CtrlWin, "Start"), !.

    Код изменяет название кнопки (Start/Stop), чтобы показать, запускать таймер или останавливать. Вызов предиката win_GetText может возвратить надпись на кнопке, а вызов предиката win_SetText — установить новый текст для кнопки.

    Замечание: чтобы изменить текст, мы обращаемся к идентификатору кнопки Start(_CtrlWin), a не к дескриптору окна Clock. Дескриптор этого окна передается в структуре события e_Control.

    В качестве нашего второго изменения мы хотели бы модифицировать окно Clock в зависимости от состояния флажка Show Date. Для этого мы используем предикат win_IsChecked, который, принимая дескриптор окна флажка, может возвращать логическое значение, определяющее, установлен флажок или нет.

    Однако в предложении события e_Update имеется маленькая проблема — у нас нет дескриптора к окну Show Date. Чтобы получить его, мы используем предикат win_GetCtrlHandle, который, принимая дескриптор родительского окна и идентификатор элемента управления (константа idc_show_date), возвращает дескриптор окна для элемента управления.

    % This must be the first e_Update clause
    win_clock_eh (_Win, e_Update (_), 0):-
      % Note: no Cut !
      _CtrlWin = win_GetCtlHandle ( _Win, idc_show_date),
      IsChecked = win__IsChecked ( _CtrlWin),
      IsChecked = checkbox_off, !.

    He забудьте удалить первое отсечение в приведенном выше предложении. Третьим изменением будет удаление первоначального вызова предиката timer_set из предложения e_Create:

    win_clock_eh ( _Win, e_Create(_) , 0):- 
      !, 
      _NewTimerId = timer_Set (_Win, 1000). % <- удалите эту строку

    Теперь нужно обеспечить, чтобы окно обновлялось немедленно после того, как будет изменено состояние флажка. Поэтому, когда мы получаем событие для флажка, окно становится недействительным:

    win_clock_eh ( _Win, e_Control (idc_show_date, _, _CtrlWin, _CtlInfo) , 0):- 
      !, win_Invalidate(_Win).

    В приведенном выше примере мы воспользовались преимуществом специфического свойства MS Windows. При первоначальном создании элемента управления по умолчанию устанавливается флажок Ctl_Auto. Это означает, что флажок автоматически изменяет свое состояние, когда пользователь щелкает на нем мышью.

    Обратите внимание, что этот простейший код показывает только время. Чтобы увидеть, как отображать дату и время, — проверьте код в файле Clock.pro.

    Создание окна редактора

    Для настройки и использования редактора существует гибкий API (Application Programming Interface). Помимо специальных функций, редактор поддерживает закрашивание лексемы и гипертекстовые поля. Теперь поработаем с окном редактора.

    Выполните следующие шаги:

    • Создайте новый исходный модуль Edwin.pro.
    • Создайте новое окно Editor.
    • Войдите в эксперт окон и диалоговых окон и определите, что код должен быть в
      модуле Edwin.pro. Выберите стиль кода edit_Create для генерации экспертом кода.
    • Добавьте пункт Editor Window в меню Task подменю Test. Вставьте код для
      создания окна редактора для этого события.
    • Попытайтесь запустить приложение: откройте окно редактора и попробуйте
      редактировать какой-либо текст в этом редакторе.

    Если посмотрим на сгенерированный код в модуле Edwin.pro, то увидим, что вызов создания окна редактора имеет задаваемый по умолчанию набор значений для различных аргументов.

    win_editor_Create (_Parent):-
    ifdef use_editor
      Text = "",
        Font = font_Create(ff_Fixed,[ ],10),
        ReadOnly = b_false, Indent = b_true, InitPos = 1,
        edit_Create (win_editor_WinType, win_editor_RCT, win_editor_Title,
        win__editor_Menu, _Parent, win_editor_Flags, Font, ReadOnly,
        Indent, Text, InitPos, win_editor_eh),
    enddef
    true .

    Вы можете легко изменить этот код, например, чтобы загрузить определенный текст в редактор:
    file_str ("С:\\TEMP\\TST\\Myproj.con",Text)

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

    Вставка текста в редактор

    Вставить текст в редактор, вызывая предикаты, очень просто. Предикат edit_PasteStr может вставлять строку в любую позицию в тексте (эта позиция начинается с 1).

    В качестве примера мы можем добавить новую функцию, которая состоит в том, что, как только вы напечатаете начало комментария /*, автоматически будет вставлен конец комментария */. Чтобы сделать это, мы будем следить за печатаемыми символами. Когда пользователь нажимает клавишу, активному окну посылается событие e_Char. Очень просто добавить пару предложений, которые отслеживают символы / и *. Как только замечен символ /, устанавливается флажок для регистрации этого факта, и если следом идет символ *, тогда будет вставлена строка */, в противном случае флажок будет сброшен. Используем предикат edit_GetPos, чтобы определить позицию курсора в редакторе. Наконец, для удобства пользователя мы выделяем строку, которая вставлена таким образом, что если пользователь не хочет ее вставлять, ему всего лишь нужно напечатать любой символ, и строка исчезнет.

    win_editor_eh (_Win, e_Char ( ' / ' , _ ) , 0):-
      !, not (commentflag ( _Win) ), 
      assert (commentflag (_Win)),
      fail.
    win_editor_eh (_win, e_Char(' * ', _ ),0):-
      !, retract (commentflag(_Win)),
      Pos = edit_GetPos (_Win),
      edit_PasteStr (_Win, Pos, "* */"),
      Posl = Pos+1, Pos2 = Posl + 4,
      edit_SetSelection (_Win, Posl, Pos2), !.
    win_editor_eh (_Win, e_Char (_, _), 0):-!,
      retract (commentflag (_Win)),
      fail.

    Два предыдущих предложения, которые просто управляют состоянием флажка, тоже завершаются неуспехом; таким образом, редактор сам может выполнять стандартную обработку таких сообщений (вставить символы, обновить экран и т. д.) так, как если бы этих предложений не было. Чтобы определить базу данных, используемую выше, вставьте следующий код в начале файла:

    facts – editor
      commentflag (window)

    Сложение двух чисел

    Опишем простейшую программу сложения двух чисел. По уже известной нам схеме создадим окно «Addition» следующего вида:

    В диалоговом окне Dialog and Window Expert нажмем кнопку Default Code для того, чтобы сгенерировать код по умолчанию для окна и элементов управления.

    Программа должна работать следующим образом. Вводим два слагаемых в соответствующие поля, а при нажатии кнопки «Вычислить» в поле суммы отображается результата сложения. Для этого рассмотрим процесс обработки событий для кнопки «Вычислить». В диалоговом окне Dialog and Window Expert выберем в списке Event Type поле Control, а в списке Event or Item — идентификатор кнопки «Вычислить». Нажмем на кнопку Add Clause для генерации кода обработки событий для кнопки «Вычислить».

    Далее нам необходимо внести изменения в код обработки событий кнопки. Для этого нажмем кнопку Edit Clause. В результате появиться следующий код:

    %BEGIN addition, idc_push_button _CtlInfo
    win_addition_eh(_Win,e_Control(idc_push_button,_CtrlType,_CtrlWin,_CtlInfo),0):-
      !, !.
    %END addition, idc_push_button _CtlInfo

    Произведем обработку события (вычисление суммы). Получаем следующий код:

    %BEGIN addition, idc_push_button _CtlInfo
    win_addition_eh(_Win,e_Control(idc_push_button,_CtrlType,_CtrlWin,_CtlInfo),0):-
      !, Ctl1=win_GetCtlHandle(_Win,idc_edit1),
      %получение оконного дескриптора
      %элемента управления edit1
      String1 = win_GetText(Ctl1), %получение содержимого поля %редактирования (1 слагаемое)
      str_real(String1,X), %преобразование содержимого поля редактирования 
      %String1 в вещественное число X
      Ctl2=win_GetCtlHandle(_Win,idc_edit2),
      %получение оконного дескриптора
      %элемента управления edit2
      String2 = win_GetText(Ctl2), %получение содержимого поля %редактирования (2 слагаемое)
      str_real(String2,Y), %преобразование содержимого поля редактирования %String2 в вещественное число Y
      Z=X+Y,
      str_real(String,Z), %преобразование числа Z в строку String
      Ctl3=win_GetCtlHandle(_Win,idc_edit3),
      %получение оконного дескриптора
      %элемента управления edit3
      win_SetText(Ctl3,String),
      %установка содержимого содержимого поля редактирования (результат)
      !.
    %END addition, idc_push_button _CtlInfo

    Создание диалогового окна

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

    Код для обработки диалогового окна может быть очень похож на код для обработки окна. Существует предикат для создания диалогового окна.

    Предикат win_CreateResDialog создаст модальное или немодальное диалоговое окно в зависимости от параметра Windowtype:

    Window = win_CreateResDialog(ParentWindow, Windowtype, ResId, Eventhandler, CreationData)

    Здесь ParentWindow – это окно, которое получит фокус после закрытия диалогового окна. Windowtype должен быть равен wd_Modal или wd_ModeLess в зависимости от того, какое нужно диалоговое окно. ResId – целое число, которое определяет диалоговое окно в RES-файле, Eventhandler – предикат обратного вызова, который используется для обработки событий от диалогового окна, CreationData – значение типа long, которое передается событию e_Create.

    По событию e_Create вы можете инициализировать все элементы управления, а когда нажата кнопка ОК, вы можете получить все значения.

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

    Для того чтобы реализовать пример использования диалоговых окон, выполните следующие действия:

    • Создайте новый исходный модуль Dialogs.
    • Создайте дополнительный пункт Dialog в меню Task подменю Test.
    • Создайте диалоговое окно Person.
    • Вставьте следующие элементы управления в диалоговое окно:
      1. поле редактирования: idc_name;
      2. поле редактирования: idc_age;
      3. зависимый переключатель: idc_male;
      4. зависимый переключатель: idc_female;
      5. независимый переключатель: idc_married;
      6. список элементов: idc_skills — множественная и расширенная выборка (Multiselect+Extended).

    Здесь надо использовать визуальные компоненты: статический текст (static text) для написания заголовков перед элементами редактирования и списка элементов, рамка, которая окружает кнопки Male и Female.

    Скомпонуйте ваше диалоговое окно. Затем вызовите эксперта кода для диалогового окна, выберите исходный модуль dialogs.pro и выберите стиль кода diaiog_Create перед активизацией кнопки Default code.

    Чтобы увидеть, как работает сгенерированный по умолчанию код, вам нужно добавить дополнительное предложение для события пункта меню Task окна Test | Dialog, вставить вызов для создания диалогового окна и запустить приложение.

    Эксперт диалогового пакета

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

    Самый простой способ вызвать эксперт диалогового пакета — выбрать имя диалогового окна в окне проекта, выбрать эксперт кода и затем нажать кнопку Dialog Pack.

    Экран эксперта диалогового пакета разделен на две части. Левая область окна всегда содержит список доступных элементов управления. Некоторые из них снабжены префиксом + (плюс): двойной щелчок на + отображает более детальную информацию. Правая сторона используется для отображения и изменения различных настроек выбранного элемента управления.

    Выберите элемент управления, который должен содержать имя человека idc_name — тип переменной должен быть строковый (string). Нажмите на значок + и, когда он изменится на -, выберите из раскрывшегося списка значение Init value, щелкните на кнопке списка Setting method, затем выберите значение Variable, чтобы указать, что начальное значение задается из переменной. В поле Variable (init) вы должны ввести имя переменной — Name.

    Точно так же для поля возраста Age вы определите, что:

    • – тип переменной — целый (integer);
    • – оно будет установлено посредством Variable;
    • – имя переменной — Age;
    • – метод настройки параметров — User specified;
    • – минимальное значение — 0;
    • – максимальное значение — 70.

    Элемент управления idc_married — это независимый переключатель; мы определяем, установлен ли он, по значению переменной Married.

    Следующий элемент управления — список навыков. Это список с возможностью множественного выбора, т. к. человек может обладать множеством разнообразных навыков. Пункты списка в окне списка всегда постоянны, а навыки человека выбраны (высвечены).

    В диалоговом окне Alternatives вы можете ввести список статических элементов в виде строк, разделенных запятыми. В диалоговом окне Init value вы можете определить, что переменная Skills будет возвращать список целых чисел (индексы выбранных навыков).

    Также в эксперте диалогового пакета нужно:

    • определить, каким группам принадлежат те или иные зависимые переключатели (radio buttons);
    • дать имя переменной для каждой группы так, чтобы можно было произвести инициализацию и возвратить заданные значения.

    Новые группы переключателей создаются при нажатии кнопки New; кнопки Add и Del используются, чтобы добавлять (удалять) зависимые переключатели в группы:

Для ответа в этой теме необходимо авторизоваться.