Шаг 25.
Visual Prolog.
Использование списка

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

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

    Для управления списками имеется несколько предикатов VPI, имена которых начинаются с префикса lbox_.

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


Рис. 1. Полное окно каталогов

    Как обычно, при подготовке кода для окна Directory Browser выполните следующие шаги:

  1. Создайте новый исходный модуль Dirlist.pro.
  2. Добавьте пункт Directory List в меню Task подменю Test.
  3. Создайте новое окно Directory.
  4. Установите атрибут Maximized.
  5. Обратитесь к эксперту окон и диалоговых окон и добавьте код по умолчанию для окна Directory в модуль Dirlist.pro.
  6. Затем добавьте предложение для окна Task, которое при выборе команды Test | Directory List будет активизировать окно Directory.
  7. Запустите программу и проверьте, создается ли окно при активизации Test | Directory List.

    Теперь зайдите в редактор окна и поместите список в окно Directory. Позиция и размер не имеют значения, поскольку мы изменим размеры управляющего элемента списка так, чтобы он соответствовал окну (рис. 2).


Рис. 2. Добавление списка в окно

    Когда вы добавите список, убедитесь, что изменили заданный по умолчанию идентификатор на idc_listbox. Затем нужно нажать на кнопку Control Flags. Для элементов управления имеется большое количество опций (рис. 3). Пока пропустите все, что вам незнакомо.


Рис. 3. Выбор управляющих флажков для списка

    Так как мы хотим добавить табуляцию, разделяющую строки в нашем списке, и иметь возможность устанавливать столбцы табуляции, отметим флажок UseTabStops. Опция MultiSelect позволяет выбирать более одного пункта в списке.

    Другая опция, которую вы можете изменить, - NoBorder, но мы раскроем список на все окно, поэтому граница не нужна.

Код для браузера каталогов

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

   include "iodecl.con" 
   domains
     stamp=s(integer Hour,integer Min,integer Sec,integer Year,
	     integer Month,integer Day,long Size);
          dir
   predicates
      nondeterm get_files(string Path,string FileName,stamp)
   clauses
      get_files (PATH, SUBDIR, dir):-
         concat(PATH,"*.*",PP), 
         dirfiles(PP,fa_subdir,SUBDIR,_,_,_,_,_,_,_,_),
         SUBDIR ><  ".".
      get_files(PATH,FName,s(Hour,Min,Sec,Year,Month,Day,Size)):-
         concat(PATH,"*.*",PP),
         dirfiles(PP,fa_normal,FName,_,Hour,Min,Sec,Year,Month,Day,Size).

    Затем мы создадим предикат, принимающий на вход идентификатор списка и путь (Path), который добавит имена файлов и подкаталогов в список. В этом предикате мы будем использовать два предиката VPI, которые работают со списками: предикат lbox_clear - удаляет все содержимое из списка и предикат lbox_add - добавляет строку на данную позицию в списке. Если позиция равна -1, то элемент будет добавлен в конец списка.

   predicates
      fill_lbox(window,string Path)
      fill_lbox(window,string FileName,stamp)
   clauses
      fill_lbox(Win,Path):-
         lbox_Clear(Win),
         get_files(Path,FName,STAMP),
         fill_lbox(Win,FName,STAMP),
         fail.
      fill_lbox(_Win,_Path).
      fill_lbox(Win,SubDir,dir):-
         format(Str,"%\t%",SubDir,"<dir>"),
         lbox_Add(Win, -1, Str). 
      fill_lbox(Win,FName,s(Hour,Min,Sec,Year,Month,Day,Size)):-
         format(Str,"%\t%8\t%2:%2:%2\t%4/%2/%2", 
              FName,Size,Hour,Min,Sec,Year,Month,Day),
         lbox_Add(Win,-1,Str).

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

    Для этой цели мы выделим каталог из строки этого элемента.

   predicates
      get_path(string Item,string Path,string Rest) 
   clauses
      get_path(Item,Path,Rest):-
         searchchar(Item, '\t',Pos),
         Len=Pos-1,
         frontstr(Len,Item,Path,Rest).

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

    Завершим начатое. Вызовем предикат lbox_SetTabStops для того, чтобы установить позиции табуляции. Позиции табуляции определяются в базовых единицах Dialog Base Units.

    Далее изменим шрифт для списка (это делать необязательно). Если мы не хотим делать сложное форматирование, проще выбрать непропорциональный шрифт ff_fixed.

    Затем установим заголовок окна, показывающий путь к отображаемым файлам и подкаталогам (win_SetText), и заполним содержание списка (fill_lbox). Добавим код к предложению e_Create. Код должен быть добавлен после комментария %END DIRECTORY, ToolbarCreate:

   LBWIN=win_GetCtlHandle(_Win,idc_listbox),
   lbox_SetTabStops(LBWIN,[0,75,125,175,225]), 
   Font=font_Create(ff_Fixed,[],10),
   win_SetFont(LBWIN,Font),
   win_SetText(_Win,"C:\\"), 
   fill_lbox(LBWIN,"C:\\")

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

   win_directory_eh(_Win,e_Size(_Width,_Height),0):-!,
      LBWin=win_GetCtlHandle(_Win,idc_listbox), 
      win_Move(LBWin,rct(0,0,_Width,_Height))

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

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




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