лабораторные на Pasca (Кудрявцев)l
.pdfОкна |
263 |
|
|
Наконец, мы должны определить реакцию на выбор этих команд, то есть добавить в процедуру TMyApp.HandleEvent описание дейст- вий, которые нужно выполнить:
cmTile: begin
DeskTop^.GetExtent(R);
DeskTop^.Tile(R);
end;
cmCascade: begin
DeskTop^.GetExtent(R);
DeskTop^.Cascade(R);
end;
Если Вы все сделали правильно, то открытые Вами окна теперь можно будетрасполагать каскадом или мозаикой.
Еще одно поле, которым располагает TWindow – поле Palette типа integer. Это поле задает цвет элементов окна. Стандартными явля-
ются значения wpBlueWindow, wpCyanWindow и wpGrayWindow. Лег-
ко, например, сделать серыми второе и четвертое из открываемых окон. Для этого в процедуру TMyApp.NewWindow достаточно доба- вить строку:
if ((WinCount=2) or (WinCount=4)) then Window^.Palette:=wpGrayWindow;
Для того, чтобы изменить стандартную “раскраску” окон, необхо- димо воспользоваться виртуальной функцией GetPalette: PPalette. Это выглядит так:
function TDemoWindow.GetPalette: PPalette; const
CDemoWindow=#15#9#5;
PDemoWindow: string[Length(CDemoWindow)]=CDemoWindow; begin
GetPalette:=@PDemoWindow;
end;
Константа CDemoWindow и содержит описание новой палитры окна. Ее первый бит (#15) определяет цвет рамки пассивного окна, вто- рой (#9) – цвет рамки активного окна, третий (#5) – цвет кнопок управления окном. Всего в CDemoWindow содержится восемь бит, определяющих полную окраску окна. Вы можете удивиться, поче-
264 |
Лабораторная работа № 24 |
|
|
му, указав цвет 15, Вы получили не белое окно, а красное (15 номер соответствует белому цвету в стандартном Паскале). Дело в том, что передача цветов в Turbo Vision происходит достаточно сложным образом. Во-первых, для отображения некоторого видимого объек- та нужно задать два цвета – цвет фона и цвет изображения. Во- вторых, каждый видимый объект имеет своего “хозяина”, который этим объектом владеет, соответственно должны быть согласованы цвета различных объектов. Поэтому в CDemoWindow на самом деле Вы указываете не сам цвет окна, а то место, которое нужный Вам цвет (точнее пара – цвет фона + цвет изображения) занимает в па- литре цветов объекта-хозяина. Хозяином всех наших окон является DeskTop, который, однако, собственной палитры не имеет. Поэто- му, поднимаясь по дереву иерархии, мы находим другого хозяина – TProgram, в палитре которого и находятся выбранные нами цвета. Не вдаваясь в подробности описания сложной палитры TProgram, Вы можете попробовать «экспериментально» подобрать те цвета, которые покажутся Вам наиболее удачными.
После всех внесенных изменений Ваша программа должна принять окончательный вид:
program TFirst3;
uses App,Objects,Menus,Drivers,Views; const
cmNewWin=199;
cmFileOpen=200; winCount: Integer=0;
type TMyApp=Object(TApplication) procedure InitStatusLine; virtual; procedure InitMenuBar; virtual; procedure NewWindow; virtual;
procedure HandleEvent(var Event: TEvent); virtual; end;
type PDemoWindow=^TDemoWindow; TDemoWindow=object(TWindow) function GetPalette: PPalette;virtual; end;
Окна |
265 |
|
|
var
MyApp: TMyApp;
function TDemoWindow.GetPalette: PPalette; const
CDemoWindow=#15#13#4;
PDemoWindow: string[Length(CDemoWindow)]=CDemoWindow; begin
GetPalette:=@PDemoWindow;
end;
procedure TMyApp.InitStatusLine; var R:TRect;
begin GetExtent(R); R.A.Y:=R.B.Y-1;
StatusLine:=New(PStatusLine,Init(R, NewStatusDef(0,$FFFF, NewStatusKey('~Alt-X~Exit',kbAltX,cmQuit, NewStatusKey('~F4~New',kbF4,cmNewWin, NewStatusKey('~Alt-F3~Close',kbAltF3,cmClose, NewStatusKey('~F10~Menu',kbF10,cmMenu,
nil)))),
nil)))
end;
procedure TMyApp.InitMenuBar; var R:TRect;
begin GetExtent(R); R.B.Y:=R.A.Y+1;
MenuBar:=New(PMenuBar,Init(R,NewMenu(
NewSubMenu('~F~ile',hcNoContext,NewMenu(
NewItem('~O~pen','F3',kbF3,cmFileOpen,
hcNoContext,
NewItem('~N~ew','F4',kbF4,cmNewWin,
hcNoContext,
NewLine( NewItem('E~x~it','Alt-X',kbAltX,cmQuit,
hcNoContext,
nil))))),
266 |
Лабораторная работа № 24 |
|
|
NewSubMenu('~W~indow',hcNoContext,NewMenu(
NewItem('~N~ext','F6',kbF6,cmNext,
hcNoContext,
NewItem('~Z~oom','F5',kbF5,cmZoom,
hcNoContext, NewItem('~S~ize/Move','Ctr-F5',kbCtrlF5,cmResize,
hcNoContext,
NewItem('~T~ile','',0,cmTile,
hcNoContext,
NewItem('~C~ascade','',0,cmCascade,
hcNoContext,
nil)))))),
nil)))))
end;
procedure TMyApp.NewWindow; var
Window: PDemoWindow; R: TRect;
begin Inc(WinCount); R.Assign(0,0,30,7);
R.Move(Random(58),Random(16)); Window:=New(PDemoWindow, Init(R,'Demo Window ', WinCount)); Window^.Options:=Window^.Options+ofTileable; DeskTop^.Insert(Window);
end;
procedure TMyApp.HandleEvent(var Event: TEvent); var R: TRect;
begin TApplication.HandleEvent(Event); if Event.What=evCommand then begin
case Event.Command of cmNewWin: NewWindow; cmTile:
begin DeskTop^.GetExtent(R); DeskTop^.Tile(R);
Окна |
267 |
|
|
end;
cmCascade: begin
DeskTop^.GetExtent(R);
DeskTop^.Cascade(R); end
else Exit; end; end;
end; BEGIN
MyApp.Init;
MyApp.Run;
MyApp.Done;
END.
Задания для самостоятельнойработы
Поупражняйтесь в изменении атрибутов создаваемых программой TFirst3 окон: а) сделайте так, чтобы первые десять окон имели индивидуальные заголовки (например, Первое окно, Второе окно и т. д.); б) сделайте так, чтобы первые четыре окна при их выводе на экран располагались каска- дом; в) сделайте так, чтобы первые четыре окна при выводе их на экран располагались мозаикой.
Измените атрибуты третьего окна так, чтобы оно стало недоступным для пользователя, то есть после создания не реагировало бы ни на какие ко- манды от мышки или клавиатуры.
268
Лабораторная работа № 25
ИНТЕРЬЕР
В предыдущей работе мы научились создавать окна, правда, пока совершенно пустые. Попробуем теперь заполнить окно, поместив в него для начала какую-нибудь простую фразу, например «Я Вам пишу». В стандартном Паскале мы воспользовались бы для этой цели оператором Write. Однако в Turbo Vision он явно не годится – этот оператор просто выведет данную фразу на экран, а нам этого мало! Наши окна умеют делать множество веще – перемещаться, изменять свои размеры, закрываться, а написанная с помощью Write фраза ничего этого не знает. Вместе с тем, приобретенный в преды- дущих работах опыт подсказывает, что нам нужно – нам нужен ви- димый объект, который составит с окном группу и, следовательно, будет себя вести в соответствии с требованиями хозяина (т.е. окна)
– перемещаться вместе с ним, исчезать при его закрытии и так да- лее. Этот видимый объект и называют интерьером окна или просто интерьером. Как мы уже отмечали, все видимые объекты являются потомками TView, поэтому его объявление в соответствии с общи- ми правилами Turbo Vision будетиметь вид:
PInterior=^TInterior;
TInterior=object(TView)
Для инициализации объекта TInterior нам достаточно указать разме- ры той области, которую он будет занимать, то есть инициализиро- вать единственное поле, определяемое переменной типа TRect. Следовательно, в описание объекта войдет конструктор
constructor TInterior.Init(var Bounds: TRect);
Наконец, TInterior должен уметь себя рисовать. Все видимые объек- ты рисуют себя с помощью родительского метода Draw, который нам необходимо расширить, поскольку создаем мы наш собствен- ный интерьер (в предыдущей работе мы создавали стандартные ок- на и расширение метода Draw нам не потребовалось). Следователь- но, в описание TInterior войдет виртуальная процедура Draw и раз- дел описания типов нашей программы TFirst3 пополнится строками:
PInterior=^TInterior;
TInterior=object(TView)
Интерьер |
269 |
|
|
constructor TInterior.Init(var Bounds: TRect); procedure Draw; virtual;
end;
Входящие сюда конструктор и процедура описываются следующим кодом:
constructor TInterior.Init(var Bounds: TRect);
begin |
|
|
TView.Init(Bounds); |
|
{вызываем метод Init предка} |
GRowMode:=gfGrowHiX+gfGrowHiY; |
{и устанавливаем, что при изменении |
|
|
размеров окна его интерьер будетсохранять |
|
постоянное расстояние от правой и нижней границ окна-владельца} |
||
end; |
|
|
procedure TInterior.Draw; |
|
|
var |
|
|
S: string; |
|
|
begin |
|
|
TView.Draw; |
|
{вызываем метод предка} |
S:='Я Вам пишу'; |
|
|
WriteStr(4,2,S,6); |
{добавляем в интерьер необходимуюзапись; |
|
|
первые две цифры — относительные координаты строки S, |
|
|
|
последняя — код цвета строки} |
end;
Теперь нужно подсоединить интерьер к окну. На языке Turbo Vision это означает, что мы должны снова инициализировать окно, теперь уже с добавлением к нему интерьера. Поэтому придется написать конструктор Init для нашего объекта TDemoWindow. Он может вы- глядеть, например, так:
constructor TDemoWindow.Init(Bounds: TRect; WinTitle: string; WindowNo: Integer);
Var |
|
{не забудьтеобновить описание типов} |
|
S: string[3]; |
|
|
|
Interior: PInterior; |
|
|
|
begin |
|
|
|
Str(WindowNo, S); |
{переводим численное значение номера окна в строку} |
||
TWindow.Init(Bounds, WinTitle+' '+S, wnNoNumber); |
{и добавляем его к |
||
GetClipRect(Bounds); |
|
|
заголовку окна} |
{запрашиваем размеры доступного пространства окна} |
|||
Bounds.Grow(-1,-1); |
{устанавливаем размеры интерьера на единицу меньше |
||
|
размеров окна} |
|
|
Interior:=New(PInterior, Init(Bounds)); |
{инициализируем интерьер} |
||
Insert(Interior); |
|
{и вставляем его в окно} |
|
end; |
|
|
|
Интерьер |
271 |
|
|
begin TView.Init(Bounds);
GRowMode:=gfGrowHiX+gfGrowHiY;
end;
procedure TInterior.Draw; var
S: string; begin
TView.Draw; S:='Запись в окно'; WriteStr(4,2,S,6); end;
constructor TDemoWindow.Init(Bounds: TRect; WinTitle: string; WindowNo: Integer);
var S: string[3]; Interior: PInterior;
begin Str(WindowNo, S);
TWindow.Init(Bounds, WinTitle+' '+S, wnNoNumber); GetClipRect(Bounds);
Bounds.Grow(-1,-1); Interior:=New(PInterior, Init(Bounds)); Insert(Interior);
end;
procedure TMyApp.InitStatusLine; var R:TRect;
begin GetExtent(R); R.A.Y:=R.B.Y-1;
StatusLine:=New(PStatusLine,Init(R, NewStatusDef(0,$FFFF, NewStatusKey('~Alt-X~Exit',kbAltX,cmQuit, NewStatusKey('~F4~New',kbF4,cmNewWin, NewStatusKey('~Alt-F3~Close',kbAltF3,cmClose, NewStatusKey('~F10~Menu',kbF10,cmMenu,
nil)))),
nil)))
end;
procedure TMyApp.InitMenuBar; var R:TRect;
begin GetExtent(R); R.B.Y:=R.A.Y+1;
MenuBar:=New(PMenuBar,Init(R,NewMenu(
272 |
Лабораторная работа № 25 |
|
|
NewSubMenu('~F~ile',hcNoContext,NewMenu(
NewItem('~O~pen','F3',kbF3,cmFileOpen,
hcNoContext,
NewItem('~N~ew','F4',kbF4,cmNewWin,
hcNoContext,
NewLine( NewItem('E~x~it','Alt-X',kbAltX,cmQuit,
hcNoContext,
nil))))),
NewSubMenu('~W~indow',hcNoContext,NewMenu(
NewItem('~N~ext','F6',kbF6,cmNext,
hcNoContext,
NewItem('~Z~oom','F5',kbF5,cmZoom,
hcNoContext, NewItem('~S~ize/Move','Ctr-F5',kbCtrlF5,cmResize,
hcNoContext,
NewItem('~T~ile','',0,cmTile,
hcNoContext,
NewItem('~C~ascade','',0,cmCascade,
hcNoContext,
nil)))))),
nil)))))
end;
procedure TMyApp.NewWindow; var Window: PDemoWindow;
R: TRect; begin
Inc(WinCount);
R.Assign(0,0,30,7);
R.Move(Random(58),Random(16)); Window:=New(PDemoWindow, Init(R,'Demo Window ', WinCount)); Window^.Options:=Window^.Options+ofTileable; DeskTop^.Insert(Window);
end;
procedure TMyApp.HandleEvent(var Event: TEvent); var
R: TRect; begin
TApplication.HandleEvent(Event); if Event.What=evCommand then begin
case Event.Command of cmNewWin: NewWindow; cmTile: