Учебный центр "ANIT Texno Inform"
Опубликован: 25.06.2014 | Доступ: свободный | Студентов: 2595 / 850 | Длительность: 24:39:00
Специальности: Программист
Лекция 18:

Многооконные приложения. SDI- и MDI-интерфейсы

< Лекция 17 || Лекция 18: 12 || Лекция 19 >

Немодальные окна

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

Создайте новую форму командой "Файл -> Создать форму" или одноименной кнопкой на панели инструментов Lazarus. Форму (свойство Name) назовите fStats, а ее модуль сохраните под именем Stats. Далее, в свойстве Caption формы напишите "Статистика". Свойство BorderStyle установим в bsDialog, чтобы пользователь не мог менять размеры формы, а Position - в poMainFormCenter, чтобы окно появлялось по центру главного окна.

Теперь нам понадобятся шесть меток TLabel. Первые три установите в левой части формы, одну под другой. Эти метки мы переименовывать не будем, так как нам не придется обращаться к ним программно. В первой напишите "Строк:", во второй "Слов:" и в третьей "Символов:". Не забывайте ставить двоеточие после этих слов. Затем в правой части, так же одну под другой, установим еще три метки, их уже переименуем. В свойстве Name этих меток напишите, соответственно, LinesCount, WordsCount и CharsCount, а в свойстве Caption всех трех меток установите "0" (ноль).

В центре нижней части формы с вкладки Additional Палитры компонентов установите кнопку TBitBtn, в свойстве Kind которой выберите значение bkOK. В результате, у вас должна получиться примерно такая форма:

Форма fStats

Рис. 20.3. Форма fStats

Сгенерируйте следующее событие OnClick для кнопки "ОК":

procedure TfStats.BitBtn1Click(Sender: TObject);
begin
  Close;
end;
    

То есть, когда пользователь нажмет на эту кнопку, окно статистики закроется.

Далее перейдем в модуль главного окна fMain. Чтобы мы могли оттуда вызвать новое окно, нужно через запятую добавить его модуль Stats в конец раздела uses, как это мы делали с модулем About в прошлом примере. Сюда же добавьте еще два модуля: LCLProc и StrUtils. В первом реализованы UTF8-функции, одна из них нам понадобится для определения количества символов. Во втором реализовано множество полезных строковых функций, включая и ту, которая нам нужна для подсчета количества слов в тексте:

Присоединенные модули

увеличить изображение
Рис. 20.4. Присоединенные модули

Теперь подумаем, каким образом мы будем вызывать окно статистики. Лучше всего поместить вызов статистики в раздел меню "Файл". Дважды щелкните по MainMenu1, чтобы вызвать редактор меню. В разделе меню "Файл" выделите подраздел "Сохранить как…", щелкните по нему правой кнопкой и выберите команду "Вставить новый пункт (после)". В свойстве Name нового подпункта введите FileStat, а в свойстве Caption напишите "Статистика":

Новый подпункт в меню

Рис. 20.5. Новый подпункт в меню

Теперь закройте Редактор меню; выбрав команду "Файл -> Статистика" сгенерируйте событие OnClick для нового подпункта. Код события следующий:

procedure TfMain.FileStatClick(Sender: TObject);
begin
  fStats.Show;
end;
    

Как видите, здесь мы вызываем форму fStats, но не методом ShowModal, как в прошлом примере, а методом Show. В результате окно будет показано, как немодальное. Однако этого недостаточно, чтобы окно показывало статистику. Нам нужно еще подсчитать и вывести на экран количество строк, слов и символов.

Выделите компонент Memo1. В Инспекторе объектов перейдите на вкладку "События" и сгенерируйте для него событие OnChange, дважды щелкнув по нему. Это событие возникает всякий раз при изменении текста в Memo1, тут мы и будем считать статистику. Код события следующий:

procedure TfMain.Memo1Change(Sender: TObject);
begin
  //считаем символы:
  fStats.CharsCount.Caption:= IntToStr(UTF8Length(Memo1.Text));
  //слова:
  fStats.WordsCount.Caption:= IntToStr(WordCount(Memo1.Text, StdWordDelims));
  //строки:
  fStats.LinesCount.Caption:= IntToStr(Memo1.Lines.Count);
end;
    

Тут для нас много нового, так что разберем код подробней. Вначале функцией UTF8Length (см. "Стандартные строковые функции и сообщения" ) мы получили количество символов в тексте Memo1, включая служебные символы перехода на новую строку. Это - целое число, которое нам пришлось преобразовать в строковую форму с помощью функции IntToStr, чтобы мы могли присвоить эту строку свойству Caption метки CharsCount. Обратите внимание, что метка находится не на этой, а на другой форме, поэтому нам пришлось сначала указать имя этой формы, затем имя метки и уж потом свойство Caption.

Слова в тексте считать сложнее, для этого мы воспользовались новой для нас функцией WordCount. Функция описана в модуле StrUtils, который мы подключили, она возвращает количество слов в указанном тексте, и имеет следующий синтаксис:

function WordCount(const S: String; const WordDelims:TSysCharSet):integer;
    

Константа S содержит текст, в котором подсчитываются слова, в нашем случае, это Memo1.Text. Константа WordDelims содержит список символов-разделителей, которыми может отделяться одно слово от другого. Проще всего в этом параметре воспользоваться системной константой StdWordDelims, которая уже описана в том же модуле, и объявлена следующим образом:

const StdWordDelims = [#0..' ', ',', '.', ';', '/', '\', ':', '''', '"', '`'] + Brackets;
    

То есть, в этой константе перечислены основные символы-разделители слов. Функция возвращает целое число - количество слов в указанном тексте. Преобразовав его в символьную форму, мы присваиваем это значение свойству Caption метки WordsCount.

А вот количество строк даже считать не нужно, оно содержится в свойстве Memo1.Lines.Count. Нам остается лишь преобразовать его в символьную форму, и присвоить соответствующей метке. Теперь каждый раз, как в Memo1 изменится текст (пользователь ввел символ, скопировал текст в Memo или удалил текст), это событие будет пересчитывать количество слов, символов и строк, и выводить их в форму fStats, даже если ее не видно. Выбрав команду меню "Файл -> Статистика", пользователь сможет вывести окно статистики. Более того, он может, не закрывая этого окна, вернуться в главную форму и продолжать набирать текст. Окно статистики при этом будет параллельно отображать результаты:

Немодальное окно статистики в действии

Рис. 20.6. Немодальное окно статистики в действии

Сохраните проект, запустите его на выполнение и убедитесь, что окно статистики не мешает работе главного окна. Проект Блокнота-шифровальщика нам потребуется ещё в лекциях №№ "Создание справочной системы" и "Создание инсталлятора" , так что не удаляйте его.

MDI-приложения

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

  1. Вначале вы создаете главное, оно же родительское окно. Это окно будет служить своеобразным контейнером для дочерних окон, поэтому основная, рабочая часть главной формы должна быть свободной. В свойстве FormStyle (стиль формы) родительского окна следует выбрать значение fsMDIForm.
  2. Затем вы создаете дочернее окно. Во время работы программы дочернее окно будет создаваться внутри родительского, и не сможет покинуть его пределы. В свойстве FormStyle дочернего окна следует выбрать значение fsMDIChild.
  3. Форму дочернего окна мы конструируем только один раз, но в программе это окно можно вызывать сколько угодно много раз, открывая в нем разные документы. Все эти дочерние окна могут быть открыты одновременно.
  4. MDI-интерфейс приложения не запрещает вам создавать также модальные и немодальные окна. Например, в MDI-приложении вы с таким же успехом и таким же образом можете создать окно "О программе". Если вы будете создавать отдельные модальные и немодальные окна, то в свойстве FormStyle этих форм следует оставить значение по умолчанию fsNormal.

Для реализации MDI-интерфейса сами разработчики рекомендуют установить дополнительный компонент MultiDoc, который реализует псевдоMDI-интерфейс. Рассматривать работу с нестандартными компонентами мы не будем, желающих отсылаю на сайт разработчиков по адресу: http://wiki.freepascal.org/MultiDoc

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

< Лекция 17 || Лекция 18: 12 || Лекция 19 >
Инга Готфрид
Инга Готфрид
Александр Скрябнев
Александр Скрябнев

Через WMI, или используя утилиту wmic? А может есть еще какие более простые пути...