Шаг 24.
Visual Prolog.
Добавление элементов управления в окно часов

    На этом шаге мы рассмотрим добавление элементов управления в окно часов.

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

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

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

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


Рис.1. Добавление элементов управления к окну Clock

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

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


Рис.2. Окно Clock с добавленными элементами управления

    Если вы теперь попытаетесь запустить приложение и откроете окно 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,rct(45,91,165,116),"Show Date",
       Win,[wsf_Group,wsf_TabStop,wsf_Auto],idc_show_date)

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


Рис.3. Добавление функциональности в элементы управления

    Чтобы добавить предложение для каждого элемента управления, используем кнопку 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:

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

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

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


    Замечание: Чтобы изменить текст, мы обращаемся к идентификатору кнопки Start (_CtrlWin), а не к дескриптору окна 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(_UpdateRct),0):-
      _CtrlWin=win_GetCtlHandle(_Win,idc_show_date),
       IsChecked=win_IsChecked(_CtrlWin),
       IsChecked=checkbox_on,
       !,
      win_Clear(_Win,color_LtGray), 
      RCT=win_GetClientRect(_Win), 
      time(Hours,Minutes,Seconds,_),
      date(Year,Month,Day),
      format(Str, "%/%/% - %:%:%",Year,Month,Day,Hours,Minutes,Seconds), 
      draw_TextInRect(_Win, RCT, Str, -1,
                   [dtext_center,dtext_vcenter,dtext_singleline]),
	!.
   win_clock_eh(_Win,e_Update(_),0):-!,
	win_Clear(_Win,color_LtGray),
	RCT=win_GetClientRect(_Win),
	time(Hours,Minutes,Seconds,_),
	format(Str,"%:%:%",Hours,Minutes,Seconds),
	draw_TextInRect(_Win, RCT, Str, -1,
                                     [dtext_center,dtext_vcenter,dtext_singleline]),
	!.	

    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.

    Результат работы приложения изображен на рисунке 4:


Рис.4. Результат работы приложения

    Созданное приложение можно взять здесь (452,9 Кб).

    На следующем шаге мы рассмотрим использование списка.




Предыдущий шаг Содержание Следующий шаг