Методические указания для проведения практических и лабораторных занятий по дисциплине "Программирование на языке высокого уровня" для студентов специальностей 220200 Автоматизированные системы обработки информации и управления
Вид материала | Методические указания |
СодержаниеПривязка к родительским свойствам Класс TCanvas 3. Работа с компонентами Компонент TMenuItem |
- Рабочая программа по дисциплине Программирование на языке высокого уровня для специальности, 182.97kb.
- Соболева Наталья Владимировна методические указания, 73.26kb.
- Методические указания к проведению лабораторных работ. Специальность 23. 01. 02 «Автоматизированные, 1178.37kb.
- Рабочая программа По дисциплине «Системы искусственного интеллекта» для специальности, 86.74kb.
- Рабочая программа По дисциплине «Программирование на языке высокого уровня» По специальности, 280.81kb.
- Р. Е. Алексеева кафедра ису программирование на языке высокого уровня методические, 57.65kb.
- Рабочая программа по дисциплине «Алгоритмические языки и программирование» Для специальности, 208.45kb.
- Рабочая программа дисциплины «Объектно-ориентированное программирование» для специальности, 325.53kb.
- А. В. Яковлев Операционные системы и системное программирование Раздел Операционная, 1847.03kb.
- Рабочая программа дисциплины «Автоматизированные информационные системы» для специальности, 301.29kb.
Привязка к родительским свойствам
Для придания приложению строгого внешнего вида требуется, чтобы все визуальные компоненты имели единый стиль. Чтобы избавиться от необходимости изменять код элементов-потомков при изменении внешнего вида предка, в них нужно правильно установить свойства:
(pdi property ParentColor: boolean;
@ property ParentCtl3D: boolean;
(Pb) property ParentFont: boolean;
(pS) property ParentShowHint: boolean;
Все четыре свойства отвечают за наличие связи между соответствующими свойствами в родительских и дочерних элементах. Если какое-то из них у элемента установлено в True, это означает, что он наследует свойство от родителя и меняет цвет, трехмерность, шрифт или показ ярлычков вместе и вслед за ним. Но если само свойство дочернего элемента (например, Color или ParentColor) переустановить явно, то связь с родительским свойством разрьюается.
2.8. Графическая подсистема
Разработчики Delphi уделили большое внимание возможностям работы с деловой графикой: простота и удобство ее использования напрямую сказывается на простоте и удобстве созданных приложений. Вместо дебрей графического интерфейса Windows разработчик получил несколько инструментов, сколь понятных, столь же и мощных.
Другой бич работы с графикой в Windows — проблема рационального использования ресурсов. Для больших программных комплексов она стала в последнее время нешуточной (это касается, по крайней мере, версий Windows до 3.11 включительно). Такие монстры, как Microsoft Office, потребляют во время работы львиную долю ресурсов. В Delphi ресурсами GDI незримо для пользователя "заведуют" специальные менеджеры, ведущие списки всех размещенных кистей, перьев, шрифтов и т. п. и управляющие их использованием.
Обязательным для любого объекта, связанного с графикой в Delphi является событие
property OnChange: TNotifyEvent;
Его обработчик вызывается всякий раз, когда изменились какие-то характеристики объекта, влияющие на его внешний вид.
В стандартном GDI основой для рисования служит дескриптор контекста устройства hDC и связанные с ним шрифт, перо и кисть. В состав VCL входят объектно-ориентированные надстройки над последними, назначением которых является удобный доступ к свойствам инструментов и прозрачная для пользователя обработка всех их изменений. Сначала опишем три этих класса.
Класс TCanvas
TCanvas = class(TPersistent)
Этот класс — сердцевина графической подсистемы Delphi. Он объединяет в себе и "холст" (контекст конкретного устройства GDI), и "рабочие инструменты" (перо, кисть, шрифт) и даже "подмастерьев" (набор функций по рисованию типовых геометрических фигур).
В дальнейшем для обозначения этого класса мы будем пользоваться термином "канва". Сознавая неоднозначность такого перевода, авторы тем не менее считают, что у него наилучшие шансы прижиться.
Канва не является компонентом, но она входит в качестве свойства во многие другие компоненты, которые должны уметь нарисовать себя и отобразить какую-либо информацию.
Дескриптор контекста устройства, над которьм "построена" канва, может быть востребован для различных низкоуровневых операций. Он задается свойством:
property Handle: HDC;
Для рисования канва включает в себя шрифт, перо и кисть:
(р) property Font: TFont ;
(Pt property Pen: TPen;
(РЙ property Brush: TBrush;
Кроме того, можно рисовать и поточечно, получив доступ к каждому пикселу. Значение свойства
property Pixels[X, Y: Integer]: TColor;
соответствует цвету точки с координатами (X,Y).
Канва содержит методы-надстройки над всеми основными функциями рисования GDI Windows и свойства, которые приведены ниже в таблице. При их рассмотрении имейте в виду, что все геометрические фигуры рисуются текущим пером. Те из них, которые можно закрашивать, закрашиваются с помощью текущей кисти. Кисть и перо при этом имеют текущий цвет.
procedure Arc (XI, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integer) ; | Метод рисует сегмент эллипса. Эллипс определяется описывающим прямоугольником (X1,Y1) — (X2,Y2); его размеры должны лежать в диапазоне от 2 до 32767 точек. Начальная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (X3.Y3). Конечная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (X4.Y4). Сегмент рисуется против часовой стрелки. |
procedure Chord(Xl, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integer); | Рисует хорду и заливает отсекаемую ею часть эллипса. Эллипс, начальная и конечная точки определяются, как в методе Arc. |
procedure EllipsefXl, Yl, Х2, Y2: Integer) ; | Рисует и закрашивает эллипс, вписанный в прямоугольник (X1.Y1) — (X2.Y2). |
procedure LineTo(X, Y: Integer); | Проводит линию текущим пером из текущей точки в (X,Y). |
procedure MoveTo(X, Y: Integer); | Перемещает текущее положение пера (свойство PenPos) в точку (X,Y). |
procedure BrushCopy(const Dest: TRect; Bitmap: TBitmap; const Source: TRect; Color: TColor); | Производит специальное копирование. Прямоугольник Source из битовой карты Bitmap копируется в прямоугольник Dest на канве; при этом цвет Color заменяется на цвет текущей кисти (Brush.Color). С помощью этого метода можно нарисовать "прозрачную" картинку. Для этого нужно выбрать соответствующий фону цвет кисти и затем заменить на него фоновый или наиболее часто встречающийся цвет битовой карты (см. Bitmap. TransparentColor). |
procedure CopyRect(const Dest: TRect; Canvas: TCanvas; const Source: TRect) ; | Производит копирование прямоугольника Source из канвы Canvas в прямоугольник Dest в области самого объекта. |
procedure FillRect(const Rect: TRect) ; | Производит заливку прямоугольника (текущей кистью). |
procedure FrameRectfconst Rect: TRect); | Производит оконтуривание прямоугольника цветом текущей кисти (без заполнения). |
procedure Draw(X, Y: Integer; Graphic: TGraphic) ; | Осуществляет рисование графического объекта Graphic (точнее, вызов метода его рисования) в области с верхним левым углом (X,Y). |
procedure StretchDraw(const Rect: TRect; Graphic: TGraphic); | Осуществляет рисование объекта Graphic в заданном прямоугольнике Rect. Если размеры их не совпадают, Graphic масштабируется. |
procedure DrawFocusRect(const Rect: TRect); | Производит отрисовку прямоугольной рамки из точек (как на элементе, имеющем фокус ввода). Поскольку метод использует логическую операцию XOR (исключающее ИЛИ), повторный вызов для того же прямоугольника приводит изображение к начальному виду. |
procedure FloodFilKX, Y: Integer; Color: TColor; FillStyle: TFillStyle); TFillStyle = (fsSurface, fsBorder) ; | Производит заливку области текущей кистью. Процесс начинается с точки (X,Y). Если режим FillStyle равен fsSurface, то он продолжается до тех пор, пока есть соседние точки с цветом Color. В режиме fsBorder закрашивание, наоборот, прекращается при выходе на границу с цветом Color. |
procedure Pie (XI, Yl, Х2, Y2, ХЗ, Y3, Х4, Y4: Integers- | Рисует сектор эллипса, описываемого прямоугольником (X1,Y1) — (X2,Y2). Стороны сектора лежат на лучах, проходящих из центра эллипса через точки (X3.Y3) и (X4,Y4). |
procedure Polygon(const Points: array of TPoint) ; | Строит многоугольник, используя массив координат точек Points. При этом последняя точка соединяется с первой и внутренняя область закрашивается. |
procedure Polyline(const Points: array of TPoint) ; | Строит ломаную линию, используя массив координат точек Points. |
procedure Rectangle(XI, Yl, Х2, Y2 : Integer) ; | Рисует прямоугольник с верхним левым углом в (XI ,Y1) и нижним правым в (X2.Y2). |
procedure RoundRect (XI, Yl, Х2, Y2, ХЗ, Y3: Integer); | Рисует прямоугольник с закругленными углами. Координаты вершин — те же, что и в методе Rectangle. Закругления рисуются как сегменты эллипса с размерами осей по горизонтали и вертикали ХЗ и Y3. |
function. TextHeight(const Text: string): Integer; | Возвращает высоту строки Text в пикселах. |
function TextWidth(const Text: string): Integer; | Возвращает ширину строки Text в пикселах. |
procedure TextOut(X, Y: Integer; const Text: string); | Производит вывод строки Text. Левый верхний угол помещается в точку канвы (X,Y). |
procedure TextRect(Rect: TRect; X, Y: Integer; const Text: stringi ; | Производит вывод текста с отсечением. Как и в TextOut, строка Text выводится с позиции (X,Y); при этом часть текста, лежащая вне пределов прямоугольника Rect, отсекается и не будет видна. |
(Ro) property ClipRect: TRect; | Определяет область отсечения канвы. То, что при рисовании попадает за пределы этого прямоугольника, не будет изображено. Свойство доступно только для чтения — его значение переустанавливается системой в контексте устройства канвы. |
property PenPos: TPoint; | Содержит текущую позицию пера канвы (изменяется посредством метода MoveTo). |
Метод
procedure Refresh;
сбрасывает текущие шрифт, перо и кисть, заменяя их на стандартные, заимствованные из Windows (BLACK.PEN, HOLLOW_BRUSH, SYSTEM.FONT).
Предусмотрено два события для пользовательской реакции на изменение канвы:
property OnChange: TNotifyEvent;
property OnChanging: TNotifyEvent;
Эти события возникают при изменениях свойств и вызовах методов TCanvas, меняющих вид канвы (то есть при любом рисовании. В MoveTo, например, они не возникают). Отличие их в том, что OnChanging вызывается до начала изменений, a OnChange — после их завершения.
Идентификатор (код) растровой операции при копировании прямоугольных блоков содержится в свойстве
(Pb) property CopyMode: TCopyMode;
TCopyMode = Longint;
и определяет правило сочетания пикселов, копируемых на канву, с ее текущим содержимым. При этом можно создавать разные изобразительные эффекты. В Delphi определены следующие константы кодов: cmBlackness, cmDstInvert, cmMergeCopy, cmMergePaint, cmNotSrcCopy, cmNotSrcErase, cmPatCopy, cmPatInvert, cmPatPaint, cmSrcAnd, cmSrcCopy, cmSrcErase, cmSrcInvert, cmSrcPaint, cmWhiteness.
Все они стандартно определены в Windows, и подробное их описание можно найти в документации по GDI. Значением CopyMode по умолчанию является cmSrcCopy — копирование пикселов источника поверх существующих.
Использование графики иллюстрируют несколько примеров, имеющихся на дискете, прилагаемой к книге. Обратите внимание на пример MOVLINES — в нем показано, как создавать и использовать канву для всего экрана. Помимо графических примитивов, таких как линии и фигуры, на канве можно разместить готовые изображения. Для их описания создан класс TGraphic.
3. РАБОТА С КОМПОНЕНТАМИ
После знакомства с общими принципами работы компонентов перейдем к их предметному рассмотрению. В этом разделе описаны все элементы Палитры компонентов, сгруппированные по функциональному назначению. Вы встретите здесь и компоненты, не входящие в Палитру; как правило, они являются предками других компонентов, важными для понимания.
Для каждого из компонентов приводятся все методы и свойства, которые доступны программисту, работающему с этим компонентом, то есть описанные как public и published (в т. ч. недокументированные). Мы попытались проиллюстрировать некоторые неочевидные вещи хотя бы коротким фрагментом кода. В развернутом виде примеры использования компонентов можно найти на дискете, прилагаемой к книге.
3.1. Работа с меню
В приложениях, написанных на Delphi, могут быть реализованы меню двух основных видов:
• Главное меню. Такое меню принадлежит форме и отображается вместе с ней под ее панелью заголовка. Если в приложении несколько форм, то для удобства можно объединять меню всех активных форм в одном.
• Всплывающее меню. Такое меню предусмотрено почти у всех компонентов — элементов управления Windows. Оно возникает (всплывает) при нажатии правой кнопки мыши на этом компоненте. Предусмотрено такое меню и у формы.
Меню являются иерархическими структурами, состоящими из пунктов меню. Каждый пункт может быть выбран. Это может произойти вследствие щелчка кнопкой мыши, нажатия соответствующих клавиш на клавиатуре или вызова процедуры в программе.
На нижнем уровне лежат команды меню — пункты, с выбором которых должна быть связана та или иная реакция приложения. Команда! объединяются в подменю. Подменю — это пункты, выбор которых означает показ или свертывание списка входящих в него команд и подменю.
Принципы создания и работы с меню в Delphi очень просты. Каждому пункту меню соответствует свой компонент класса TMenuItem. Вы добавляете к меню новые пункты (а к форме — новые компоненты) либо во время разработки (при помощи Конструктора меню), либо во время исполнения. При выборе пункта меню для описывающего его компонента инициируется событие OnClick, в обработчике которого и нужно предусмотреть соответствующие действия.
Компонент TMenuItem
TObject—>TPersistent—”TComponent—>TMenuItein
Модуль MENUS
В Палитру компонентов не входит
Этот компонент, который является основой системы меню в Delphi, вы не встретите в Палитре компонентов — он входит в состав имеющихся там компонентов TMainMenu и TPopupMenu.
Текст, содержащийся в пункте меню, определяется свойством:
(Pb) property Caption: string;
Помимо основной, он несет еще две дополнительные нагрузки. Во-первых, если в строке имеется амперсанд ('&'), то он вместе с следующим за ним символом является акселератором. Например, для строки '&File' нажатие
одного символа '-', то этот пункт служит в меню разделителем (имеет стиль MFJSEPARATOR);
Помимо акселератора может быть описана еще одна комбинация клавиш, нажатие которой равнозначно выбору пункта. Она должна содержаться в свойстве: •
(Pb) property Shortcut: TShortCut;
TShortCut = Low(Word)..High(Word);
Способы выбора пункта меню — щелчок мышью, нажатие
procedure Click;
приводят к возникновению события:
(Р1э) property OnClick: TNotifyEvent;
Компонент TMenuItem может различать только это событие, с которьм должны быть связаны действия, ради которых вы ввели данный пункт в меню. Воспринимают это событие те пункты меню, которые в данный момент активны, что означает-установленное в True свойство:
(РЬ) property Enabled: Boolean;
Если Enabled равно False, пункт изображается серьм цветом и не воспринимает сообщений.
Часто пункты меню используются для переключения каких-либо режимов работы программы. При этом они могут быть отмечены "галочкой" перед началом текста. Свойство
(Pb) property Checked: Boolean;
отвечает за то, является ли этот пункт отмеченным.
Если в меню слишком много команд, то их расположение одна под другой может вызвать серьезные неудобства для пользователя. Свойство
(Pb) property Break: TMenuBreak;
TMenuBreak = (mbNone, mbBreak, mbBarBreak) ;
призвано решить эту проблему. Если оно установлено в mbBreak, то команды меню, начиная с этой, располагаются в новом — соседнем с прежним — столбце (при этом их принадлежность не изменяется). Если оно равно mbBarBreak, столбцы при этом разделяются вертикальной чертой. В Delphi все компоненты меню типа TMenuItem могут быть как простыми командами, так и подменю, имеющими собственный список пунктов. В случае, если у компонента дочерних подменю и пунктов нет, для него имеет смысл свойство:
(Ro) property Command: Word;
Прежде при написании меню нужно было выдумывать и присваивать уникальный идентификатор каждому его пункту — то есть собственно код команды, который посылался в качестве параметра сообщения WM.COMMAND. Сейчас эта задача возложена на Delphi — программист не только не определяет, но может и не знать кода команды, связанного с этим пунктом меню. Система выберет уникальное значение автоматически и присвоит это значение свойству Command. Изменять его не разрешается.
Интерпретация сообщений меню скрыта от программиста. Система сама определяет, какой пункт выбран, и вызывает его обработчик события OnClick.
Если для каких-то целей понадобился код команды, можно воспользоваться вышеуказанным свойством (см. пример в описании компонента TMenu).
Если у компонента TMenuItem имеются дочерние пункты, то он является подменю, имеет статус MF_POPUP и дескриптор меню Windows, доступный для чтения через свойство:
(ro) property Handle: HMENU;
Пункты меню иерархически связаны. Методы и свойства для работы с дочерними пунктами меню приведены в таблице.
(До) property Parent: TMenuItem; | Содержит указатель на родительское подменю. |
(Ro) property I terns[Index: Integer]: TMenuItem; | Содержит список дочерних пунктов меню. |
fRo) property Count: Integer; | Содержит количество дочерних пунктов меню. |
procedure Insert(Index: Integer; Item: TMenuItem) ; | Вставляет пункт Item в меню на место Index. Поскольку структура меню строго иерархическая, вставляемый пункт не должен быть частью другого меню (его свойство Parent должно быть равно nil). |
procedure Delete(Index: Integer) ; | Удаляет пункт с индексом Index из меню. |
function IndexOf(Item: TMenuItem): Integer; | Возвращает индекс пункта Item. |
procedure Add(Item: TMenuItem); | Добавляет пункт Item в конец меню. |
procedure Remove(Item: TMenuItem); | Удаляет пункт Item из меню. |
Если пункт меню находится в фокусе, нажатие
(Pb) property HelpContext: THelpContext;
Свойство
(Pb) property Grouplndex: Byte;
используется при объединении нескольких меню между собой. Подробное объяснение его назначения см. в описании компонента TMainMenu.
Компонент TMenu
TObject—”TPersistent->TComponent->TMenu
Модуль MENUS
В Палитру компонентов не входит
Этот компонент отсутствует в Палитре компонентов, но содержит методы и свойства, приведенные в таблице, общие для двух потомков — TMainMenu и TPopupMenu, которые туда входят.
(Ro) property Handle: HMENU; | Содержит дескриптор меню. |
property WindowHandle: HWND; | Содержит дескриптор окна Windows (формы или оконного элемента управления), с которым связано меню. |
(Ro) property Items: TMenuItem; | Содержит список элементов меню. На самом верху иерархии меню есть единственный элемент (со статусом MFPOPUP), чей список и используется. |
function DispatchCoinn>and(ACommand: Word): Boolean; | Отыскивает пункт меню с заданной командой, в случае успеха вызывает его метод Click и возвращает True. |
function DispatchPopupfAHandle: HMENU): Boolean; | Работает как Di spatchCommand, но отыскивает пункт меню с дескриптором AHandle. |
function Findltem(Value: Word; Kind: TFindItemKind): TMenuItem; TFindItemKind = (fkComrriand, fkHandle, fkShortCut); | Возвращает указатель на объект, соответствующий заданному пункту меню. Параметр Value должен содержать величину, которая интерпретируется в соответствии с одним из трех способов поиска (по команде, дескриптору или комбинации горячих клавиш). |
function GetHelpContext(Value: Word; ByComniand: Boolean) : THelpContext; | Возвращает значение контекста помощи элемента меню. Если параметр ByCommand установлен в True, Value содержит связанную с пунктом команду, в противном случае — дескриптор. Если контекст у пункта отсутствует (равен 0), то отыскивается ближайший родительский ненулевой контекст. Если и он не найден, возвращается 0. |
function IsShortCut(var Message: TWMKey): Boolean; | Определяет, какая комбинация горячих клавиш ShortCut нажата, и отыскивает соответствующий пункт меню. Если пункт с таким значением ShortCut найден, и его метод Click отработал успешно, метод возвращает True. |
В следующем примере метод обрабатывает сообщение Windows WM_MENUSELECT, которое возникает при перемещении фокуса между пунктами меню. В зависимости от типа пункта показывается его дескриптор или команда:
procedure TFormI.wmMenuSelect(var Msg :TWMMenuSelect) ;
var Anitem : TMenuItem;
begin
with Msg do
begin
if (MenuFlag and MF_POPUP <>0 )
then
begin
Anitem := Formi.Menu.Findltem(Idltem, fkHandle);
if Anitemonil then Labell .Caption :=
'Handle:'+IntToHex(Anitem.Handle,4) ;
end
else
begin
Anitem := Formi.Menu.Findltem(Idltem, fkCommand);
if Anitemonil then Labell .Caption :=
'Command:'+IntToHex(Anitem.Command,4) ;
end;
end;
inherited;
end;