10. СОЗДАНИЕ  ПРИЛОЖЕНИЙ В СРЕДЕ C++ BUILDER.

РАБОТА С КОМПОНЕНТАМИ БИБЛИОТЕКИ VCL

 

Цель этого подраздела состоит в том, чтобы научить читателя разрабатывать прикладные программы (приложения) в среде Windows, используя язык программирования С++, библиотеку визуальных компонентов Visual Component Lybrary VCL и среду программирования C++ Builder.

В подразделе рассмотрена иерархия классов библиотеки VCL, изложены вопросы обеспечения работы приложения без сбоев, приведено большое количество примеров разработки приложений, использующих различные компоненты библиотеки VCL. Большинство примеров программ являются достаточно короткими, так как они предназначены для демонстрации излагаемого материала.

Для понимания изложенного материала читатель должен быть знаком с языком программирования С++ и основами объектно-ориентированного программирования.

 

10.1. Иерархия классов VCL

 

Библиотека VCL построена на основе принципа наследования и образует иерархию классов. Основу библиотеки VCL составляют классы, представляющие компоненты (рис. 10.1). Каждый объект представляет некоторый набор методов, событий и свойств и имеет специальное назначение.

Базовым классом для всех порождаемых классов является класс TObject. Он инкапсулирует общее для всех объектов системы C++ Builder функциональное поведение, обусловленное методами, которые обеспечивают выполнение следующих действий:

– способность конструктора создавать, а деструктора разрушать объект-экземпляр класса в динамической памяти. Конструктор TObject возвращает указатель на создаваемый объект;

– представление информации об имени, типе производного объекта и его свойствах, которые объявлены как _published;

– поддержку обработки сообщений

Большинство этих методов предназначены для внутреннего использования средой C++ Builder, поэтому не следует обращаться к ним непосредственно из программы. Часть методов класса TObject объявлены как статические (с ключевым словом static). Это означает, что вам не нужно создавать экземпляр данного класса для того, чтобы обратиться к его статическим методам.

Класс TPersistent непосредственно произведен от класса TObject. Этот абстрактный класс не определяет никаких специальных свойств или событий, однако его производные приобретают особые способности присваивания и поточности.

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

Assign позволяет присваивать значения свойствам;

AssignTo позволяет присваивать содержимое одного объекта другому (например, как это делает производный от TPersistent класс TClipboard);

DefineProperties позволяет определить процедуру загрузки и сохранения в потоке особых дополнительных свойств. По умолчанию сохраняются только свойства, объявленные как _published.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Рис. 10.1. Иерархия ключевых базовых классов библиотеки VCL

 

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

– перенос на форму из палитры компонентов и манипуляции в окне редактора форм;

– способность владения и обслуживания других компонентов;

– специальные характеристики поточности, с которыми может манипулировать инспектор объектов на этапе проектирования;

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

Невизуальные компоненты произведены от класса TComponent. Графические компоненты, не ассоциированные с оконными элементами управления, произведены от класса TGraphicControl.

Общие для видимых компонент члены данных, методы и события определяет класс TControl.

 

 

Таким образом, программист создает законченное приложение посредством интерактивного взаимодействия с интегрированной визуальной средой C++Builder, используя компоненты VCL для создания интерфейса программы с пользователем. Все компоненты являются прямыми или косвенными потомками одного общего класса-прародителя TComponent.

Знание классов библиотеки VCL необходимо программисту как для успешного использования этой библиотеки  при разработке приложений, так и для создания собственных компонент.

Ниже более подробно рассмотрены многие классы и компоненты библиотеки VCL, а также приведены примеры их применения.

 

10.2. Обеспечение бессбойной работы приложений

 

Среда программирования C++ Builder предусматривает специальные механизмы для обработки исключений (ошибок), которые могут возникнуть при использовании библиотеки VCL. C++ Builder также поддерживает обработку исключений самой операционной системы и модель завершения работы приложения. Если исключение не будет перехвачено нигде в программе, то оно обрабатывается методом Application – >HandleException, который обеспечивает стандартную реакцию программы на большинство исключений и выдачу пользователю краткой информации в окне сообщений об аварийном завершении приложения.

Некоторые наиболее часто встречающиеся классы исключений системы C++ Builder приведены в табл. 10.1.

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

1. В меню Tolls / Debugger Otions перейти на страницу Language Exception.

2. На странице Language Exception выключить опции Stop on Delphi Exception и Stop on C++ Exception.

 

Таблица 10.1.

Классы исключений системы C++ Bulder

 

Имя класса

Причина возникновения исключительной ситуации

EDivByZero

Попытка целочисленного деления на нуль

EIntOverflow

Переполнение при целочисленных операциях

EZeroDivide

Деление на нуль

EOverflow

Переполнение в операциях с плавающей запятой

EOutOfMemory

Не хватает места при динамическом распределении памяти

EConvertError

Ошибки преобразования, возникающие при вызове функций StrToInt, StrToFloat

 

 

 

Таким образом, среда C++ Builder предоставляет в распоряжение программиста классы библиотеки VCL, поддерживающие обработку исключительных ситуаций. В процессе отладки приложения могут появляться мешающие работе сообщения отладчика среды C++ Builder, однако их можно отключить.

Примеры программ, в которых предусмотрена обработка исключений, будут представлены ниже в пп.10.3.1 и 10.3.2.

 

10.3. Обработка событий в компонентах

 

Управление процессами  в прикладных программах  производится с помощью создания обработчиков событий.

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

Для того чтобы написать обработчик события какого-то компонента, нужно выделить этот компонент на форме и в окне инспектора объектов перейти на страницу событий. В списке событий следует найти требуемое и сделать двойной щелчок в окне, правее имени события, при этом будет открыто окно редактора кода,  в котором уже будет занесена заготовка обработчика. В заготовке следует записать код функции – обработчика события.

Практически во все обработчики событий передается параметр Tobject  *Sender – указатель на объект класса TОbject. Sender является указателем на тот компонент, который воспринял происшедшее событие. Если нужно написать обработчик только для одного события, то параметр Sender не нужен, поскольку источник события известен. Более подробно о параметре Sender будет рассказано в пп. 10.3.2.

 

2.3.1. Компонент окна редактирования Edit

Компонент окна редактирования Edit позволяет выполнять отображение, ввод и редактирование однострочных текстов. Его пиктограмма  находится на странице Standart библиотеки VCL. Основное свойство этого компонента – Text, имеющее тип AnsiString. Если в этот компонент требуется занести число, то следует использовать функции  StrToFloat() или StrToInt(), преобразующие символьное изображение числа в его значение типа вещественного или целого числа.

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

1. Откройте новое приложение, выполнив для этого команду File| New Application. Перенесите на форму со страницы библиотеки Standart  два окна редактирования Edit, одну панель Panel, одну кнопку Button и три метки Label для надписей. Разместите все это примерно так, как показано на рис.10.2. Выровняйте компоненты, чтобы они располагались в горизонтальном направлении по центру окна

2. Измените надписи в метках (свойство Caption), например, на Число 1, Число 2, Результат. Полезно задать для меток жирный шрифт.

3. Замените свойство Caption вашей кнопки, например, на Расчет. Очистите свойство Caption у панели. В свойстве Тeхt (текст) окон редактирования задайте 1 для окна Edit1 и 2 для окна Edit2 – это начальное значение текста.

4. Попробуйте установить такие свойства панели, как BevelInner и BevelOuter, которые определяют вид (утопленный – byLowered или выпуклый – byRaised) основного поля и рамки панели. Например, можете установить BevelInner = byLowered и BevelOuter = byRaised.

Пример кода функции – обработчика щелчка по кнопке приведен в листинге 10.3. В этом листинге вывод результата – числа вещественного типа выполняется в компонент Panel. Текст, отображаемый в этом компоненте, определяется его свойством Caption, имеющим тип AnsiString. Для вывода числовой информации в свойство Caption  следует использовать функции FloatToStr и IntToStr, переводящие соответственно вещественные и целые числа в строку.

 

                                   Label1                          Edit1                        Label2

 


Button1

 

Edit2

 

Panel1

 

Label3

 
 

 

Рис. 10.2. Приложение в процессе проектирования

 

Листинг 10.3. Код функции – обработчика щелчка по кнопке Button1

 

void __fastcall TForm1 :: Button1Click(TObject  *Sender)

{

float a, b, c;

 

// контроль преобразования строки, введенной в окно редактирования

// Edit1, в  вещественное число

   try

  {

  a = StrToFloat(Edit1 –> Text);

  }

// если в процессе преобразования строки из окна Edit1 в число возникла ошибка

  catch (EСonvertError  &)

  {

// вывод сообщения об ошибке

   Application –> MessageBox ("Вы ввели ошибочное первое число", "Повторите ввод", MB_OK);

  Edit1 –> Text = "";  // очистка окна редактирования Edit1

  return;   // возврат из функции

}

 

// контроль преобразования строки, введенной в окно редактирования

// Edit2, в  вещественное число

  try

  {

  b = StrToFloat(Edit2 –> Text);

  }

 

// если в процессе преобразования строки из окна Edit2 в число возникла ошибка

  catch (EconvertError &)

  {

  Application –> MessageBox ("Вы ввели ошибочное второе число", "Повторите ввод", MB_OK);

    Edit2 –> Text = "";   // очистка окна редактирования Edit2

  return ;

}

// контроль выполнения операции деления

  try

  {

    a / b;

    }

// если была предпринята попытка деления на нуль

    catch(EZeroDivide &)

    {

    Application –> MessageBox ("На нуль делить нельзя!", "Повторите ввод второго числа", MB_OK);

     Edit2 –> Text = "";

     return;

     }

     c = a / b;

// вывод результата в панель

Panel1 –> Caption = Edit1 –> Text + "/" + Edit2 –> Text + " = " + FloatToStr(c);

Edit1 –> Text = ""; 

Edit2 –> Text = "";

}

 

Если пользователь ввел неверное число (например, по ошибке нажал не цифру, а какой-то буквенный символ), то при выполнении функции StrToFloat возникнет исключение класса EСonvertError. Соответствующий обработчик исключения сообщит пользователю о сделанной ошибке и посоветует повторить ввод. Аналогичная реакция возникает при вводе пользователем в качестве делителя нуля (класс исключения EZeroDivide).

Сделаем интерфейс нашего приложения более удобным и наглядным для пользователя. Для этого снабдим его компоненты ярлычками с подсказками, которые будут всплывать, если пользователь задержит курсор мыши над компонентом. Для задания текстов этих ярлычков служит свойство Нint, имеющееся почти у всех визуальных компонентов. Выделите например, на своей форме компонент Еdit1, и вы увидите это свойство в окне инспектора объектов. Напишите в нем краткое пояснение назначения компонента, например, Первое число. Это и будет текстом ярлычка. Но для того чтобы этот ярлычок всплывал при задержке курсора мыши над компонентом, нужно еще установить свойство ShowHint – показ ярлычка в true. Проделайте аналогичную операцию с другим окном редактирования, с панелью и кнопкой, помещая в них в свойство Hint соответствующие пояснения. Запустите приложение, и вы увидите, как всплывают ярлычки, когда пользователь задерживает курсор мыши над соответствующим компонентом.

 

10.3.2. Распознавание источника события (параметр Sender)

Параметр Sender типа TObject передается во все обработчики событий. Этот параметр содержит указатель на компонент, в котором произошло событие. Он не нужен, если пишется обработчик события для одного конкретного компонента. Однако часто один обработчик применяется для нескольких компонентов. Тогда параметр Sender можно использовать для распознавания источника события. Однако поскольку тип TОbject не имеет никаких полезных для пользователя свойств и методов, то объект Sender следует  рассматривать как объект одного из производных от TОbject типов.

Если требуется распознавать только тип объекта, то можно использовать функцию ClassNameIs. Например, оператор:

 

if   (Sender –> ClassNameIs (“TlistBox”))

 

проверяет, не является ли источник события компонентом типа TlistBox.

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

 

if   (((TСomponent   *)Sender –> Name   == “Edit1”)

проверяет,  является ли этот компонент компонентом с именем Edit.

 

Если надо только проверить, является ли Sender определенным компонентом, то можно поступить проще:

 

if   (Sender   == Edit1)

 

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

 

Листинг 10.4. Использование параметра Sender для распознавания источника события

#include <vcl.h>

#pragma hdrstop

 

#include "Ucalk.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

float x, y, z;  // глобальные переменные

 

//---------------------------------------------------------------------------

__fastcall TForm1 :: TForm1(Tcomponent *Owner) : TForm(Owner) {      }

 

// обработка события OnClick – нажатия любой кнопки на окне приложения

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Button1Click(TObject *Sender)

{

   try

  {

x = StrToFloat(Edit1 –> Text);

  }

 

  catch (EConvertError&)

  {

  Application –> MessageBox ("Вы ввели ошибочное первое число", "Повторите ввод", MB_OK);

  return;

}

 

  try

  {

 y = StrToFloat(Edit2 –> Text);

  }

 

  catch (EConvertError&)

  {

  Application  –>  MessageBox ("Вы ввели ошибочное второе число", "Повторите ввод", MB_OK);

  return;

}

 

//распознавание источника события

   if(Sender == Button1)

   {

   z = x + y;

  }

     if(Sender== Button2)

   {   

z=x – y;  

  }

 

      if(Sender == Button3)

   {

   z = x * y;  

}

 

      if(Sender == Button4)

   {

    try

             {

                x / y;

              }

 

    catch (EZeroDivide&)

  {

  Application –> MessageBox ("На нуль делить нельзя", "Повторите ввод", MB_OK);

  return;

}

 

  z = x / y;

    }

  Panel1 –> Caption = FloatToStr(z);

}

//---------------------------------------------------------------------------

 

2.3.3. Радиокнопки (компоненты RadioButton и GroupBox)

 

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

Работу с радиокнопками рассмотрим на примере разработки приложения, выполняющего перезагрузку или завершение работы Windows в зависимости от выбора пользователя (рис. 2.3.)

Для разработки приложения выполните следующие шаги:

1. Откройте новое приложение, выполнив для этого команду File | New Application. Перенесите на форму со страницы библиотеки Standart  панель GroupBox. Эта панель сама по себе пуста. Она предназначена служить контейнером для других управляющих элементов, в частности, радиокнопок RadioButton. Перенесите на форму две радиокнопки RadioButton  и две кнопки Button. С помощью радиокнопок пользователь будет делать выбор, а с помощью кнопок – подтверждать свои действия. Разместите  компоненты так, как показано на рис. 10.3.

2. Измените свойства Cарtion радиокнопок на надпись, которая должна появиться справа от радиокнопок в окне, а свойства Cарtion кнопок – на текст надписи на них.

3. Установите для первой радиокнопки свойство Checked равным true. Это означает, что первая радиокнопка в начале выполнения приложения будет выбрана по умолчанию. Следует заметить, что свойство Checked может быть установлено в значение true  только для одной радиокнопки из группы.

4. Запишите коды для обработчиков событий – щелчков по радиокнопкам и по кнопкам.  При нажатии радиокнопки свойство компонента Checked меняется на противоположное и возникает событие OnClick.


 

Рис.10.3. Вид окна приложения для завершения работы Windows

 

Коды функций – обработчиков событий приведены в листинге 10.5. Для перезагрузки операционной системы использована функция Windows API ExitWindowsEx, первый из параметров которой определяет способ завершения работы Windows.

 

Листинг 10.5. Коды функций – обработчиков событий приложения для перезагрузки или завершения работы Windows.

 

// переменная,  объявленная программистом и хранящая

// индекс нажатой радиокнопки: 0 – для первой, 1 – для второй

int Radio;

 

// обработка события OnClick – нажатия кнопки Отмена

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Button2Click(TObject  *Sender)

{

// функция, закрывающая окно приложения – выход из приложения

Close();   

}

 

// обработка события OnClick – нажатия кнопки ДА

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Button1Click(TObject *Sender)

{

// выбор действия, в зависимости от того, какая радиокнопка была нажата

switch (Radio)

{

case 0:   // была нажата первая радиокнопка – Выключить компьютер

// вызов функции API для завершения работы Windows

ExitWindowsEx(EWX_SHUTDOWN,0);

break;

 

case 1:      // была нажата вторая радиокнопка – Перезагрузить компьютер

//вызов функции API для перезагрузки Windows

 ExitWindowsEx(EWX_REBOOT, 0 );

break; 

 }

 }

 

// обработка события OnClick – нажатия первой радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton1Click(TObject *Sender)

{

  Radio = 0;

 }

// обработка события OnClick – нажатия второй радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton2Click(TObject *Sender)

{

 Radio = 1;

 }

//---------------------------------------------------------------------------

 

10.3.4. Таймер (компонент Timer)

 

Таймер в Windows является устройством ввода информации, которое периодически извещает приложение о том, что истек заданный интервал времени. Программа задает интервал, с которым Windows периодически посылает приложению сообщение  WM_TIMER.

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

Таймер – невизуальный компонент, который может размещаться в любом месте формы. Он имеет два свойства, позволяющие им управлять: Interval – интервал времени в миллисекундах и Enabled – доступность. Свойство Interval задает период срабатывания таймера. Через заданный интервал времени после предыдущего срабатывания, или после программной установки свойства Interval, или после запуска приложения, если значение Interval установлено во время проектирования, таймер срабатывает, вызывая событие OnTimer.

Если задать Interval = 0 или Enabled = false, то таймер перестает работает работать. Чтобы запустить отсчет времени нужно задать Enabled = true, если установлено положительное значение свойства Interval. Таймер точно выдерживает заданные интервалы Interval, если они достаточно велики – сотни и тысячи миллисекунд. А если задавать интервалы длительностью десятки или единицы миллисекунд, то реальные интервалы времени оказываются заметно больше вследствие различных накладных расходов, связанных с вызовами функций.

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

Для разработки приложения выполните следующие действия:

1. Откройте новое приложение, выполнив команду File | New Application. Занесите заголовок окна приложения: Использование таймера для движения строки в свойство Caption формы. Свойству ClientHeigt (высота окна приложения) формы присвойте значение 288, а свойству ClientWidth (ширина окна приложения) – значение 449. Свойство BorderStyle формы установите равным bsDialog, чтобы запретить пользователю изменять размеры окна в процессе работы приложения.

2. Перенесите на форму со страницы System библиотеки визуальных компонентов компонент Timer. Установите свойство Interval таймера равным значению 500 мс (0,5 с). Перенесите на форму со страницы библиотеки Standart  компонент Edit и две панели GroupBox. Перенесите на левую панель четыре радиокнопки RadioButton, на правую –  две обычные кнопки Button.

3. Для окна редактирования в свойстве Font задайте шрифт – Tahoma, начертание – полужирный наклонный, размер – 24, цвет – черный. Очистите свойство Тeхt (текст) окна  редактирования.

4. Измените свойства Cарtion панелей, радиокнопок и кнопок  на соответствующие надписи, как показано на рис.2.4. Установите свойство Font радиокнопок, задавая цвет шрифта их надписей: для первой – красный, для второй – зеленый, для третьей – синий, для четвертой – черный.

5. Установите свойство Checked для четвертой радиокнопки в значение true. Это означает, что четвертая радиокнопка в начале выполнения приложения будет выбрана по умолчанию.

6. Запишите коды для обработчиков событий: события срабатывания таймера OnTimer, событий OnClick  щелчков по радиокнопкам и по кнопкам. В обработчике события OnTimer перемещение строки имитируется циклическим сдвигом влево на 1 символ (вращением) содержимого свойства Text окна редактирования Edit. Обычные кнопки регулируют с дискретностью 0,1 с частоту обновления строки и, следовательно, видимую скорость ее движения. Коды функций – обработчиков событий приведены в листинге 10.6.

7. Откомпилируйте и запустите разработанное приложение. Сохраните файлы проекта.

 


Рис. 10.4. Форма в приложения в процессе проектирования

 

Листинг 10.6. Коды функций –обработчиков событий приложения, выводящего на экран бегущую строку

 

// реакция на выбор первой радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton1Click(TObject *Sender)

{

TRadioButton *rbutton = (TRadioButton*) Sender;

// задание цвета в окне редактирования равным цвету шрифта радиокнопки

Edit1 –> Font->Color = rbutton –> Font –> Color;

}

 

// реакция на выбор второй радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton2Click(TObject *Sender)

{

TRadioButton *rbutton = (TRadioButton*) Sender;

Edit1 –> Font –> Color = rbutton  –> Font –> Color;   

}

// реакция на выбор третьей радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton3Click(TObject *Sender)

{

TRadioButton *rbutton =(TRadioButton*) Sender;

Edit1 –> Font –> Color = rbutton –> Font –> Color;

}

// реакция на выбор четвертой радиокнопки

//---------------------------------------------------------------------------

void __fastcall TForm1 :: RadioButton4Click(TObject *Sender)

{

TRadioButton *rbutton = (TRadioButton*) Sender;

Edit1 –> Font –> Color = rbutton  –> Font –> Color;   

}

 

// обработка события таймера – истечения заданного интервала времени

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Timer1Timer(TObject *Sender)

{

// буфер, содержащий строку для вывода в окне

static char str[] =" Покрась меня ...            ";

// очистка  окна редактирования

Edit1 –> Clear();

// вывод в окно редактирования текста из буфера str

Edit1 –> Text = str;

//присваивание переменной first значения первого символа для вывода

char first = str[0];

//организация циклического сдвига строки на один символ влево

for(int i = 0; i < 27; i++)

str[i] = str[i + 1];

str[27] = first;

}

 

// реакция на нажатие кнопки Быстрее

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Button2Click(TObject *Sender)

{

if(Timer1 –> Interval <= 100)               return;

       Timer1 –> Interval – = 100; //уменьшить интервал срабатывания таймера

}

 

// реакция на нажатие кнопки Медленнее

//---------------------------------------------------------------------------

void __fastcall TForm1 :: Button1Click(TObject *Sender)

{

if(Timer1 –> Interval –> 2000)     return;

   Timer1 –> Interval + = 100; //увеличить интервал срабатывания таймера

}

//---------------------------------------------------------------------------

 

10.3.5. Компоненты выбора из списков

 

Списки являются динамическими структурами данных, размер которых может сокращаться или увеличиваться в процессе работы программы. Запоминание объектов в списках – типичный прием программирования. Например, программа рисования может хранить список нарисованных объектов, а игровая программа – список игроков с наибольшим рейтингом и параметры текущего состояния игры с тем, чтобы ее можно было продолжить. Среда С++ Builder предоставляет такие списочные компоненты, как TListBox, TComboBox  и др. Все списки библиотеки VCL можно считать контейнерными классами, они решают проблемы по динамическому распределению памяти под данные. При использовании списков размер контейнера автоматически меняется, реагируя на добавление или удаление своих элементов.

Разработаем приложение для работы со списком. Откройте новый проект и разместите на форме компоненты ListBox, Button и Edit, как показано на рис. 10.5.

 

 

Рис.10.5. Форма приложения во время проектирования

 

Основное свойство компонента ListBoxItems, имеющее тип TStrings (список строк). Во время выполнения программы можно работать с этим свойством, пользуясь свойствами и методами этого класса, например Clear (очистить список), Add (добавить строку в конец списка), AddStrings (добавить группу строк в список). Производный от класса TStrings класс TStringList  добавляет следующие свойства:

Sorted (выполнить сортировку строк списка);

Duplicates (запретить хранение дубликатов строк);

Текст файла реализации модуля для работы со списком приведен в листинге 10.7.

 

Листинг 10.7. Текст файла реализации модуля для работы со списком

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

 

// создание объекта MyList производного от TStrings класса TStringList

TStringList  *MyList = new TStringList;

 

//---------------------------------------------------------------------------

// определение конструктора формы

__fastcall TForm1 :: TForm1(TComponent* Owner  : TForm(Owner)

{

 // добавить элемент к концу списка

  MyList –> Add("Информатика");

  MyList –> Add("Физика");

   MyList –> Add("Математика");

// игнорировать дубликаты

   MyList –> Duplicates = dupIgnore;

// сортировать список

   MyList –> Sorted = true;

// добавить к концу списка группу строк и отобразить их

  ListBox1 –> Items –> AddStrings (MyList);

}

 

//---------------------------------------------------------------------------

// обработчик щелчка по кнопке Добавить

void __fastcall TForm1 :: Button1Click(TObject *Sender)

{

if(Edit1 –> Text ! = "")   // если строка в окне редактирования не пустая

    {

 MyList –> Add(Edit1 –> Text);  // добавить строку к списку

ListBox1 –> Clear();   // очистить список

 ListBox1 –> Items –> AddStrings(MyList);  // отобразить список

     }

}

 

// обработчик события OnClose,  возникающего при закрытии формы

//---------------------------------------------------------------------------

void __fastcall TForm1 :: FormClose(TObject *Sender,

TCloseAction & Action)

{ 

delete MyList;             // уничтожить объект

ShowMessage("Список класса TStringList уничтожен");   

}

//---------------------------------------------------------------------------

 

Строки списка можно читать из файла и сохранять в файле. Для этого следует использовать методы LoadFromFile и SaveToFile класса TStrings. Для демонстрации работы с этими методами внесем изменения в разработанное нами приложение. Добавим на форму приложения вторую кнопку, назвав ее, например, Сохранить. Для компонента ListBox1 установите свойство Sorted в true, чтобы список выводился в отсортированном виде. Определения функций – обработчиков событий в файле реализации модуля приведены в листинге 10.8.

 

Листинг 10.8. Определения функций – обработчиков событий

// создание обекта MyList производного от TStrings класса TStringList

TStringList  *MyList = new TStringList;

 

// конструктор формы

//---------------------------------------------------------------------------

__fastcall TForm1 :: TForm1(Tcomponent *Owner) : TForm(Owner)

{

 // считать из файла строки и отобразить их в списке ListBox1

   ListBox1 –> Items –> LoadFromFile("names.txt");

}

 

//---------------------------------------------------------------------------

// обработчик щелчка по кнопке Добавить

void __fastcall TForm1 :: Button1Click(TObject *Sender)

{   

if(Edit1 –> Text ! = "")     // если в окно редактирования введен текст

   {  // добавить строку из окна редактирования в список  MyList

MyList –> Add(Edit1 –> Text);

 ListBox1 –> Clear();   // очистить список

// добавить строку из списка MyList в список  ListBox1

 ListBox1 –> Items –> AddStrings(MyList);

    }

}

 

//---------------------------------------------------------------------------

// обработчик события OnClose для формы

void __fastcall TForm1 :: FormClose(TObject *Sender, TCloseAction &Action)

{   // освободить память,

delete MyList;

ShowMessage("Список класса TStringList уничтожен");

}

 

//---------------------------------------------------------------------------

// обработчик щелчка по кнопке Сохранить

void __fastcall TForm1 :: Button2Click(TObject *Sender)

{  

 // сохранить список в файле

ListBox1 –> Items –> SaveToFile("names.txt");

}

//---------------------------------------------------------------------------

 

 

Таким образом, проектирование приложений в среде C++ Builder сводится практически к размещению компонентов на форме, заданию их свойств и написанию обработчиков событий. С каждым компонентом библиотеки VCL связан определенный набор событий, на которые он может реагировать. Каждому событию соответствует своя функция – обработчик этого события. Список всех функций – обработчиков событий можно увидеть на вкладке Events окна инспектора объектов. Во время проектирования формы и размещения на ней компонентов среда C++ Builder автоматически генерирует коды программы, включая в нее соответствующие фрагменты, описывающие компоненты и заголовки функций – обработчиков событий.

Для отображения текста на форме могут использоваться такие компоненты, как Label и  Panel. Ввод и одновременное редактирование информации позволяет выполнять компонент Edit, а задавать в приложении интервалы времени можно с помощью компонента Timer. Для работы с такой динамической структурой данных, как список следует использовать компонент ListBox. 

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

 

10.4. Разработка интерфейса пользователя

 

Разрабатываемое приложение не должно выбиваться из общего стиля Windows ни общим видом, ни способом взаимодействия с ним.  Для пользователя большим преимуществом является то, что большинство приложений выглядят и ведут себя сходным образом.

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

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

 

10.4.1. Прикрепление меню

Меню – это наиболее распространенный элемент управления в Windows. Все главные окна приложений  имеют связанные с ними меню. В  среде С++ Builder для создания меню используется специальный редактор, обладающий следующими возможностями:

– создание как главного, так и контекстных меню;

– обеспечение оперативного доступ к редактору кода для обработки событий OnClick,  соответствующих пунктам меню;

– вставка меню из шаблонов или файлов ресурсов;

– сохранение пользовательских меню в виде шаблонов.

Работу с редактором меню рассмотрим на примерах разработки приложений для просмотра текстовых файлов и многооконного текстового редактора.

Откройте новое приложение и перенесите на форму компонент МаinМеnu (главное меню) со страницы Standart (вторая пиктограмма слева). В результате откроется окно, вид которого представлен на рис. 2.6. В этом окне вы можете спроектировать свое меню.

Компонент МаinМеnu потребуется нам, чтобы создать в приложении меню, являющееся обязательным атрибутом любого приложения Windows. В нашем приложении мы хотим создать всего одно выпадающее меню Файл с двумя разделами Открыть и Сохранить, которые соответственно открывают файл текстового документа и сохраняют его на диске после редактирования.

 

 

Рис. 2.6. Форма с помещенным на нее компонентом MainMenu

 

Компонент МаinМеnu – невизуальный, т. е. место его размещения на форме в процессе проектирования не имеет никакого значения для пользователя, который все равно увидит не сам компонент, а только меню, сгенерированное им.

Основное свойство компонента МаinМеnu Items. Его заполнение производится с помощью редактора меню (рис.10.7), вызываемого двойным щелчком на компоненте МаinМеnu или нажатием кнопки с многоточием рядом со свойством Items в окне инспектора объектов.

При работе в окне редактора меню новые разделы можно вводить, помещая курсор в рамку из точек, обозначающую место расположения нового раздела. Если при этом раздел ввелся не там, где вам было нужно, вы можете отбуксировать его мышью туда, куда вам надо. Другой путь ввода нового раздела – это использование контекстного меню, всплывающего при щелчке правой кнопкой мыши. Если вы предварительно выделите какой-то раздел меню и выберете из контекстного меню команду Insert, то рамка нового раздела вставится перед ранее выделенным разделом.

При выборе нового раздела вы увидите в окне инспектора объектов множество свойств данного раздела. Дело в том, что каждый раздел меню (каждый элемент свойства Items) является объектом типа TMenuItem, обладающим своими свойствами, методами, событиями. Рассмотрим их.


 

Рис. 10.7. Окно редактора меню

 

Свойство Name задает имя объекта, соответствующего разделу меню. Основное свойство раздела – Caption обозначает надпись раздела. В надписях можно предусматривать использование клавиш ускоренного доступа к разделу меню, выделяя для этого один из символов надписи. Перед символом, который должен соответствовать клавише ускоренного доступа, ставится символ амперсанда (&). Этот символ не появляется в надписи, но следующий за ним символ оказывается подчеркнутым. Тогда пользователь вместо выбора меню может нажать клавишу Аlt совместно с клавишей выделенного символа. Если меню раскрылось, то клавишей Аlt и соответствующим символом можно выбрать раздел меню.

Свойство ShortCut определяет клавиши быстрого доступа к разделу меню – клавиши, с помощью которых пользователь, даже не заходя в меню, может в любой момент вызвать выполнение процедуры, связанной с данным разделом. Чтобы определить клавиши быстрого доступа, следует открыть выпадающий список свойства ShortCut в окне инспектора объектов и выбрать из него нужную комбинацию клавиш.

Выполните проектирование меню. Сделайте двойной щелчок на компоненте МainМеnu вашего приложения, выделите мышью пунктирную рамку, перейдите в окно инспектора объектов и в свойстве Caption напишите &Файл. В окне конструктора меню появится надпись Файл (см. рис. 10.7). Щелкните на этой надписи. Ниже нее появится пунктирная рамка, в которую вы аналогичным образом введете надпись второго раздела Открыть... (многоточие после имени раздела говорит пользователю, что будет открыто диалоговое окно). Введите и третий раздел меню –Сохранить как.... Задайте для этого раздела «горячие» клавиши например, F2. В окне конструктора меню рядом с соответствующим разделом, как показано на рис. 10.7, появится указание на эту клавишу. В заключение закройте окно конструктора меню его системной кнопкой. Вверху формы вашего приложения возникнет надпись спроектированного вами меню. Присвойте свойству Caption формы приложения значение Просмотр и редактирование текстов.

Разместите на форме окно редактирования RichEdit (рис. 10.8) со страницы библиотеки Win32 (четвертая пиктограмма слева). Это многострочное окно редактирования, позволяющее работать как с текстовыми файлами в формате АSСII, так и с текстовыми файлами в обогащенном формате RTF.

 

 

Рис.10.8. Форма с размещенным на ней окном редактирования RichEdit

 

Желательно, чтобы окно RichEdit занимало всю площадь формы, причем не только в процессе проектирования, но и при изменении пользователем в процессе работы размеров окна приложения. Для этой цели  следует использовать свойство Allign (выравнивание). По умолчанию оно равно alNone. Это означает, что выравнивание не осуществляется. Свойство Align можно задать равным аlТор или аlВоttоn, или аlLeft или allRight, это значит, что компонент должен занимать всю верхнюю, или нижнюю, или левую, или правую часть клиентской области компонента-контейнера. Под клиентской областью понимается вся свободная площадь формы или другого контейнера, в которой могут размещаться включенные в этот контейнер компоненты. Можно также задать свойству компонента Align значение аlClient, что приводит к заполнению компонентом всей свободной клиентской области. Во всех этих случаях размеры компонента будут автоматически изменяться при изменении размеров контейнера. В нашем случае окно редактирования должно занимать всю площадь формы. Поэтому задайте для него значение Align равным аlClient и окно немедленно закроет всю вашу форму, кроме заголовка меню.

Основное свойство компонента RichEdit – Lines (строки текста). Нажмите кнопку с многоточием в строке Lines окна RichEdit, и вам откроется окно редактирования списков строк. Вы можете редактировать или вводить текст непосредственно в этом окне или нажать кнопку СоdeEditor и работать в обычном окне редактора кода. В этом случае, завершив работу с текстом, выберите из контекстного меню, всплывающего при щелчке правой кнопкой мыши, команду Сlоsе Раgе и ответьте утвердительно на вопрос, хотите ли вы сохранить текст в соответствующем свойстве окна редактирования. В нашем примере в окне ничего записывать не нужно. Наоборот, в этом окне надо стереть текст RichEdit1 занесенное в него имя компонента.

Теперь нам требуется предоставить пользователю стандартные диалоги Windows для открытия текстового файла и его сохранения под заданным именем. Для этого перенесите на форму компоненты ОреnDialog (диалог Открыть файл) и SaveDialog (диалог Сохранить файл). Эти компоненты, как и другие диалоги, расположены в библиотеке VCL на странице Dialogs. Компоненты ОреnDialog и SaveDialog невизуальные, их можно размещать в любом месте формы (рис. 10.9).

 


Рис.10.9. Форма приложения в процессе проектирования

 

Компоненты ОреnDialog и SaveDialog инкапсулируют стандартные диалоги Windows. Среди множества свойств этих компонентов следует задать только свойство Filter, определяющее типы файлов, появляющиеся в диалоге в выпадающем списке. Это свойство проще всего задать с помощью редактора фильтров, который вызывается нажатием кнопки с многоточием около имени свойства Filter в окне инспектора объектов. При этом открывается окно редактора фильтров Filter Editor (рис. 10.10).

Вызов любого диалога осуществляется методом Ехесutе. Этот метод возвращает значение true (истина), если пользователь, работая с диалогом, произвел необходимый выбор. Если же пользователь в диалоге нажал кнопку Отмена или клавишу Еsс, то возвращается значение false (ложь). Имя выбранного пользователем файла возвращается значением свойства FileName диалогов ОреnDialog и SaveDialog.

Напишем код, соответствующий разделу Открыть нашего меню. Откройте на форме спроектированное меню Файл и выберите его раздел Открыть. Вы попадете в окно редактора кода на текст

 

void_fastcall Tform1 : :  N2Click (TObject *Sender)

     {            

  }

 

В левой панели Filter Name следует записать тот текст, который увидит пользователь в выпадающем списке Тип файлов диалога.

В правой  панели Filter записываются разделенные точками с запятой шаблоны фильтра. В нашем примере имеет смысл задать два фильтра: текстовых файлов с расширениями .rtf и .txt и любых файлов с шаблоном *.*.

 
 


 

Рис. 10.10. Окно редактора фильтров

компонентов OpenDialog и SaveDialog

 
 

 

 

 


Это заготовка обработчика щелчка на данном разделе. Занесите в него между фигурными скобками оператор

 

if (OpenDialog1 –> Execute())

         RichEdit1 –> Lines –> LoadFromFile(OpenDialogl –> FileName);

 

Этот оператор вызывает метод Ехесute компонента ОреnDialog1, анализирует результат, и если результат равен true (пользователь выбрал файл), то в строки Lines окна редактирования RichEdit1 методом LoadFromFile с помощью оператора ОреnDialog1 –> FileName заносится содержимое файла, выбранного пользователем.

В обработчик щелчка пользователя в разделе Сохранить как необходимо занести оператор

 

 if (SaveDialog1 –> Execute ())

           RichEdit1 –> Lines –> SaveToFile(SaveDialog1 –> FileName);

 

Дайте имя форме (свойство Name), отличное от имени по умолчанию, например имя FDoc. Это нужно делать тогда, когда вы намереваетесь использовать форму в своих будущих проектах (форма FDoc используется в проекте, создание которого описано ниже в п. 10.4). Модуль формы сохраните с именем UDoc. Выполните приложение (приготовьте для этого текст в формате RTF) и поработайте с ним. Вы можете увидеть, что в вашем окне редактирования автоматически реализованы многие функции, свойственные текстовым редакторам: выделение слова при двойном щелчке мыши, возможность перемещения выделенного фрагмента текста в другое место файла, «горячие» клавиши Ctrl-C (копировать выделение в буфер обмена Clipboard), Ctrl-X (вырезать в Clipboard), Ctrl-V (копировать из Clipboard), Ctrl-Z (отменить последнюю операцию редактирования). Приложение вызывает стандартные диалоги Windows открытия и сохранения файлов.

 

10.4.2. Создание панели инструментов

Большинство современных приложений Windows имеют панели инструментов. Создание панели инструментов выполняется поэтапно: вначале создается контейнер панели инструментов на форме приложения, а затем выполняется заполнение панели необходимыми кнопками. Создадим панель инструментов для приложения, выполняющего просмотр текстовых файлов, процесс разработки которого был описан в п. 10.4.1.

Для создания контейнера панели инструментов на форме выполните следующие шаги:

1. Скопируйте файлы проекта в другую папку (нужно копировать только файлы *.dfm, *.bpr, *.cpp, *.h).

2. Откройте файл проекта приложения для просмотра текстовых файлов.

3. Выберите компонент Panel из палитры компонентов и поместите его на форму в любом месте.

4. Измените значение свойства Name панели на ToolBar.

5. Установите значение свойства Height равным 32.

6. Сотрите значение свойства Caption.

7. Измените значение свойства Allign на alTop. Панель инструментов переместится наверх.

Для размещения кнопок на панели инструментов сделайте  следующие шаги:

1. Щелкните на вкладке Additional палитры компонентов и выберите компонент SpeedButton (кнопка быстрого доступа) и поместите ее на панель, не беспокоясь о точном размещении.

2. Измените значение свойства Name компонента SpeedButton на FileOpenBtn.

3. Установите значение свойства Left равным 5.

4. Выберите в главном меню пункт View  |  Alignment Palette.  Щелкните на кнопке Center Vertically in Window.

5. Найдите свойство Glyph, щелкните в столбце, в результате откроется окно редактора изображений.

6. Нажмите кнопку Load. На экране появится диалоговое окно Load picture. Перейдите в подкаталог …\ Program Files \ Common Files \ Borland Shared \ Image \ Buttons и выберите файл fileopen.bmp. Нажмите кнопку OK.

7. Повторите последние шесть шагов, чтобы добавить кнопку  File Save. Поместите ее справа от кнопки File Open. Дайте ей имя FileSaveBtn  и используйте файл filesave.bmp для свойства Glyph.

В результате форма должна принять вид, показанный на рис.10.11.

 


Рис. 10.11. Форма с размещенной на ней панелью инструментов

 

Запишите коды обработчиков событий – щелчков на кнопках панели инструментов. Эти коды можно скопировать из функций – обработчиков щелчков по перечисленным выше пунктам меню. Откомпилируйте и запустите приложение на исполнение. Убедитесь, что с помощью кнопок панели инструментов действительно можно выполнить те же действия что и с помощью пунктов меню. Прикрепите всплывающие подсказки к кнопкам панели инструментов (как это сделать было показано в п. 10.3.1).

 

10.4.3. Многооконный текстовый редактор

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

Начните новый проект и назовите (свойство Name) его форму именем main. Это желательно сделать, поскольку в нашем проекте будет несколько форм и, назвав их непонятными именами, мы рискуем в них запутаться. Задайте окну формы (свойство Сарtion) заголовок Многооконный редактор. Сохраните проект сразу, дав сохраняемому модулю имя Umain, а проекту – имя РМDM. Осмысленные имена модулям полезно давать с той же целью: потом в проекте будет три модуля, а с их стандартными именами Unit1, Unit2, Unit3 мы рискуем запутаться, который из них к какой форме относится.

Перенесите на форму уже знакомый вам компонент МainMenu – главное меню (см. п. 10.4.1). Введите с его помощью меню Справка с единственным разделом О программе (рис. 10.12). Если пользователь выберет этот раздел, то ему должна быть показана форма, содержащая информацию о программе, поэтому нам нужно включить в проект еще одну форму.

 


Рис10.12. Начальный вариант главной формы приложения

 

Выполните команду File | New Form. В ваш проект включится новая форма. Дайте ей имя Аbout и заголовок О программе. Сохраните файл модуля этой формы (команда File | Save), дав ему имя UAbout. Эта форма будет содержать информацию о вашей программе. Размер формы имеет смысл значительно уменьшить, так как информационные окна обычно небольшие. Стиль формы (свойство BorderStyle) следует установить в bsDialog, так как пользователь не должен иметь возможность изменять ее размеры. Свойство формы Position установите в poScreenCenter,  чтобы форма появлялась в центре экрана.

Если вы решили украсить свою форму графикой, то перенесите на нее компонент Image. Установите его свойство AutoSize равным true, в результате этого размер компонента Image будет автоматически подстраиваться под размер загруженного в него изображения.

Основное свойство компонента ImagePicture. В это свойство можно загрузить любой графический файл. Для загрузки можно сделать двойной щелчок на компоненте Image или нажать кнопку с многоточием около свойства Picture в окне инспектора объектов. Вы попадете в окно загрузки изображения, но сначала оно будет пустым. Нажмите кнопку Load и в открывшемся окне выберите интересующий вас файл. Со средой С++ Builder поставляется много файлов изображений, помещенных в подкаталоги каталога Program Files \ Common Files \ Borland Shared \ Images. Щелкните на кнопке ОК, и изображение загрузится в компонент Image. Измените размеры изображения на форме так, чтобы оно занимало примерно половину окна формы и установите свойство AutoSize компонента Image в значение false. Это послужит запретом для дальнейших изменений размеров изображения в окне About. Теперь в другой половине окна можно разместить любой текст. В результате форма может выглядеть например, так, как показано на рис. 10.13, где изображена загрузка файла пиктограммы Program Files \ Common Files \ Borland Shared \ Images \ Splasht \ 16 color \ skyline.bmp.

 

Для размещения текста в окне About используйте  компонент Memo, для чего щелкните на вкладке Standart палитры компонентов и выберите компонент Memo. Поместите его справа от изображения на форме.

 

 

 

        Рис.10.13. Пример формы с информацией

                            о программе

 

Для размещения и форматирования текста в компоненте Memo выполните следующие действия:

1. Измените значение свойства Name на Memo.

2. Дважды щелкните в столбце Value рядом со свойством Lines. Откроется окно редактора строк (String List Editor). Введите в это окно текст.

3. Установите значение свойства Alignment равным ta Center. Текст надписи будет выровнен по центру внутри компонента Memo.

4. Установите значение свойства Enabled равным false для того, чтобы его было невозможно изменить в процессе работы приложения.

5. Установите значение свойства Color равным ClbtnFace, задайте размер шрифта 12 пунктов, начертание – полужирный.

6. Сохраните результаты проектирования этой формы.

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

По умолчанию главной становится форма, которая была создана в проекте первой, поэтому в нашем проекте главная форма main. Но если бы мы начали проект с создания формы About, то именно она стала бы главной.

В среде  С++ Builder имеется инструмент, который позволяет управлять формами и, в частности, задавать главную из числа форм, имеющихся в проекте. Выполните команду Project | Options и в открывшемся окне опций проекта перейдите на страницу Forms. В верхнем выпадающем списке Main forms вы можете выбрать главную форму среди имеющихся в проекте. Пользуясь двумя нижними окнами, можно установить, какие формы должны создаваться автоматически, а какие не должны. Например, если нужно исключить форму FDoc из списка автоматически создаваемых, то следует выделить ее в левом окне (Аuto-creat forms) и с помощью кнопки со стрелкой, направленной вправо, переместить в правое окно доступных форм (Availabel forms).

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

Теперь нам осталось только написать оператор, который делает форму Аbout видимой при выборе пользователем раздела О программе. Перейдите в своем проекте на форму main, раскройте меню, щелкните на разделе О программе и в открывшуюся в окне редактора кода заготовку обработчика этого щелчка внесите оператор

 

Аbout –> Show();

 

Этот оператор с помощью метода Show делает форму Аbout видимой. Если вы попробуете откомпилировать программу, то вам будет выдано замечание undefined symbol About. Дело в том, что форма Аbout недоступна из модуля Umain. Чтобы модуль UАbout, содержащий форму Аbout, стал доступен из модуля Umain, в модуль Umain следует внести директиву препроцессора

 

#include “UAbout.h”

 

Это можно сделать вручную, а можно, находясь в окне редактора кода в модуле Umain, выполнить команду File | Include Unit Hdr и в открывшемся окне выбрать из списка в нижней части окна модуль UAbout. Тогда указанная выше директива include занесется в текст автоматически.

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

Превратим наше приложение в многооконный редактор текстов – так называемое приложение МDI – это приложение с множеством документов типа Word, Excel и т. п. В приложении МDI имеется родительская (первичная) форма и ряд дочерних форм (называемых также формами документов). Окна документов могут создаваться самим пользователем в процессе выполнения приложения с помощью команд типа Окно, Новое. Число дочерних окон заранее неизвестно, так как пользователь может создать их столько, сколько ему потребуется. Окна документов располагаются в клиентской области родительской формы. Чтобы там было больше места для документов, по умолчанию родительскую форму часто делают развернутой на весь экран. Для этого ее свойство WindowState нужно установить в wsMaximized.

В нашем примере родительской будет форма main, а в качестве окна документов воспользуемся формой текстового редактора, разработанной вами ранее в п. 10.4.1.

Скопируйте из папки, в которой находится проект, созданный в

п. 10.4.1 файл UDoc.cpp (в нем хранится код модуля формы текстового редактора), файл формы UDoc.dfm и заголовочный файл UDoc.h.  Выполните команду Project | Add to Project или нажмите соответствующую быструю кнопку и выберите в открывшемся окне файл Udoc.cpp, в котором хранится модуль вашей формы текстового редактора. Сошлитесь так же, как вы делали это выше с помощью директивы include в модуле Umain, на модуль UDoc, содержащий форму UDoc. Задайте для формы Main, как было указано выше, WindowState = wsMaximized.

Теперь в нашем приложении уже три формы. При этом форма FDoc не должна создаваться автоматически. Поэтому с помощью страницы Forms окна опций проекта перенесите форму FDoc из списка автоматически создаваемых в список доступных.

Нам нужно указать, что наша форма main – родительская, а формы FDoc – дочерние. Для этого в окне инспектора объектов задайте свойство FormStyle формы main равным fsMDIForm (родительская), а аналогичное свойство формы FDocfsMDIChild (дочерняя).

Поскольку из родительской формы необходимо управлять дочерними окнами, меню формы main следует пополнить еще одним меню –Окно с разделами Новое, Каскад, Упорядочить по горизонтали, Упорядочить по вертикали, Упорядочить значки (рис. 10.14). Сделайте это с помощью  компонента MainMenu. Поскольку у нас теперь много разделов меню и с их именами по умолчанию мы далее можем запутаться, то назовите объекты каждого раздела более осмысленно. Для этого выделите поочередно каждый раздел меню в окне конструктора меню и в окне инспектора объектов задайте им соответственно имена MNew, MCascade, MHor, MVert, MPict. На эти имена мы и будем ссылаться при дальнейшем изложении.


 

Рис.10.14. Главная форма приложения – окончательный вариант.

 

В приложениях MDI меню окна документа автоматически объединяется с меню родительской формы. В нашем случае в дочерней форме имеется меню Файл, которое должно встраиваться в меню родительской формы, причем, как это принято во всех приложениях Windows, меню Файл должно быть первым. Последовательность встраивания определяется свойствами GroupIndex разделов меню. До сих пор это свойство во всех разделах было равно нулю. Но при объединении меню это недопустимо, поскольку последовательность встраивания одного меню в другое определяется именно этим свойством. Следовательно, оставив это свойство равным нулю в меню Файл, надо с помощью конструктора меню просмотреть все разделы меню Окно и Справка и задать для меню Окно и его разделов свойство GroupIndex равным 1, а для меню Справка и его раздела равным 2. Тогда объединение меню будет происходить без особых проблем.

Нам осталось написать обработчики для разделов меню Окно. Для раздела MNew (Новое) обработчик приведен в листинге 10.8.

Листинг 10.8. Код обработчика для раздела Новое меню Окно

void _fastcall Tmain :: MNewClick(TObject *Sender)

{ / * объявление указателя ТF на создаваемый объект формы ТFDoc и создание нового объекта формы * /

TFDoc *TF = new TFDoc(Application) ;

// возврат из функции, если объект не удалось создать

 if (! TF)    return;

// формирование уникального заголовка нового окна

TF –> Caption = "Окно " + IntToStr(MDIChildCount);

// отобразить вновь созданное окно

TF –> Show();

}

 

В приведенный текст внесены комментарии, поясняющие каждый оператор. Первый оператор объявляет локальную (временную) переменную TF как указатель на объект класса TFDoc – это класс формы FDoc. Этот же оператор создает операцией new новый объект формы документа. Следующий оператор проверяет, создался ли объект, и если не создался, то он обеспечивает выход из обработчика оператором return. Третий оператор задает заголовок окна нового документа, формируя его из слова Окно и порядкового номера дочернего окна. Этот номер определяется свойством родительской формы MDIChildCount. Его не следует искать в окне инспектора объектов, так как это свойство времени выполнения, т. е. оно доступно только во время выполнения и автоматически возрастает при создании каждого нового дочернего объекта. Последний оператор при помощи метода Show отображает окно созданного документа на экране.

Тексты остальных обработчиков щелчков на разделах меню Окно приведены в листинге 10.9.

 

Листинг 10.9. Коды обработчиков щелчков на разделах меню Окно

//---------------------------------------------------------------------------

// упорядочивание окон каскадом (пункт меню Каскад)

void _fastcall Tmain :: MHorClick(TObject *Sender)

{   Cascade(); }

 

//---------------------------------------------------------------------------

// упорядочивание окон по горизонтали  (пункт меню

// Упорядочить по горизонтали)

void_fastcall Tmain :: MHorClick(TObject *Sender)

{   TileMode = tbHorizontal;

    Tile () ;

 }

 

//---------------------------------------------------------------------------

// упорядочивание окон по вертикали (пункт меню

// Упорядочить по вертикали)

void _fastcall Tmain :: MVertClick(TObject *Sender)

{

TileMode = tbVertical;

Tile();

}

 

//---------------------------------------------------------------------------

// упорядочивание пиктограмм свернутых окон

void_fastcall Tmain :: MPictClick(TObject *Sender)

{   ArrangeIcons ();  }

//---------------------------------------------------------------------------

 

Сохраните приложение и опробуйте его в работе. При запуске приложения в нем не будет ни одного окна документа и будут видны только два меню: Окно и Справка. Выполнение команды Окно | Новое создаст окно документа. В этот момент вы увидите в полосе главного меню раздел Файл. В дальнейшем каждое выполнение команды Окно | Новое будет приводить к созданию следующего окна документа, в каждом из которых вы можете написать свой текст или загружать текстовые файлы.

 

10.4.4. Прикрепление к приложению формы–заставки

 

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

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

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

1. Создайте новую папку и дайте ей имя, например zastavka. Скопируйте в эту папку все файлы одного из созданных вами работающих проектов. Откройте проект, дважды щелкнув по файлу проекта.

2. Добавьте в приложение новую форму (File | New Form).  Это будет форма–заставка. Назовите ее Flog (свойство Name).  Уменьшите размеры формы- аставки. Установите следующие свойства:

BorderStyle     bsNone   (отсутствие полосы заголовка и кнопок);

Position   poScreenCenter  (форма будет появляться в центре экрана);

Visible  должно иметь значение false.

Разместите на форме–заставке компонент Memo и поместите в него текст заставки. Можно разместить на форме и рисунок (используя компонент Image).

3. Напишите следующие обработчики событий для формы-заставки, которые при любом действии закрывали бы форму:

– события onKeyDown (нажатие клавиши на клавиатуре) и onMouseDown (нажатие кнопки мыши) – обработчики должны содержать оператор Close();

– свойство KeyPreview  установите в значение true, чтобы форма перехватывала все связанные с нажатием клавиш события компонентов.

4. Сделайте так, чтобы и при отсутствии действий со стороны пользователя форма закрывалась сама, например, через 5 с. Для этого добавим на форму компонент Timer со страницы System. Зададайте значение свойства  Interval равным 5 000. В обработчике события таймера OnTimer напишите единственный оператор Close().

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

 

Action  = caFree;

 

6. Cохраните проект, дав имя модулю формы-заставки UFlog.  Выполните для модуля  главной формы приложения команду File | Include Unit Hdr  и укажите в диалоге имя включаемого модуля UFLog.

7. Для главной формы приложения напишите обработчик события формы OnShow

 

FLog -> ShowModal();

 

Событие OnShow наступает до того, как форма действительно станет видимой. Во время обработки этого события главная форма еще не видна. Оператор открывает форму  FLog как модальную, передает ей управление, и дальнейшее выполнение программы в главном модуле останавливается до тех пор, пока модальная форма не будет закрыта.

В заключение откомпилируйте и запустите приложение.

 

10.4.5. Прикрепление к приложению формы–пароля

 

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

1. Откройте существующий проект. Добавьте новую форму. Назовите ее FPSW (свойство Name), сохраните ее модуль под именем UPSW. Уменьшите размеры формы. Установите следующие свойства:

 

BorderStyle     bsNone   (отсутствие полосы заголовка и кнопок);

Position  poScreenCenter (форма будет появляться в центре экрана).

 

В свойстве Caption напишите Введите пароль и нажмите Enter.

2. В центре формы FPSW поместите окно редактирования Edit, в котором пользователь будет вводить пароль. Очистите его свойства Text, а в свойство PasswordChar внесите символ *, тогда символы вводимого пользователем в окно Edit пароля будет отображаться в виде звездочек, что повысит уровень защиты вашего приложения. В обработчике события OnKeyDown этого компонента запишите оператор

 

if(Key == VK_RETURN)   // если была нажата клавиша Enter

   Close(); // закрытие формы с запросом пароля

 

После нажатия пользователем клавиши Enter считается, что пользователь завершил ввод пароля и форма для ввода пароля должна быть закрыта. При закрытии формы наступает целая последовательность событий, которые можно обрабатывать. Первым возникает событие onCloseQuery. В его обработчик передается по ссылке булева переменная CanClose, определяющая, должно ли продолжаться закрытие формы. По умолчанию значение CanClose равно true, что означает продолжение закрытия. Если форму закрывать не нужно, то параметру CanClose должно быть присвоено значение false. Тогда последующих событий, связанных с закрытием формы, не будет.

Если обработчик события onCloseQuery отсутствует или если в его обработчике сохранено значение true для CanClose, то затем наступает событие OnClose.

3. В событие  onClose формы FPSW  вставьте оператор

 

if(Edit1 –> Text == "qwerty")

ModalResult = 6;

 

Этот оператор сличает введенный текст с паролем. Если введен правильный пароль (qwerty), то свойству ModalResult  присваивается некоторое условное число, например 6. Можно присвоить и  любое другое число, кроме 0 или 2.

4. Выполните для модуля  главной формы приложения команду File | Include Unit Hdr  и укажите в диалоге имя включаемого модуля UPSW. В обработчике события OnShow  после других операторов добавьте операторы

 

if(FPSW –> ShowModal() ! =6 )

{    ShowMessage ("Ваш пароль неверный");

// закрытие главной формы приложения (т. е. всего приложения)

 Close();   

}

else

   {  

 ShowMessage ("Ваш пароль верный");

   delete FPSW;

 }

10.4.6. Многостраничные панели

 

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

Откройте новый проект и разместите на форме компонент PageControl со страницы Win32. Этот компонент отображает стопку страниц с частично перекрывающими друг друга вкладками. Щелкните на форме правой кнопкой мыши на компоненте PageControl и во всплывшем меню выберите команду NewPage (создать новую страницу). Каждая создаваемая страница  является объектом типа TTabSheet. Это панель, на которой можно размещать любые управляющие компоненты. Увеличьте мышью размеры страницы примерно так, как показано на рис. 10.15.

В свойство Caption панели занесите надпись Телефоны. Аналогично создайте еще три страницы и введите надписи, которые будут появляться на ярлычках закладок.

 

 

 

Рис. 10.15. Форма с размещенным на ней с компонентом Page Control

 

Выделите страницу с названием  E-mail моих знакомых. Разместите на этой странице компоненты RichEdit, Memo, Edit, два компонента Label  и кнопку Button (рис.10.16). Занесите текст в метки, удалите текст из компонентов RichEdit, Memo и Edit.

В обработчик OnCick щелчка на кнопке занесите код, приведенный в листинге 10.10.

 

 

 

 

Рис. 10.16. Приложение с выделенной страницей E-mail моих знакомых

 

Листинг 10.10. Обработчик щелчка по кнопке OK на странице E-mail моих знакомых

 

// переменная для сохранения ответа пользователя ввести пароль повторно

int  btn; 

AnsiString pass = "123-456-789"; // строка, содержащая пароль

// строка, считанная из окна редактирования

AnsiString type = Edit1->Text.c_str();

Edit1 –> Clear();           // очистка окна редактирования для ввода пароля

Edit1 –> SetFocus();     // передача фокуса ввода в окно редактирования

  if ( type ! = pass )        //если считанная в строка не соответствует паролю

{

// вывод стандартного диалогового окна Windows с запросом о повторе ввода

btn = Application –> MessageBox("Неверный пароль! Повторить?", "Ввод пароля", MB_YESNO);

// если отказ от ввода пароля идет повторно, то

// активизировать следующую страницу

    if (btn == IDNO)

{

PageControl1->SelectNextPage(true);

return;

 }

    if (btn == IDYES)

return; // подтверждение желания ввести пароль повторно

  }

 

//введен правильный пароль 

 try    // контроль ошибок открытия файла

  {   

  RichEdit1 –> Lines –> LoadFromFile("Pages.rtf"); 

   }

  catch (...)

  {

    Application –> MessageBox("Ошибка чтения файла PAGES.RTF", NULL, MB_OK);

  }

// поместить информацию на секретную страницу

  RichEdit1 –> Lines –> Append("1. Lewis A. 

WordWeb@netword.demon.co.uk");

  RichEdit1 –> Lines –> Append("2. Roache J.  johnroache@aol.com");

  RichEdit1 –> Lines- –> Append("3. Лозинский Д.  loz@dials.msk.su");

  RichEdit1 –> Lines –> Append("4. Данилов И.  id@sald.spb.su");

  RichEdit1 –> Lines –> Append("5. Шамис В.   vshamis@ass.iki.rssi.ru");

 

Выделите страницу с названием Календарь Разместите на этой странице компоненты CCalendar со страницы Samples и  метку Label.

В обработчик события OnChange (событие наступает сразу после переключения на страницу)  для компонента Page Control занесите код, который позволит поместить в метку Label текст, содержащий название дня, месяца и года:

 

Label3 –> Caption = "Сегодня" + FormatDateTime ("dddd mmmm,yyyy", CCalendar1 –> CalendarDate);

 

В обработчик события OnCreate формы вставьте код, позволяющий активизировать страницу c номером 3:

 

PageControl1 –> ActivePage = TabSheet3;

 

 

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

MainMenu, позволяющий создавать строку меню с разделами главного меню и раскрывающимся списком команд;

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

PageControl, предоставляющий возможность выполнить перелистывание страниц на главной форме.

Помимо перечисленных выше элементов, интерфейс приложения может включать в себя контекстные меню, полосу состояния, файл справки и др. Для получения информации по их применению можно воспользоваться литературой [10],[11].

 

2.5. Запуск внешних программ и создание дочерних процессов

 

В ряде случаев программисту может понадобиться запускать из своей программы другие программы. Это могут быть стандартные архиваторы, калькуляторы, текстовые, графические редакторы, программы, ранее разработанные для среды DOS, которые представлены только своим исполняемым модулем. Запуск одной программы из другой называется порождением дочернего процесса.

Запуск внешней программы в среде C++ Builder можно сделать с помощью нескольких функций API Windows, примеры применения которых приведены ниже

1. С помощью функции WinExec():

  запуск программы Пасьянс

 

WinExec("sol.exe",SW_RESTORE);

 

  запуск стандартной программы Блокнот

 

WinExec("notepad.exe",SW_RESTORE);

 

запуск собственной программы

WinExec("C:\\bcb6_user\\calculator\\Project2.exe", SW_RESTORE);

 

Параметр SW_RESTORE означает, что окно запускаемого приложения активизируется и отображается на экране.

2.С помощью функции ShellExecute():

– запуск стандартной программы Блокнот

 

ShellExecute(Handle, "open", "notepad.exe", NULL, NULL, SW_RESTORE);

 

запуск собственной программы

 

ShellExecute(Handle, "open", "C: \\ bcb6_user \\ calculator \\ Project2.exe", NULL, NULL, SW_RESTORE);

 

Здесь Handleдескриптор родительского окна (32-разрядное целое), open – выполняемая операция (открыть запускаемое приложение).

3. С помощью функции CreateProcess(). Эта функция является более современной, чем  функция WinExec. Функция CreateProcess рекомендуется для 32 разрядных приложений. В программе, использующей эту функцию, следует выполнить объявления:

 

// структура, определяющая основное окно дочернего процесса

STARTUPINFO StartInfo = {sizeof(TStartupInfo)};

PROCESS_INFORMATION   ProcInfo;

LPCTSTR s;

StartInfo.cb = sizeof(StartInfo);

StartInfo.dwFlags = STARTF_USESHOWWINDOW;

StartInfo. WShowWindow = SW_SHOWNORMAL;

 

Приведем пример применения функции CreateProcess для запуска собственного приложения:

 

CreateProcess(NULL, "C: \\ bcb5_user \\ calculator \\ Project2.exe", NULL, NULL, false, HIGH_PRIORITY_CLASS, NULL, NULL, &StartInfo, &ProcInfo);

 

 

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

 

Контрольные вопросы и задания

 

1. Назовите основные классы библиотеки VCL и поясните их назначение.

3. Какие классы предусмотрены в среде С++ Builder для обработки исключительных ситуаций?

4. Как отключить сообщения об исключениях, выводимые отладчиком среды С++ Builder?

5. Каким образом происходит обработка событий в компонентах библиотеки VCL?

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

7. Какой компонент можно использовать для ввода и отображения текстовой информации?

8. Какие функции предназначены для преобразования текстовой информации в число и обратного преобразования? Какие исключительные ситуации могут возникнуть в процессе этих преобразований?

9. Разработайте приложение, содержащее компоненты, позволяющие выполнять ввод и отображение текстовой информации (см. п. 2.3.1).

10. Какие возможности можно представить пользователю, если в приложении использованы радиокнопки?

11. Какие структуры данных в языке С++ называют динамическими? Назовите компонент среды С++ Builder, поддерживающий работу с такой динамической структурой, как список.

12. Разработайте приложение, в котором для представления данных используется список (см. п. 2.3.5).

13. Какие компоненты библиотеки VCL предназначены для загрузки стандартных диалогов открытия и сохранения файлов?

14. Каким образом прикрепить к компонентам окна всплывающие подсказки?

15. Каким образом можно прикрепить меню к окну приложения?

16. Как задать «горячие клавиши» при проектировании пунктов меню?

17. Для чего предназначена  панель инструментов? Как выполнить ее создание?

18. Как можно установить высоту и ширину окна в процессе проектирования приложения?

19. В каких случаях в приложении следует использовать компонент Timer? Перечислите свойства и события, связанные с этим компонентом.

20. Разработайте приложение, выводящее на экран бегущую строку (см. п. 2.3.4).

21. Как добавить к приложению новую форму?

22. Какой стиль должен быть задан для формы, содержащей информацию о программе?

23. Разработайте приложение для просмотра текстовых файлов, содержащее меню и панель инструментов (см. п. 2.4.1 и п. 2.4.2).

24. Какой компонент следует использовать для загрузки в него  изображений?

25. Как в приложении с несколькими формами задать главную форму? Как получить информацию о том, сколько форм имеется в приложении?

26. Какие значения свойства FormStyle должны быть у родительской и дочерних форм?

27. Как выполнить объединение меню родительской и дочерней форм?

28. Разработайте приложение выполняющее функции многооконного текстового редактора (см. п. 2.4.3).

29. Какая форма называется модальной?

30. Каковы особенности работы с модальной формой?  Как сделать видимой модальную форму?

31. Какой компонент позволяет разместить на одном месте страницы разного содержания?

32. Какой процесс называется дочерним? Назовите функции для создания дочерних процессов.

 

Упражнения

 

1. Напишите программу, выполняющую изменение цвета фона окна через каждую секунду. Например:  красный, желтый, зеленый (clRed, clYellow, clGreen).

2. Напишите программу – простейший калькулятор для выполнения арифметических действий сложения, вычитания, умножения и деления. Пример окна программы показан на рис.10.17.

 

Предусмотрите в программе обработку  следующих ошибок:

·        попытку выполнения деления на 0 (это ошибка класса EzeroDivide);

·        неправильный ввод данных в окна редактирования.

 

 

 

 


.

 

 

 

 

 

 

 

 

 

 

      Рис.10.17. Окно программы–калькулятора

 

3. Напишите программу–тест, позволяющую контролировать, правильно ли пользователь умеет выполнять сложение целых чисел. Вид формы приложения  показан на рис.10.18.

Программа должна удовлетворять следующим требованиям:

·                    она должна предлагать пользователю выполнить сложение двузначных чисел, выбранных случайным образом;

·               пользователь не должен иметь возможности изменять предлагаемые ему числа.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Рис.10.18. Форма приложения «Сложение целых чисел»

 

Кроме того, время работы программы должно быть ограниченным например 30 с,  а по окончании тестирования пользователь должен получить информацию о результатах тестирования:  оценку отлично, если он не сделал ни одной ошибки; оценку хорошо, если ошибок не более 5; оценку удовлетворительно, если сделано не более 10 ошибок; оценку неудовлетворительно в других случаях.

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

 

Указание.  На форме следует разместить компонент Image. Установите свойство AutoSize этого компонента в значение true. Для открытия и сохранения графических файлов следует использовать компоненты OpenPictureDialog  и  SavePictureDialog. Для тестирования приложения можно использовать файлы, расположенные в папке Program Files \ Common Files \ Borland Shared.

 

Программа должна удовлетворять следующим требованиям:

–по сигналу от таймера кнопка должна менять положение в окне;

– пользователь должен иметь возможность управлять скоростью перемещения кнопки по окну;

– если пользователь поймал кнопку, щелкнув по ней мышью, кнопка должна перестать прыгать и стать недоступной, а в заголовок окна должна быть выведена строка Игра окончена.

 
5. Напишите программу, содержащую «прыгающую кнопку». Форма приложения приведена на рис.10.19.

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 10.19. Форма приложения

          «Прыгающая кнопка»

 

6. Разработайте приложение с компонентом PageControl (см. п.10.4.6) и внесите в него следующие изменения:

cоздайте с помощью стандартной программы Блокнот текстовый файл с нужными вам телефонами. В одной строке файла – одна запись, например:  Горгаз – 22–33–44. Сохраните файл в той же папке, в которой вы создали приложение;

– выделите страницу Телефоны. Разместите на ней компоненты RichEdit и Button. Добавьте в приложение код, позволяющий отображать на странице Телефоны при переключении на нее содержимое созданного вами файла, а при нажатии на кнопку – сохранять файл с изменениями, которые пользователь внесет в свою записную книжку;

– выделите страницу Календарь. Разместите на этой странице компоненты CCalendar со страницы Samples и  метку Label. В обработчик события OnChange (событие наступает сразу после переключения на страницу) для компонента Page Control занесите код, который позволит поместить в метку Label текст, содержащий название дня, месяца и года:

 

Label –> Caption = "Сегодня" + FormatDateTime ("dddd mmmm, yyyy", CCalendar1 –> CalendarDate);

Добавьте страницу О программе, в которую поместите информацию о версии программного продукта, авторских правах.

 

7. Напишите программу-игру «Угадай число». Программа запоминает в в целочисленной переменной случайное число и предлагает пользователю его угадать. Игра заканчивается, если пользователь угадал число. Примерный вид окна программы показан на рис. 10.20.

Требования к программе:

·                 Вывод номера попытки угадать число;

·                 Сообщение пользователю о результатах попытки, напримерМое число меньше

·                 Мое число больше

·                 Вы угадали

·                 Наличие меню с возможностями начать игру заново или выйти из программы

Добавьте в меню пункт О программе

 

 

Рис. 20.Примерный вид окна программы «Угадай число»

 

8. Напишите программу, содержащую два выпадающих меню:

– меню, содержащее пункты для запуска игр, входящих в состав стандартных программWindows, например Пасьянс, Сапер;

– меню, содержащее пункты для запуска приложений, созданных вами ранее, например приложения, выводящего рисунок, приложения, выводящего часы.

9. Используя материал, изложенный в п.п. 10.4.5 и 10.4.6, добавьте к любому из разработанных вами приложений форму–заставку и форму для ввода пароля. Измените код, позволяющий вводить пароль так, чтобы пользователю предоставлялось три попытки для ввода правильного пароля, после чего приложение должно закрываться, если пароль был введен неверно.

Хостинг от uCoz