Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Тема 8: «Типизированные файлы»
Длина любого компонента типизированного файла строго постоянна, что дает возможность организовать прямой доступ к каждому из них (т.е. доступ к компоненту по его порядковому номеру). Перед первым обращением к процедурам ввода-вывода указатель файла стоит в его начале и указывает на первый компонент с номером 0. После каждого чтения или записи указатель сдвигается к следующему компоненту файла. Переменные в списках ввода-вывода должны иметь тот же тип, что и компоненты файла. Если этих переменных в списке несколько, указатель будет смещаться после каждой операции обмена данными между переменными и дисковым файлом. Процедура READ. Обеспечивает чтение очередных компонентов типизированного файла. Формат обращения: READ (<ф.п.>,<сп.ввода>) Здесь <cn.вводa> - список ввода, содержащий одну или более переменных такого же типа, что и компоненты файла. Файловая переменная <ф.п.> должна быть объявлена предложением FILE OF... и связана с именем файла процедурой ASSIGN. Файл необходимо открыть процедурой RESET. Если файл исчерпан, обращение к READ вызовет ошибку ввода-вывода. Процедура WRITE. Используется для записи данных в типизированный файл. Формат обращения: WRITE (<ф.п.>,<сп.вывода>) Здесь <сп.вывода> - список вывода, содержащий одно или более выражений того же типа, что и компоненты файла. Процедура SEEK. Смещает указатель файла к требуемому компоненту. Формат обращения: SEEK (<ф.п.>,<N компонента>) Здесь <N компонента> - выражение типа LONGINT, указывающее номер компонента файла. Первый компонент файла имеет номер 0. Процедуру нельзя применять к текстовым файлам. Функция FILESIZE. Возвращает значение типа LONGINT, которое содержит количество компонентов файла. Формат обращения: ' FILESIZE (<ф.п.>) Функцию нельзя использовать для текстовых файлов. Чтобы переместить указатель в конец типизированного файла, можно написать: seek (FileVar, FileSize(FileVar)); где FILEVAR - файловая переменная. Функция.FILEPOS. Возвращает значение типа LONGINT, содержащее порядковый номер компонента файла, который будет обрабатываться следующей операцией ввода-вывода. Формат обращения: FILEPOS (<ф.п.>) Функцию нельзя использовать для текстовых файлов. Первый компонент файла имеет порядковый номер 0. Тема 9: «Модуль Graph» Пример перехода к графическому режиму var Driver, Mode, Error:Integer; begin Driver := Detect;{Автоопределение драйвера} InitGraph(Driver, Mode,' ');{Инициируем графику} Error := GraphResult;{Получаем результат} if Error <> grOk then{Проверяем ошибку} begin{Ошибка в процедуре инициации} WriteLn(GraphErrorMsg(Error));{Выводим сообщение} ....... end else{Нет ошибки} ....... Procedure ClearViewPort Очищает окно. Если тип адаптера ПК неизвестен или если программа рассчитана на работу с любым адаптером, используется обращение к процедуре с требованием автоматического определения типа драйвера: Driver := Detect; InitGraph(Driver, Mode, 'C:\TP\BGI'); После такого обращения устанавливается графический режим работы экрана, а при выходе из процедуры переменные Driver и Mode содержат целочисленные значения, определяющие тип драйвера и режим его работы. При этом для адаптеров, способных работать в нескольких режимах, выбирается старший режим, т.е. тот, что закодирован максимальной цифрой. Так, при работе с CGA -адаптером обращение к процедуре со значением Driver = Detect вернет в переменной Driver значение 1 (CGA) и в Mode -значение 4 (CGAHi), а такое же обращение к адаптеру VGA вернет Driver = 9 (VGA) и Mode = 2 (VGAHi). Функция GraphResult. Возвращает значение типа Integer, в котором закодирован результат последнего обращения к графическим процедурам. Если ошибка не обнаружена, значением функции будет ноль, в противном случае - отрицательное число, имеющее следующий смысл: const grOk = 0;{Нет ошибок} grlnitGraph =-1;{He инициирован графический режим} grNotDetected =-2;{Не определен тип драйвера} grFileNotFind =-3;{Не найден графический драйвер} grlnvalidDriver =-4;{Неправильный тип драйвера} grNoLoadMem =- 5;{Нет памяти для размещения драйвера} grNoScanMem = - 6;{Нет памяти для просмотра областей} grNoFloodMem =- 7;{Нет памяти для закраски областей} grFontNotFound = -8;{Не найден файл со шрифтом} grNoFontMem =- 9;{Нет памяти для размещения шрифта} grlnvalidMode =-10;{Неправильный графический режим} grError =-11;{Общая ошибка} grIOError =-12;{Ошибка ввода-вывода} grlnvalidFont =-13;{Неправильный формат шрифта} grInvalidFontNum=-14; {Неправильный номер шрифта} После обращения к функции GraphResult признак ошибки сбрасывается, поэтому повторное обращение к ней вернет ноль. Функция GraphErrorMsg. Возвращает значение типа String, в котором по указанному коду ошибки дается соответствующее текстовое сообщение. Заголовок функции: Function GraphErrorMsg(Code: Integer): String; Здесь Code - код ошибки, возвращаемый функцией GraphResult. Например, типичная последовательность операторов для инициации графического режима с автоматическим определением типа драйвера и установкой максимального разрешения имеет следующий вид: var Driver, Mode, Error:Integer; begin Driver := Detect;{Автоопределение драйвера} InitGraph(Driver, Mode,' ');{Инициируем графику} Error := GraphResult;{Получаем результат} if Error <> grOk then{Проверяем ошибку} begin{Ошибка в процедуре инициации} WriteLn(GraphErrorMsg(Error));{Выводим сообщение} ....... end else{Нет ошибки} ....... Чаще всего причиной возникновения ошибки при обращении к процедуре InitGraph является неправильное указание местоположения файла с драйвером графического адаптера (например, файла CGA.BGI для адаптера CGA). Настройка на местоположение драйвера осуществляется заданием маршрута поиска нужного файла в имени драйвера при вызове процедуры InitGraph. Если, например, драйвер зарегистрирован в подкаталоге DRIVERS каталога PASCAL на диске D, то нужно использовать вызов: InitGraph(Driver, Mode, 'd:\Pascal\Drivers'); Замечание. Во всех следующих примерах процедура InitGraph вызывается с параметром Driver в виде пустой строки. Такая форма обращения будет корректна только в том случае, когда нужный файл графического драйвера находится в текущем каталоге. Для упрощения повторения примеров скопируйте файл, соответствующий адаптеру Вашего ПК, в текущий каталог. Процедура CloseGraph. Завершает работу адаптера в графическом режиме и восстанавливает текстовый режим работы экрана. Заголовок: Procedure CloseGraph; Процедура RestoreCRTMode. Служит для кратковременного возврата в текстовый режим. В отличие от процедуры CloseGraph не сбрасываются установленные параметры графического режима и не освобождается память, выделенная для размещения графического драйвера. Заголовок: Procedure RestoreCRTMode; Функция GetGraphMode. Возвращает значение типа Integer, в котором содержится код установленного режима работы графического адаптера. Заголовок: Function GetGraphMode: Integer; Процедура SetGraphMode. Устанавливает новый графический режим работы адаптера. Заголовок: Procedure SetGraphMode(Mode: Integer); Здесь Mode - код устанавливаемого режима. Следующая программа иллюстрирует переход из графического режима в текстовый и обратно: Uses Graph; var . Driver, Mode, Error : Integer; begin {Инициируем графический режим} Driver := Detect; InitGraph(Driver, Mode, ''); Error := GraphResult; {Запоминаем результат} i£ Error <> grOk then {Проверяем ошибку} WriteLn(GraphErrorMsg(Error)) {Есть ошибка} else begin {Нет ошибки} WriteLn ('Это графический режим'); WriteLn ('Нажмите "Enter"...':20); ReadLn; {Переходим в текстовый режим} RestoreCRTMode; WriteLn (' А это текстовый...'); ReadLn; {Возвращаемся в графический режим} SetGraphMode (GetGraphMode); WriteLn ('Опять графический режим...'); ReadLn; CloseGraph end end. В этом примере для вывода сообщений как в графическом, так и в текстовом режиме используется стандартная процедура WriteLn. Если Ваш ПК оснащен нерусифицированным адаптером CGA, вывод кириллицы в графическом режиме таким способом невозможен, в этом случае замените соответствующие сообщения так, чтобы использовать только латинские буквы. Процедура DetectGraph. Возвращает тип драйвера и режим его работы. Заголовок: Procedure DetectGraph(var Driver,Mode: Integer); Здесь Driver - тип драйвера; Mode - режим работы. В отличие от функции GetGraphMode описываемая процедура возвращает в переменной Mode максимально возможный для данного адаптера номер графического режима. Функция GetDriverName. Возвращает значение типа String, содержащее имя загруженного графического драйвера. Заголовок: Function GetDriverName: String; Функция GetMaxMode. Возвращает значение типа Integer, содержащее количество возможных режимов работы адаптера. Заголовок: Function GetMaxMode: Integer; Функция GetModeName. Возвращает значение типа String, содержащее разрешение экрана и имя режима работы адаптера по его номеру. Заголовок: Function GetModName(ModNumber: Integer): String; Здесь ModNumber - номер режима. Следующая программа после инициации графического режима выводит на экран строку, содержащую имя загруженного драйвера, а также все возможные режимы его работы. Uses Graph; var a,b: Integer; begin a := Detect; InitGraph(a, b, ''); WriteLn(GetDriverName); for a := 0 to GetMaxMode do WriteLn(GetModeName(a):10); ReadLn; CloseGraph end. Процедура GetModeRange. Возвращает диапазон возможных режимов работы заданного графического адаптера. Заголовок: Procedure GetModeRange(Drv: Integer; var Min, Max: Integer); Здесь Drv - тип адаптера; Min - переменная типа Integer, в которой возвращается нижнее возможное значение номера режима; Мах - переменная того же типа, верхнее значение номера. Если задано неправильное значение параметра Drv, процедура вернет в обеих переменных значение -1. Перед обращением к процедуре можно не устанавливать графический режим работы экрана. Следующая программа выводит на экран названия всех адаптеров и диапазоны возможных номеров режимов их работы. Uses Graph; var D,L,H: Integer; const N: array [1..11] of String [8] = ('CGA ', 'MCGA ', 'EGA ', 'EGA64 ', 'EGAMono ', ЧВМ8514 ', 'HercMono', 'ATT400 ', 'VGA ', 'PC3270 ', 'Ошибка '); begin WriteLn('Адаптер Мин. Макс.'); for D := 1 to 11 do begin GetModeRange(D, L, H); WriteLn(N[D], L:7, H:10) end end. КООРДИНАТЫ, ОКНА, СТРАНИЦЫ Многие графические процедуры и функции используют указатель текущей позиции на экране, который в отличие от текстового курсора невидим. Положение этого указателя, как и вообще любая координата на графическом экране, задается относительно левого верхнего угла, который, в свою очередь, имеет координаты 0,0. Таким образом, горизонтальная координата экрана увеличивается слева направо, а вертикальная - сверху вниз. Функции GetMaxX и GetMaxY. Возвращают значения типа Word, содержащие максимальные координаты экрана в текущем режиме работы соответственно по горизонтали и вертикали. Например: Uses Graph; var a,b: Integer; begin a := Detect; InitGraph(a, b, ''); WriteLn(GetMaxX, GetMaxY:5); ReadLn; CloseGraph end. Функции GetX и GetY. Возвращают значения типа Integer, содержащие текущие координаты указателя соответственно по горизонтали и вертикали. Координаты определяются относительно левого верхнего угла окна или, если окно не установлено, экрана. Процедура SetViewPort. Устанавливает прямоугольное окно на графическом экране. Заголовок: Procedure SetViewPort(XI,Y1,X2,Y2: Integer; ClipOn: Boolean); Здесь X1...Y2 - координаты левого верхнего (XI,Y1) и правого нижнего (X2,Y2) углов окна; СНрОп - выражение типа Boolean, определяющее «отсечку» не умещающихся в окне элементов изображения. Координаты окна всегда задаются относительно левого верхнего угла экрана. Если параметр ClipOn имеет значение True, элементы изображения, не умещающиеся в пределах окна, отсекаются, в противном случае границы окна игнорируются. Для управления этим параметром можно использовать такие определенные в модуле константы: const ClipOn = True; {Включить отсечку} ClipOff = False; {He включать отсечку} Следующий пример иллюстрирует действие параметра СНрОп. Программа строит два прямоугольных окна с разными значениями параметра и выводит в них несколько окружностей. Для большей наглядности окна обводятся рамками . Uses Graph,CRT; var x,y,e: Integer; xll,yll,xl2,yl2, {Координаты 1-го окна} x21,x22, {Левый верхний угол 2-го} R, {Начальный радиус} k: Integer; begin DirectVideo := False {Блокируем прямой доступ к видеопамяти в модуле CRT} {Инициируем графический режим} х := Detect; InitGraph(x, у, ''); {Проверяем результат} е := GraphResult; if e <> grOk then WriteLn(GraphErrorMsg (e) ) {Ошибка} else begin {Нет ошибки} {Вычисляем координаты с учетом разрешения экрана} x11:=GetMaxX div 60; x12:=GetMaxX div 3; y11:=GetMaxY div 4; y12:=2*y11; R:=(x12-x11) div 4; x21:=x12*2; x22:=x21+x12-x11; {Рисуем окна} WriteLnt'ClipOn:':10,'ClipOff:':40); Rectangle(x11, y11, x12, y12); Rectangle(x21, y11 x22, y12); {Назначаем 1-е окно и рисуем четыре окружности} SetViewPort(x11, y11, x12, y12, ClipOn); for k := 1 to 4 do Circle(0,y11,R*k); {Назначаем 2-е окно и рисуем окружности} SetViewPort(x21, y11, x22, y12, ClipOff); for k := 1 to 4 do Circle(0,y11,R*k); {Ждем нажатия любой клавиши} if ReadKey=#0 then k := ord(ReadKey); CloseGraph end end. Процедура GetViewSettings. Возвращает координаты и признак отсечки текущего графического окна. Заголовок: Procedure GetViewSettings(var Viewlnfo: ViewPortType); Здесь Viewlnfo - переменная типа ViewPortType. Этот тип в модуле Graph определен следующим образом: type ViewPortType = record x1,y1,x2,y2: Integer; {Координаты окна} Clip : Boolean {Признак отсечки} end ; Процедура MoveTo. Устанавливает новое текущее положение указателя. Заголовок: Procedure MoveTo(X,Y: integer); Здесь X, Y - новые координаты указателя соответственно по горизонтали и вертикали. Координаты определяются относительно левого верхнего угла окна или, если окно не установлено, экрана. Процедура MoveRel. Устанавливает новое положение указателя в относительных координатах. Procedure MoveRel(DX,DY: Integer); Здесь DX.DY- приращения новых координат указателя соответственно по горизонтали и вертикали. Приращения задаются относительно того положения, которое занимал указатель к моменту обращения к процедуре. Процедура ClearDevice. Очищает графический экран. После обращения к процедуре указатель устанавливается в левый верхний угол экрана, а сам экран заполняется цветом фона, заданным процедурой SetBkColor. Заголовок: Procedure ClearDevice; Процедура ClearViewPort. Очищает графическое окно, а если окно не определено к этому моменту - весь экран. При очистке окно заполняется цветом с номером О из текущей палитры. Указатель перемещается в левый верхний угол окна. Заголовок: Procedure ClearViewPort; В следующей программе на экране создается окно, которое затем заполняется случайными окружностями . После нажатия на любую клавишу окно очищается. Для выхода из программы нажмите Enter. Uses CRT,Graph; var x1,y1,x2,y2,Err: Integer; begin {Инициируем графический режим} xl := Detect; InitGraph(xl,x2,''); Err := GraphResult; if ErrogrOk then WriteLn(GraphErrorMsg(Err)) else begin {Определяем координаты окна с учетом разрешения экрана} x1 := GetMaxX div 4,-y1 := GetMaxY div 4; x2 := 3*x1; y2 := 3*y1; {Создаем окно} Rectangle(x1,y1,x2,y2); SetViewPort(x1+1,y1+1,x2-1,y2-1,ClipOn); {Заполняем окно случайными окружностями} repeat Сirclе(Random(Ge tMaxX),Random(Ge tMaxX) Random(GetMaxX div 5)) until KeyPressed; {Очищаем окно и ждем нажатия Enter} ClearViewPort; OutTextXY(0,0,'Press Enter...1); ReadLn; CloseGraph end end. Процедура GetAspectRatio. Возвращает два числа, позволяющие оценить соотношение сторон экрана. Заголовок: Procedure GetAspectRatio(var X,Y: Word); Здесь X, Y - переменные типа Word. Значения, возвращаемые в этих переменных, позволяют вычислить отношение сторон графического экрана в пикселях. Найденный с их помощью коэффициент может использоваться при построении правильных геометрических фигур, таких как окружности, квадраты и т.п. Например, если Вы хотите построить квадрат со стороной L пикселей по вертикали, Вы должны использовать операторы GetAspectRatio (Xasp, Yasp); Rectangle(x1, y1, x1+L*round (Yasp/Xasp), y1+L); а если L определяет длину квадрата по горизонтали, то используется оператор Rectangle (x1,y1,x1+L,y1+L*round(Xasp/Yasp)); Процедура SetAspectRatio. Устанавливает масштабный коэффициент отношения сторон графического экрана. Заголовок: Procedure SetAspectRatio(X,Y: Word); Здесь X, Y- устанавливаемые соотношения сторон. Следующая программа строит 20 окружностей с разными соотношениями сторон экрана Uses Graph,CRT; const R =.50; dx = 1000; var d,m,e,k : Integer; Xasp,Yasp: Word; begin d := Detect; InitGraph(d, m,.''); e : = GraphResult; if e <> grOk then WriteLn(GraphErrorMsg(e)) else begin GetAspectRatio(Xasp, Yasp); for k := 0 to 20 do begin SetAspectRatio(Xasp+k*dx,Yasp); Circle(GetMaxX div 2,GetMaxY div 2,R) end; if ReadKey=#0 then k := ord(ReadKey); CloseGraph end end. Процедура SetActivePage. Делает активной указанную страницу видеопамяти. Заголовок: Procedure SetActivePage(PageNum: Word); Здесь PageNum - номер страницы. Процедура может использоваться только с адаптерами, поддерживающими многостраничную работу (EGA, VGA и т.п.). Фактически процедура просто переадресует графический вывод в другую область видеопамяти, однако вывод текстов с помощью Write/WriteLn всегда осуществляется только на страницу, которая является видимой в данный момент (активная страница может быть невидимой). Нумерация страниц начинается с нуля. ПроцедураSetVisualPage. Делает видимой страницу с указанным номером. Обращение: Procedure SetVisualPAge(PageNum: Word); Здесь PageNum - номер страницы. Процедура может использоваться только с адаптерами, поддерживающими многостраничную работу (EGA, VGA и т.п.). Нумерация страниц начинается с нуля. Следующая программа сначала рисует квадрат в видимой странице и окружность -в невидимой. После нажатия на Enter происходит смена видимых страниц. Uses Graph; var d,m,e: Integer; s : String; begin d := Detect; InitGraph(d, m, ''); e := GraphResult; if e <> grOk then WriteLn (GraphErrorMsg(e)) else {Нет ошибки. Проверяем, поддерживает ли драйвер многостраничную работу с видеопамятью:} if d in [HercMono,EGA,EGA64,MCGA,VGA] then begin {Используем многостраничный режим} if d<>HercMono then SetGraphMode(m-1); {Заполняем видимую страницу} Rectangle(10,10,GetMaxX div 2,GetMaxY div 2); OutTextXY(0,0,'Page 0. Press Enter...'); {Заполняем невидимую} SetActivePage (1); Circle(GetMaxX div 2, GetMaxY div 2, 100); OutTextXY(0,GetMaxY-10,'Page 1. Press Enter...'); {Демонстрируем страницы} ReadLn; SetVisualPage(1); ReadLn; SetVisualPage (0); ReadLn; CloseGraph end else begin {Драйвер не поддерживает многостраничный режим} s := GetDriverName; CloseGraph; WriteLn('Адаптер ',s,' использует только 1 страницу') end end. Обратите внимание на оператор if doHercMono then SetGraphMode(m-1); С его помощью гарантированно устанавливается многостраничный режим работы на адаптерах EGA, MCGA, VGA. Как уже говорилось, после инициации графики с Driver=Detect устанавливается режим работы с максимально возможным номером; перечисленные адаптеры в этом режиме могут работать только с одной графической страницей, чтобы обеспечить работу с двумя страницами, следует уменьшить номер режима. ЛИНИИ И ТОЧКИ Процедура PutPixel. Выводит заданным цветом точку по указанным координатам. Заголовок: Procedure PutPixel(X,Y: Integer; Color: Word); Здесь X, Y- координаты точки; Color - цвет точки. Координаты задаются относительно левого верхнего угла окна или, если окно не установлено, относительно левого верхнего угла экрана. Следующая программа периодически выводит на экран «звездное небо» и затем гасит его. Для выхода из программы нажмите любую клавишу. Uses CRT, Graph; type PixelType = record x, у : Integer; end; const N = 5000; {Количество "звезд"} var d,r,e,k: Integer; x1,y1,x2,y2: Integer; a: array [1..N] of PixelType; {Координаты} begin {Инициируем графику} d := Detect; InitGraph(d, r, ' ') ; e := GraphResult; if e<>grOk then WriteLn(GraphErrorMsg(e)) else begin {Создаем окно в центре экрана} x1 := GetMaxX div 4; y1 := GetMaxY div 4; x2 := 3*x1; y2 := 3*y1; Rectangle(x1,y1,x2,y2); SetViewPort(x1+1,y1+1,x2-1,y2-1,ClipOn); {Создаем и запоминаем координаты всех "звезд"} for k := 1 to N do with a[k] do begin x := Random(x2-x1); у := Random(y2-y1) end; {Цикл вывода} repeat for k := 1 to N do with a[k] do {Зажигаем "звезду"} PutPixel(x,y,white); if not KeyPressed then for k := N downto 1 do with a[k] do {Гасим "звезду"} PutPixel(x,y,black) until KeyPressed; while KeyPressed do k := ord(ReadKey); CloseGraph end; end. Функция GetPixel. Возвращает значение типа Word, содержащее цвет пикселя с указанными координатами. Заголовок: Function GetPixel(X,Y: Integer): Word; Здесь X, Y - координаты пикселя. Процедура Line. Вычерчивает линию с указанными координатами начала и конца. Заголовок: Procedure Line(X1,Y1,X2,Y2: Integer); Здесь XL. .Yl - координаты начала (XI, Y1) и конца (Х2, Y2) линии. Линия вычерчивается текущим стилем и текущим цветом. В следующей программе в центре экрана создается окно, которое затем расчерчивается случайными линиями. Для выхода из программы нажмите любую клавишу. Uses CRT, Graph; var d,r,e : Integer; x1,y1,x2,y2: Integer; begin {Инициируем графику} d := Detect; InitGraph(d, r, ''); e := GraphResult; if e <> grOk then WriteLn(GraphErrorMsg(e)) else begin {Создаем окно в центре экрана} x1 := GetMaxX div 4; y1 := GetMaxY div 4; x2 := 3*x1; y2 := 3*y1; Rectangle(x1,y1,x2,y2); SetViewPort(x1+1,y1+1,x2-1,y2-1,ClipOn); {Цикл вывода случайных линий} repeat SetColor(succ(Random(16))); {Случайный цвет} Line(Random(x2-x1), Random(y2-y1), Random(x2-x1), Random(y2-y1)) until KeyPressed; if ReadKey=#0 then d:= ord(ReadKey); CloseGraph end end. Процедура LineTo. Вычерчивает линию от текущего положения указателя до положения, заданного его новыми координатами. Заголовок: Procedure LineTo(X,Y: Integer); Здесь X, Y - координаты нового положения указателя, они же - координаты второго конца линии. Процедура LineRel. Вычерчивает линию от текущего положения указателя до положения, заданного приращениями его координат. Заголовок: Procedure LineRel (DX, DY: Integer); Здесь DX, DY- приращения координат нового положения указателя. В процедурах LineTo и LineRel линия вычерчивается текущим стилем и текущим цветом. Процедура SetLineStyle. Устанавливает новый стиль вычерчиваемых линий. Заголовок: Procedure SetLineStyle(Type,Pattern,Thick: Word) Здесь Type, Pattern, Thick - соответственно тип, образец и толщина линии. Тип линии может быть задан с помощью одной из следующих констант: const SolidLn= 0; {Сплошная линия} DottedLn= 1; {Точечная линия} CenterLn= 2; {Штрих-пунктирная линия} DashedLn= 3; {Пунктирная линия} UserBitLn= 4; {Узор линии определяет пользователь} Параметр Pattern учитывается только для линий, вид которых определяется пользователем (т.е. в случае, когда Туре = UserBitLn). При этом два байта параметра Pattern определяют образец линии: каждый установленный в единицу бит этого слова соответствует светящемуся пикселю в линии, нулевой бит - несветящемуся пикселю. Таким образом, параметр Pattern задает отрезок линии длиной в 16 пикселей. Этот образец периодически повторяется по всей длине линии. Параметр Thick может принимать одно из двух значений: const NormWidth = 1; {Толщина в один пиксель} ThickWidth = 3; {Толщина в три пикселя} Отметим, что установленный процедурой стиль линий (текущий стиль) используется при построении прямоугольников, многоугольников и других фигур. В следующем примере демонстрируются линии всех стандартных стилей, затем вводятся слово-образец и линия с этим образцом заполнения (рис. 14.4). Для выхода из программы введите ноль. Uses CRT, Graph; const style: array [0..4] of String [9] = ( 'SolidLn ', 'DottedLn ', 'CenterLn 'DashedLn', 'UserBitLn'); var d,r,e,i,j,dx,dy: Integer; p: Word; begin {Инициируем графику} d := Detect; InitGraph(d, r, ''); e := GraphResult; if e <> grOk then WriteLn (GraphErrorMsg(e)) else begin {Вычисляем смещение линий} dx := GetMaxX div 6; dy := GetMaxY div 10; {Выводим стандартные линии} for j := 0 to 1 do {Для двух толщин} begin for i := 0 to 3 do {Четыре типа линий} begin SetLineStyle(i, 0, j*2+1); Line(0,(i+j*4+l)*dy,dx,(i+j*4+l)*dy); OutTextXY(dx+10, (i+j*4+l)*dy,style [i]) end end; {Вводим образец и чертим линию} j := 0; dy := (GetMaxY+1) div 25; repeat OutTextXY(320,j*dy,'Pattern: '); GotoXY(50,j+1); ReadLn(p); if p <> 0 then begin SetLineStyle(UserBitLn,p,NormWidth); Line(440,j*dy+4, 600, j*dy+4); inc(j) end until p = 0; CloseGraph end end. Процедура GetLineSettings. Возвращает текущий стиль линий. Заголовок: Procedure GetLineSettings(var Stylelnfo: LineSettingsType) Здесь Stylelnfo - переменная типа LineSettingsType, в которой возвращается текущий стиль линий. Тип LineSettingsType определен в модуле Graph следующим образом: type LineSettingsType = record LineStyle: Word; {Тип линии} Pattern : Word; {Образец} Thickness: Word {Толщина} end; Процедура SetWriteMode. Устанавливает способ взаимодействия вновь выводимых линий с уже существующим на экране изображением. Заголовок: Procedure SetWriteMode(Mode); Здесь Mode - выражение типа Integer, задающее способ взаимодействия выводимых линий с изображением. Если параметр Mode имеет значение 0, выводимые линии накладываются на существующее изображение обычным образом (инструкцией МОV центрального процессора). Если значение 1, то это наложение осуществляется с применением логической операции XOR (исключительное ИЛИ): в точках пересечения выводимой линии с имеющимся на экране изображением светимость пикселей инвертируется на обратную, так что два следующих друг за другом вывода одной и той же линии на экран не изменят его вид. Режим, установленный процедурой SetWriteMode, распространяется на процедуры Drawpoly, Line, LineRel, LineTo и Rectangle. Для задания параметра Mode можно использовать следующие определенные в модуле константы: const CopyPut = 0;{Наложение операцией MOV} XORPut = 1;{Наложение операцией XOR} В следующем примере на экране имитируется вид часового циферблата (рис. 1.4.5). Для наглядной демонстрации темп хода «часов» ускорен в 600 раз (см. оператор Delay (100)). При желании Вы сможете легко усложнить программу, связав ее показания с системными часами и добавив секундную стрелку. Для выхода из программы нажмите на любую клавишу. Uses Graph, CRT; var d,r,r1,r2,rr,k, x1,y1,x2,y2,x01,y01: Integer; Xasp,Yasp : Word; begin {Инициируем графику} d := detect; InitGraph(d, r, ''); k := GraphResult; if k <> grOK then WriteLn(GraphErrorMSG(k)) else begin {Определяем отношение сторон и размеры экрана} x1 := GetMaxX div 2; y1 := GetMaxY div 2; GetAspectRatio(Xasp, Yasp); {Вычисляем радиусы:} r:= round(3*GetMaxY*Yasp/8/Xasp); r1 := round(0.9*r); {Часовые деления} г2 := round(0.95*r); {Минутные деления} {Изображаем циферблат} Circle(x1,y1,r); {Первая внешняя окружность} Circle(x1,y1,round(1.02*г) ); {Вторая окружность} for k := 0 to 59 do {Деления циферблата} begin if k mod 5=0 then rr := r1 {Часовые деления} else rr : = r2; {Минутные деления} {Определяем координаты концов делений} x0l := x1+Round(rr*sin(2*pi*k/60)); y0l := y1-Round(rr*Xasp*cos(2*pi*k/60)/Yasp); x2 := x1+Round(r*sin(2*pi*k/60)); y2 := y1-Round(r*Xasp*cos(2*pi*k/60)/Yasp); Line(x01,y01,x2,y2) {Выводим деление} end; {Готовим вывод стрелок} SetWriteMode(XORPut); SetLineStyle(SolidLn,0,ThickWidth); {Счетчик минут в одном часе} {k = минуты} r := 0; {Цикл вывода стрелок} repeat for k := 0 to 59 do if not KeyPressed then begin (Координаты часовой стрелки} x2 := x1+Round(0.85*r1*sin(2*pi*r/60/12)); y2 := y1-Round(0.85*r1*Xasp*cos(2*pi*r/60/12)/Yasp); {Координаты минутной стрелки} x01 := x1+Round(r2*sin(2*pi*k/60)); y01 := y1-Round(r2*Xasp*cos(2*pi*k/60)/Yasp); {Изображаем стрелки} Line(x1,y1,x2,y2); Line(x1,y1,x01,y01) ; Delay(100); {Для имитации реального темпа нужно установить задержку 60000} {Для удаления стрелок выводим их еще раз!} Line(x1,y1,x01,y01); Line(x1,y1,х2,у2); {Наращиваем и корректируем счетчик минут в часе} inc(r); if r=12*60 then r := 0 end until KeyPressed; if ReadKey=#0 then k := ord(ReadKey); CloseGraph end end. МНОГОУГОЛЬНИКИ Процедура Rectangle. Вычерчивает прямоугольник с указанными координатами углов. Заголовок: Procedure Rectangle(X1,Y1,X2,Y2: Integer); Здесь X1... Y2 - координаты левого верхнего (X1, Y1) и правого нижнего (Х2, Y2) углов прямоугольника. Прямоугольник вычерчивается с использованием текущего цвета и текущего стиля линий. В следующем примере на экране вычерчиваются 10 вложенных друг в друга прямоугольников. Uses Graph, CRT; var d,r,e,xl,yl, x2,y2,dx,dy: Integer; begin {Инициируем графику} d := Detect; InitGraph(d, r, ' ') ; e := GraphResult; if e <> grOK then WriteLn(GraphErrorMsg(e)) else begin {Определяем приращения сторон} dx := GetMaxX div 20; dy := GetMaxY div 20; {Чертим вложенные прямоугольники} for d := 0 to 9 do Rectangle(d*dx,d*dy,GetMaxX-d*dx,GetMaxY-d*dy); if ReadKey=#0 then d := ord(ReadKey); CloseGraph end end. Процедура DrawPoly. Вычерчивает произвольную ломаную линию, заданную координатами точек излома. Procedure DrawPoly(N: Word; var Points) Здесь N - количество точек излома, включая обе крайние точки; Points - переменная типа PointType, содержащая координаты точек излома. Координаты точек излома задаются парой значений типа Word: первое определяет горизонтальную, второе - вертикальную координаты. Для них можно использовать следующий определенный в модуле тип: type PointType = record х, у : Word end; При вычерчивании используется текущий цвет и текущий стиль линий. Вот как, например, можно с помощью этой процедуры вывести на экран график синуса: Uses Graph; const N = 100; {Количество точек графика} var d, r, e: Integer; m : array [O..N+1] of PointType; k : Word; begin {Инициируем графику} d := Detect; InitGraph(d, r, ''); e := GraphResult; if e <> grOk then WriteLn(GraphErrorMsg(e)) else begin {Вычисляем координаты графика} for k := 0 to N do with m[k] do begin x := trunc(k*GetMaxX/N); у := trunc(GetMaxY*(-sin(2*Pi*k/N)+1)/2) end; {Замыкаем график прямой линией} m[succ(N)].x := m[0] .x; m[succ(n)].y := m[0] .у; DrawPoly(N + 2, m); ReadLn; CloseGraph end end. В этом примере для проведения горизонтальной прямой используется «замыкание» ломаной - первая и последняя координаты ее точек излома совпадают. Замечу, что хотя количество точек излома N - выражение типа Word, на самом деле внутри процедуры на этот параметр накладываются ограничения, связанные с конечным размером используемой буферной памяти. Вы можете убедиться в этом с помощью, например, изменения N в предыдущем примере: при N=678 график перестанет выводиться на экран, а функция GraphResult будет возвращать значение -6 (не хватает памяти для просмотра областей). Таким образом, для этой программы пороговое значение количества точек излома составляет 679. В то же время для программы Uses Graph; const N=510; {Предельное значение, при котором на экране еще видна диагональная линия} var d,k: Integer; Coo: array [1..N] of PointType; begin d := Detect; InitGraph(d,k,' ') ; for k := 1 to N do with Coo[k] do if odd(k) then begin X := 0; Y := 0 end else begin X := GetMaxX; Y := GetMaxY end; DrawPoly(N,Coo); ReadLn; CloseGraph end. это значение равно 510. В этой программе ломаная задается в виде многократно накладывающихся друг на друга диагональных линий. ДУГИ, ОКРУЖНОСТИ, ЭЛЛИПСЫ Процедура Circle. Вычерчивает окружность. Заголовок: Procedure Circle(X,Y: Integer; R: Word); ЗдесьX, Y- координаты центра; R - радиус в пикселях. Окружность выводится текущим цветом. Толщина линии устанавливается текущим стилем, вид линии всегда SolidLn (сплошная). Процедура вычерчивает правильную окружность с учетом изменения линейного размера радиуса в зависимости от его направления относительно сторон графического экрана, т.е. с учетом коэффициента GetAspectRatio. В связи с этим параметр R определяет количество пикселей в горизонтальном направлении. В следующем примере в центре экрана создается окно, постепенно заполняющееся случайными окружностями. Для выхода из программы нажмите на любую клавишу. Uses Graph, CRT; var d,r,e,x,y: Integer; begin. {Инициируем графику} d i= Detect; InitGraph(d, r, ''); e := GraphResult; if e <> grOK then WriteLn(GraphErrorMsg(e)) else begin {Создаем окно в центре экрана} х := GetMaxX div 4; у := GetMaxY div 4; Rectangle(х,у,3*х,3*у); SetViewPort(x+1,y+1,3*x-1,3*y-1,ClipOn); {Цикл вывода случайных окружностей} repeat SetColor(succ(Random(white))); {Случайный цвет} SetLineStyle(0,0,2*Random(2)+1); {и стиль линии} х := Random(GetMaxX); {Случайное положение} у := Random(GetMaxY); {центра окружности} Circle(х,у,Random(GetMaxY div 4)); until KeyPressed; if ReadKey=#0 then x := ord(ReadKey); CloseGraph end end. Процедура Arc. Чертит дугу окружности. Заголовок: Procedure Arc(X,Y: Integer; BegA,EndA,R: Word); Здесь X, Y - координаты центра; BegA, EndA - соответственно начальный и конечный углы дуги; R - радиус. Углы отсчитываются против часовой стрелки и указываются в градусах. Нулевой угол соответствует горизонтальному направлению вектора слева направо. Если задать значения начального угла 0 и конечного - 359, то будет выведена полная окружность. При вычерчивании дуги окружности используются те же соглашения относительно линий и радиуса, что и в процедуре Circle. Вот как выглядят две дуги: одна с углами 0 и 90, вторая 270 и 540 градусов (рис. 14.6): Следующая программа создает это изображение: Uses Graph, CRT; var d, r, е : Integer; Xasp,Yasp: Word; begin {Инициируем графику} d := Detect; InitGraphtd, r, ''); e := GraphResult; if e <> grOK then WriteLn(GraphErrorMsg(e)) else begin GetAspectRatio(Xasp,Yasp); {R = 1/5 от вертикального размера экрана} r := round(Yasp*GetMaxY/5/XAsp); d := GetMaxX div 2; {Смещение второго графика} e : = GetMaxY div 2; {Положение горизонтальной оси} {Строим левый график} Line (0,e,5*r div 2,e); {Горизонтальная ось} Line (5*r div 4,e div 2,5*r div 4,3*e div 2) ; Arc (5*r div 4,e,0,90,R); {Дуга} OutTextXY(0,e+e div 8,'0 - 90'); {Надпись} {Правый график} Line (d,e,d+5*r div 2,e); Line (d+5*r div 4,e div 2, d+5*r div 4,3*e div 2); Arc (d+5*r div 4,e,270,540,R); OutTextXY(d,e+e div 8,'270 - 540'); {Ждем нажатия на любую клавишу} if ReadKey=#0 then d := ord(ReadKey); CloseGraph end end. Процедура GetArcCoords. Возвращает координаты трех точек: центра, начала и конца дуги. Заголовок: Procedure GetArcCoords(var Coords: ArcCoordsType); Здесь Coords - переменная типа ArcCoordsType, в которой процедура возвращает координаты центра, начала и конца дуги. Тип ArcCoordsType определен в модуле Graph следующим образом: type ArcCoordsType = record X,Y : Integer; {Координаты центра} Xstart,Ystart: Integer; {Начало дуги} Xend,Yend : Integer; {Конец дуги} end; Совместное использование процедур Arc и GetArcCoords позволяет вычерчивать сопряжения двух прямых с помощью дуг. Обратите внимание на коррекцию длины радиуса в следующем примере, в котором вычерчивается прямоугольник со скругленными углами. Uses Graph,CRT; const RadX = 50; {Горизонтальный радиус} lx = 400; {Ширина} ly = 100; {Высота} var d,r,e: Integer; coo : ArcCoordsType; x1,y1: Integer; xa,ya: Word; RadY : Integer; {Вертикальный радиус} begin {Инициируем графику} d := Detect; InitGraph(d, r, ' ') ; e := GraphResult; if e <> grOK then WriteLn(GraphErrorMsg(e)) else begin GetAspectRatio(xa,ya) ; {Получаем отношение сторон} {Вычисляем вертикальный радиус и положение фигуры с учетом отношения сторон экрана} RadY := round (RadX *( xa /ya) ); x1 := (GetMaxX-lx) div 2; y1 := (GetMaxY-2*RadY-ly) div 2; {Вычерчиваем фигуру} Line (x1,y1,x1+lx,y1); {Верхняя горизонтальная} Arc (x1+lx,y1+RadY,0,90,RadX) ; {Скругление} GetArcCoords(coo); with coo do begin Line(Xstart,Ystart,Xstart,Ystart+ly); {Правая вертикальная} Arc(Xstart-RadX,Ystart+ly,270,0,RadX); GetArcCoords (coo); Line(Xstart,Ystart,Xstart-lx,Ystart); {Нижняя горизонтальная} Arc(Xstart-lx,Ystart-RadY,180,270,RadX); GetArcCoords(coo); Line(Xstart,Ystart,Xstart,Ystart-ly); Arc(Xstart+RadX,Ystart-ly,90,180,RadX) end ; if ReadKey=#0 then d := ord(ReadKey); CloseGraph end end. Процедура Ellipse. Вычерчивает эллипсную дугу. Заголовок: Procedure Ellipse(X,Y: Integer; BegA,EndA,RX,RY: Word); Здесь X, Y - координаты центра; BegA, EndA - соответственно начальный и конечный углы дуги; RX, RY- горизонтальный и вертикальный радиусы эллипса в пикселях. При вычерчивании дуги эллипса используются те же соглашения относительно линий, что и в процедуре Circle, и те же соглашения относительно углов, что и в процедуре Arc. Если радиусы согласовать с учетом масштабного коэффициента GetAspectRatio, будет вычерчена правильная окружность. В следующей программе вычерчиваются три эллипсных дуги при разных отношениях радиусов. Замечу, что чем выше разрешение графического экрана, тем ближе к единице отношение сторон и тем меньше первый график отличается от третьего. Uses Graph, CRT; var d,r,e: Integer; xa,ya: Word; begin {Инициируем графику} d := Detect; InitGraph(d, r, ''); e := GraphResult; if e <> grOK then WriteLn(GraphErrorMsg(e)) else begin {Первый график} OutTextXY(5 0,4 0,'RX = RY'); {Надпись} Line (0,100,160,100); {Ось X} Line (80,55,80,145); {Ось Y} Ellipse (80,100,180,90,40,40); {Второй график} OutTextXY(260,40,'RX = 5*RY'); Line (190,100,410,100); Line (300,55,300,145); Ellipse (300,100,0,359,100,20); {Третий график} OutTextXY(465,40,'Aspect Ratio'); Line (440,100,600,100); Line (520,55,520,145); GetAspectRatio(xa, ya); Ellipse (520,100,0,270,40,round(40*(xa/ya))); if ReadKey=#0 then d := ord(ReadKey); CloseGraph end end. |
||
Последнее изменение этой страницы: 2018-05-29; просмотров: 142. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |