Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Графические возможности TURBO C++ 51
åé int fseek(FILE*,long, int). Первый аргумент указывает на файл, с которым нужно работать. Третий аргумент обязан иметь значение системной константы SEEK_SET для текстовых файлов (а другие мы не рассматриваем и рассматри­вать не будем). Именно эта конструкция должна стоять на месте последнего параметра функции. Второй аргумент задает номер позиции, на которую должно быть установлено файловое окно, то есть номер байта, отсчитанный от начала файла. Функция long ftell(FILE*) возвращает номер текущей позиции в файле. Функция void rewind(FILE*) устанавливает файловое окно в начало файла, то есть делает то же, что и функция fseek(p,0L, SEEK_SET), åñëè ð — указатель на файл. Числовая константа 0L есть «длинный ноль» — число 0 типа long.
Графические возможности TURBO C++
В текстовом режиме, с которым мы до сих пор работали, рабочий экран представляет собой совокупность строк и столбцов. Обычно на экране разме­щено 25 строчек и 80 столбцов. В каждой позиции может быть отображен только один из алфавитно-цифровых символов клавиатуры. Гораздо большие возможности предоставляет графический режим.
Прежде чем подробно знакомиться с графикой, следует отметить, что гра­фические средства не включаются в единый стандарт языка С. Это значит, что в тех или иных системах программирования такие средства могут быть реализованы по-разному или вообще отсутствовать. То, о чем будет идти речь ниже, относится именно к системе TURBO C++ 1.0. В современных объект­но-ориентированных системах типа Borland C++ графика организована вооб­ще совершенно иначе.
Графические возможности системы определяются аппаратным и про­граммным обеспечением компьютера. Аппаратные средства включают в себя монитор и видеоадаптер. Основными характеристиками монитора являются возможность графического отображения и цветность. Современные монито­ры, как правило, предоставляют возможность работы с графикой. Вообще го­воря, и многоцветный режим работы дисплея поддерживается большинством мониторов, однако имеются и мониторы, работающие только в монохромном режиме, обеспечивающие при этом высокое разрешение. Видеоадаптерами называются электронные схемы, обеспечивающие работу монитора. Проме­жуточным звеном — интерфейсом между программой и видеоадаптером — яв­ляется программа управления последним. Такая программа называется драй­вером. Драйверы допускают работу в различных видеомодах. Видеомоды раз­личаются разрешающей способностью (количеством точек на экране по вертикали и горизонтали), количеством отображаемых цветов и количеством видеостраниц. Что такое видеостраницы и как с ними работать, любознатель­ный читатель может узнать самостоятельно, пользуясь литературой, например книгой [3], и справочной системой.
Драйверы видеоадаптера могут быть самыми разнообразными, в зависи мости от того, работу каких систем они поддерживают. В системе программи
-
-
52 Глава 1. Язык программирования С
рования TURBO Ñ существует достаточно большой набор таких драйверов, находящихся в каталоге с именем BGI. Файлы, в которых записаны драйверы, имеют расширение bgi от фирменного названия BORLAND GRAPHIC INTERFACE. Мы будем ориентироваться на работу с драйвером egavga.bgi, обеспечивающим работу монитора в режиме VGA. Кроме того, везде далее бу­дем предполагать, что графические процедуры реализуются в графической моде VGAHI (режим VGA с высоким разрешением). В этой моде экран пред­ставляет собой совокупность точек (пикселей) 640 × 480 по горизонтали и вер­тикали соответственно. В каждом пикселе возможно отображение одного из 16 цветов. Мода VGAHI может оперировать с двумя видеостраницами. Таким образом, любой пиксель имеет свои координаты — целые числа, изменяю­щиеся по горизонтали от 0 до 639 включительно и по вертикали от 0 до 479. Система координат несколько необычна. Начало ее — точка с координатами 0,0 находится в левом верхнем углу экрана так, что ось ОХ направлена сверху вниз.
Для операций с графикой к программе следует подключить соответствую­щий заголовочный файл. Если вы собираетесь рисовать, не забудьте вставить в программу препроцессорную инструкцию:
#include<graphics.h>
Что же можно делать в графическом режиме? Перечислим полный список таких возможностей, и если в следующем материале этой книги вы не найдете нужных вам сведений по какому-то из этих пунктов, обратитесь к справочной системе TURBO Ñ или найдите книгу [3].
Итак, вам предоставляется возможность:
1. Закрашивать всю рабочую область экрана одним из доступных цве-
тов — устанавливать цвет фона.
2. Ставить и удалять пиксель с любыми допустимыми координатами и
любого допустимого цвета.
3. Соединять две любые точки экрана прямой линией заданного цвета.
Линии могут быть нескольких типов и нескольких толщин.
4. Рисовать прямоугольники, окружности, эллипсы и их дуги.
5. Закрашивать замкнутые области экрана. Закраска может быть несколь-
ких типов.
6. Хранить в памяти прямоугольные области экрана и выводить их в про-
извольном месте экрана.
7. Манипулировать несколькими страницами видеопамяти.
Кроме того, к графике отнесены операции вывода на экран текстов с ис­пользованием различных размеров и типов шрифтов и различной ориентации (по горизонтали и по вертикали).
Перед первой графической операцией графика должна быть инициализи­рована — загружен необходимый драйвер и установлена необходимая мода. Инициализация производится функцией:
void initgraph(int*, int*, char*)
Графические возможности TURBO C++ 53
Первый параметр является указателем на целую переменную, которая предварительно должна получить значение номера графического драйвера. По мнению автора, здесь допущена некоторая путаница. На самом деле речь идет не о номере драйвера, а о номере режима, причем этот номер устанавливается, как правило, не числом, а системной константой. Так, для подключения режи­ма VGA следует сначала в программе выполнить присваивание gd=VGA и на место первого аргумента функции initgraph поместить &gd. Второй параметр является адресом переменной, которой присваивается значение номера графи­ческой моды. Здесь также удобнее обратиться не к числу, а к системной пере­менной. Для работы в моде высокого разрешения вы должны выполнить при­сваивание gm=VGAHI и на место второго аргумента поставить &gm. Третий ар­гумент является строкой, в которой указан полный путь к драйверу, например:
"C:\\LANGUAGE\\TC\\BGI"
В данном случае считается, что драйвер egavga.bgi находится в подкатало­ге BGI подкаталога ТС каталога LANGUAGE диска С:. Дорогой читатель! Вот вам вопрос на тестирование вашей внимательности и памяти: почему в указа­нии пути мы разделяем имена каталогов двумя обратными чертами, а не од­ной? Впрочем, можно обойтись и без указания пути вообще. Для этого скопи­руйте файл egavga.bgi из того места, где он находится, в ваш рабочий каталог и на месте третьего аргумента функции инициализации графики поставьте пустую строку «».
В случае успешной инициализации графики произойдет переход из тек­стового режима в графический, полностью очистится экран, и вы можете «брать в руки карандаши и ластик» и приступать к рисованию. Однако, преж­де чем учиться рисовать, примите рекомендацию. Перед выходом из програм­мы или в любом другом месте, закончив работу с графикой, вернитесь в тек­стовый режим. Закрытие графики выполняется очень просто. Напишите вы­ражение closegraph();, и все. Но помните, что при этом графическое изображение с экрана исчезнет.
Рассмотрим две первые графические операции установки цветов. Цвета задаются номерами — значениями типа int или символическими константами:
0 BLACK 8 DARKGRAY
1 BLUE 9 LIGHTBLUE
2 GREEN 10 LIGHTGREEN
3 CYAN 11 LIGHTCYAN
4 RED 12 LIGHTRED
5 MAGENTA 13 LIGHTMAGENTA
6 BROWN 14 YELLOW
7 LIGHTGRAY 15 WHITE.
Установка цвета фона производится функцией void setbkcolor(int), где аргу­мент задает цвет (можно писать как номер, так и название цвета в соответст­вии с приведенной выше таблицей). Цвет рисуемых объектов — линий окруж­ностей, прямоугольников и т. д. устанавливается функцией void setcolor(int).
54 Глава 1. Язык программирования С
Теперь рассмотрим построение так называемых графических примитивов. Для того чтобы поставить точку с заданными координатами и заданного цве­та, используйте функцию void putpixel(int, int. int). Два первых аргумента зада­ют Õ è Y координаты точки, а третий — ее цвет. Вы можете определить цвет точки экрана с помощью функции unsigned getpixel(int, int). Аргументами яв­ляются координаты точки. Функция возвращает номер цвета, который имеет точка с этими координатами в текущий момент.
Для того чтобы поместить «перо» в точку с заданными координатами, вы можете употребить функцию void moveto(int, int). Здесь аргументы — коорди­наты, в которые нужно установить перо. Функция void line(int, int, int, int) ри­сует прямую линию из точки с координатами, заданными первой парой аргу­ментов, в точку, заданную второй парой аргументов. Если же вы хотите про­вести прямую из текущей позиции в заданную, то это можно сделать функцией void lineto(int, int). Наконец, может возникнуть задача проведения прямой из текущей позиции в точку, смещенную на ΔX точек по горизонтали и на ΔY точек по вертикали. Выполняйте эту операцию функцией void linerel (int, int). Аргументы здесь задают смещения.
Как можно видеть, параметры, задающие координаты на экране, опреде­ляются целыми значениями типа int. В процессе построения графиков в ре­зультате различных математических вычислений координаты могут быть по­лучены в виде вещественных чисел. Ничего страшного. Система сама позабо­тится о преобразовании типов. Нужно только помнить, что преобразование будет сделано путем округления. Кроме того, программисту следует позабо­титься о том, чтобы рисуемое изображение не выходило за рамки рабочей об­ласти экрана. В ряде случаев выход за «разрешенные границы» может привес­ти к непредсказуемым последствиям, хотя, как правило, следствием такой си­туации будет только то, что вы не увидите желанного изображения или его части.
Чтобы нарисовать прямоугольник, нужно задать две пары чисел — коор­динаты левой верхней и правой нижней вершин прямоугольника — и исполь­зовать их в качестве аргументов функции void rectangle(int, int, int, int) соот­ветственно. Можно провести ломаную через заданные точки с помощью функции void drowpoly(int, int*). Первый аргумент функции задает число то­чек, через которые нужно провести ломаную.
Второй аргумент может быть именем массива целого типа, в котором за­писаны попарно Õ è Y координаты точек. Теперь настала пора написать пер­вую программу с графикой:
#include<graphics.h> int grdr=VGA,grmd=VGAHI; void main() {int mas[] ={70,75,84,96,120,100,90,100}; initgraph(&grdr,&grmd,""); setcolor(RED); drowpoly(4,mas); getch(); closegraph(); }
Графические возможности TURBO C++ 55
Массив mas содержит восемь чисел, которые представляют собой пары координат четырех точек, через которые проводится ломаная. Цвет фона не установлен, а следовательно, останется черным. Основной цвет определен как RED. Стало быть, сама ломаная рисуется красным цветом. Наличие перед за­крытием графики функции getch() обеспечивает сохранение рисунка на экра­не до тех пор, пока не будет нажата какая-либо клавиша.
Рассмотрим теперь изображение кривых второго порядка. Функция void circle(int, int, int) рисует окружность. Два первых параметра задают координа­ты центра, последний — радиус окружности. Функция, рисующая дугу окруж­ности, имеет пять аргументов типа int и может быть вызвана в виде àrñ(õ,ó,startangle,endangle,radius). Здесьхиу—координаты центра, radius — радиус окружности. Второй и третий аргументы задают начальный и конеч­ный углы, в пределах которых рисуется дуга. Углы задаются в градусах и от­считываются от положительного направления оси абсцисс против часовой стрелки.
Для рисования дуги эллипса можно вызвать функцию:
ellipce(x,ó,startangle,endangle,radiusx,radiusy)
В отличие от функции arc здесь последними параметрами задаются гори­зонтальная и вертикальная полуоси.
Пожалуй, наиболее интересные возможности графики в TURBO C++ со­средоточены в функциях доступа к видеопамяти. Наверное, понятно, что ин­формация о состоянии каждой точки графического экрана закодирована в цифровом виде и хранится в памяти компьютера. Память, отведенная под хранение состояния экрана, может быть названа видеопамятью. Любой пря­моугольный фрагмент экрана может быть сохранен в памяти в виде массива атрибутов пикселей, его составляющих. В этой связи такую «заплатку» на эк­ране можно перенести в любое другое место рабочей области. Для этого необ­ходимо выполнить следующие шаги:
1. Определить объем памяти, необходимый для запоминания «заплатки». Используется функция unsigned imagesize(int left, int top, int right, int bottom). Здесь left — Х-координата левой стороны прямоугольника, top — Y-координа­та верхней стороны прямоугольника, right — координата правой стороны, bottom — координата нижней стороны. Функция возвращает занимаемый пря­моугольником объем памяти, выраженный, разумеется, в байтах.
2. Выделить (зарезервировать) необходимую память. Здесь работает функ­ция void* malloc(unsigned size). Функция резервирует size байтов памяти и воз­вращает адрес начала зарезервированной памяти. Обратите внимание на со­всем экзотический тип функции. Дословно этот тип void* следовало бы на­звать «указатель на никакой тип», однако более верно назвать его указателем на что угодно. Функции резервирования памяти (это не только malloc,ине только для графических работ) требуют подключения заголовочного файла alloc.h. Обратим внимание на то, что после того как вы закончили работать с выделенной памятью, желательно освободить память, вызвав функцию free(point).
56 Глава 1. Язык программирования С
3. Записать в выделенную память информацию. Функция void getimage(int left, int top, int right, int bottom, void* point) помещает информацию о «заплат-
ке» в память, начиная с адреса, заданного последним параметром. Первые ар­гументы те же, что и у функции imagesize.
4. Скопировать прямоугольник в новое место экрана можно с помощью функции void putimage(int left, int top. void* point, int sort). Первый и второй па­раметры задают новые координаты левого верхнего угла копии «заплатки». С третьим аргументом, наверное, все ясно — это все тот же адрес участка па­мяти, где сохранена «заплатка». Последний аргумент управляет режимом ко­пирования. В частности, если он имеет значение 0 или символической кон­станты COPY_PUT, то копия «заплатки» просто освобождает себе место, сте­рев занимаемую область. Если sort принимает значение 1 или XOR_PUT, то двукратное применение putimage с этим значением восстанавливает прежние пиксели. Последней возможностью следует пользоваться при отображении движущихся объектов для восстановления предыдущего состояния фонового рисунка экрана. Есть еще и некоторые другие режимы копирования.
Проиллюстрируем последний, довольно сложный материал программой:
#include<graphics.h> #include<alloc.h> int gd=VGA,gm=VGAHI; void main() { void* point; unsigned size; initgraph(&gd,&gm,""); circle(70,70,10); size=imagesize(60,60,80,80); point=malloc(size); getimage(60,60,80,80,point); putimage(160,160,point,0); getch(); free(point); closegraph(); }
В программе рисуется окружность с центром в точке с координатами х=60, у=60. Затем, с использованием средств прямого доступа к видеопамяти, воспроизводится копия окружности с центром в точке х=160, у=160.
Теперь рассмотрим возможности вывода текста на экран в графическом режиме. Функция void outtext(char*) выводит текст на графический экран, на­чиная с текущей позиции, то есть с того места, где находился графический курсор в момент выполнения функции. Аргументом функции является указа­тель на символ. Таким образом, этот параметр должен быть именем символь­ного массива, содержащего печатаемую строку, или непосредственно строкой текста, взятой в кавычки. Функция void outtextxy(int, int, char*) отличается от предыдущей тем, что выводит текст, начиная с графической позиции, коорди­наты которой заданы двумя первыми параметрами.
В стандартном режиме текст выводится неким «обычным» шрифтом в го­ризонтальную строку. Можно, однако, и изменить шрифт и вывести текст в виде вертикальной строки. Изменение шрифта, направления вывода и разме­ра символов выполняет функция void settextstyle(int font, int dir, int size). Пер­вый аргумент font задает шрифт печати и может принимать значения 0, 1, 2, 3
Графические возможности TURBO C++ 57
и 4. Этим номерам соответствуют пять возможных шрифтов, включая, напри­мер, готический. Для работы с различными шрифтами системе должны быть доступны соответствующие драйверы, которые имеют расширение .chr и рас­положены там же, где и графические драйверы с расширением .bgi. По этой причине, если вы отважились на красивое оформление вашей графики с по­мощью различных шрифтов, то в функции инициализации графики необхо­димо указать путь к каталогу BGI системы TURBO C++ или поместить соот­ветствующий драйвер шрифта в рабочий каталог. Кстати, по названию .chr-драйверов вы поймете, каким шрифтам они соответствуют. Второй пара­метр — dir может принимать значения 0 или 1. В первом случае текст выво­дится в горизонтальную строку, а во втором — по вертикали снизу вверх. Тре­тий аргумент задает размер символов, изменяющийся от очень маленького — 0 до очень большого — 14.
Пример работы с различными шрифтами дает следующая программа:
#include <graphics.h> void main() { int gd=VGA,gm=VGAHI,font,dir,size; puts("FONT (0 —- 4)="); scant ("%d",&font) ; puts("DIR (0,1)="); scanf('%d",&dir); puts("SIZE (0 —- 14)="); scanf("%d",&size); initgraph(&gd,&gm,""); outtextxy(150,150."THIS is the font"); getch(); closegraph(); }
Реализовав эту программу, вы сможете опробовать различные варианты шрифтов, направлений печати и размеров символов и получите при этом не­малое эстетическое удовольствие, за что мы с вами должны поблагодарить разработчиков графических средств системы TURBIC++.
На этом ваше краткое знакомство с программированием на языке С за­канчивается. На очереди изучение современного инструмента разработки программ на C/C++ — Borland C++ Builder.
Глава 2
ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ
ПРОГРАММИРОВАНИЕ И С++ BUILDER
Техника работы в С++ Builder
В настоящем разделе мы научимся («в нулевом приближении») работать с интегрированной средой разработки приложений Borland C++ Builder. Пакет является результатом развития системы программирования TURBO C++, ори­ентированной на WINDOWS. Весь материал относится к реализации системы в пятой и шестой версии пакета. Изучение техники работы с пакетом начнем с непосредственного создания простого приложения. В соответствии с тради­циями обучения работе с новыми для пользователя системами программиро­вания поставим себе задачу разработать приложение, которое всего лишь вы­водит на экран приветствие при своем запуске.
Прежде всего, создадим с помощью проводника Windows или любого фай­лового менеджера специальную папку для хранения проекта приложения. Пусть это будет каталог NewFold в корневой директории диска Ñ. То есть DOS-овский путь к папке выглядит как C:\NewFold. Теперь запускаем Builder и попадаем в его стартовое окно, изображенное на рис. 2.1.
По умолчанию программа открывается в состоянии, готовом к разработке 32-разрядного Windows-приложения, с чем мы и согласимся. Давайте для на­чала сохраним наш пока пустой проект в подготовленной папке. Для этого из пункта меню File нужно вызвать подпункт Save all или воспользоваться ком­бинацией клавиш Ctrl+Shift+S. Откроется окно перемещений по файловой системе, где вы должны войти в нашу папку NewFold и нажать кнопку Сохра- íèòü. Тем самым будет создан и сохранен файл главного текстового модуля с именем Unit1.cpp. Имя, конечно, можно и изменить, но мы оставим предла­гаемое по умолчанию. Затем здесь же будет предложено создать и сохранить файл проекта Project1.bpr. Давайте и с этим согласимся. Теперь, если вы за­глянете в папку проекта, вы обнаружите там готовый, но пока пустой проект, состоящий из нескольких файлов-заготовок. Самое главное то, что теперь можно закрыть Builder и назавтра или через год снова начать работу с проек­том. Давайте закроем и снова откроем программу. Вызвать проект можно че­рез пункт меню File, подпункт Open Project (Ctrl+F11), перейдя далее в папку проекта и открыв тот самый файл проекта Project1.bpr. Можно поступить и
Техника работы в С++ Builder 59
Ðèñ. 2.1
по-другому. Откройте пункт File, подпункт Reopen. Здесь вы увидите ссылку на нужный файл и, возможно, на другие недавно используемые файлы.
Итак, проект загружен. Давайте посмотрим, что система успела сделать автоматически без вашего участия. В папке проекта образовано несколько файлов, среди которых для нас интересен главный текстовый модуль Unit1.cpp. Для того, чтобы посмотреть содержимое этого файла, можно от­крыть его окно. Оно находится под окном формы Form1 на представленном выше рисунке. Щелкните мышью по области, частично скрытой формой, то есть в зоне, где написано Insert. Откроется листинг, представленный далее.
#include <vcl.h> #pragma hdrstop #include "Unit1.h" //—————————————————————————————————————­#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //—————————————————————————————————————­__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
60 Глава 2. Объектно-ориентированное программирование
Пока здесь практически ничего нет. Правда, мы уже понимаем, что к основному модулю подключаются два заголовка vcl.h è Unit1.h. Строка TForm1 *Form1; означает, что создается указатель Form1 на некий класс. Это — класс так называемой формы. Подробно о классах мы поговорим позднее, а сейчас просто примем к сведению это слово. Форма представляет собой обычное окно Windows, которое будет открываться при запуске изго­товленного приложения. В рабочем окне формы можно размещать различ­ные управляющие элементы, выводить результаты расчетов, рисовать графи­ки и делать многое другое. Пока же в нашей форме вообще ничего нет, и соответствующее окно будет иметь только стандартный инструмент закры­тия — крестик в правом верхнем углу.
Хотя мы называем проект пустым, из него можно изготовить приложе­ние, которое можно запустить на исполнение и которое, естественно, ничего делать не будет. Выберите пункт меню Run и подпункт с тем же названием или просто нажмите функциональную клавишу F9 на клавиатуре. Система выполнит компиляцию программы, редактирование связей (линковку) и за­пустит приложение. С открывшимся окном программы можно сделать только одно действие — закрыть его. Ведь наша первая программа ничего делать не умеет. Если вы заглянете в папку проекта, то обнаружите там новые файлы, в частности, исполняемый файл программы Project1.exe. Это и есть наша про­грамма, которую можно запускать уже и без Builder'а и даже на другом компь­ютере.
Теперь пойдем дальше и разместим на форме управляющую кнопку. Для начала сделайте так, чтобы активным стало окно формы, например, свернув окно текстового модуля. Нам понадобится обратиться к панели так называе­мых визуальных компонентов. Эта панель (см. рисунок выше) имеет множе­ство вкладок, среди которых по умолчанию открыта вкладка Standard. Она-то нам и нужна. Найдите на вкладке маленькую картинку, изображающую кноп­ку с названием ÎÊ, сделайте по ней щелчок левой кнопкой мыши, переведите мышиный курсор в любое место рабочего поля формы и снова сделайте щел­чок мышью. В результате на форме появится кнопка с именем Button1. Сде­лайте по ней двойной щелчок, и вы снова попадете в окно Unit1.cpp. Вы обна­ружите, что к предыдущему тексту добавлена конструкция:
void __fastcall TForm1::Button1Click(TObject *Sender) {
}
Это — функция обработки события, которое заключается в нажатии мышкой на управляющую кнопку (разумеется, если программа запущена).
На секунду прервем свою увлекательную работу по разработке приложе­ния и примем некоторые меры безопасности — сохраним изменения, сделан­ные в проекте. Для этого снова нажмем одновременно три клавиши Ctrl+Shift+S. Рекомендуется делать сохранения почаще во избежание непри­ятностей, которые могут возникнуть, например, при перебоях с электроэнер гией. Вернемся в окно главного текстового модуля. Кстати, чтобы сразу по
-
-