2 Выбор средств разработки
Исходя из технического задания, можно определить круг доступных средств разработки программного обеспечения.
Основными требованиями являются:
-
компилятор языка C и C++;
-
поддержка WinAPI (на уровне поддержки динамически подключаемых библиотек и файлов определения типов, или иначе – заголовков windows.h);
-
поддержка OpenGL (требование не строгое, поскольку существуют независимые реализации OpenGL, которые можно скомпилировать с программой в любом ANSI C компиляторе);
-
наличие удобной среды разработки, включающей в себя средства редактирования текста программы и средства отладки.
Анализ рынка компиляторов C и C++ в среде Windows позволил выявить несколько потенциально подходящих под указанные требования пакетов, информация о которых сведена в таблицу 2.
Таблица 2 – Компиляторы C, C++ в среде Windows
|
Название |
Описание |
Положительные стороны |
Отрицательные стороны |
|||
|
Microsoft Visual Studio |
Удобная среда разработки. Поскольку выпускается компанией Microsoft, поддержка WinAPI в этой среде реализована наиболее полно. Однако, поскольку компания Microsoft продвигает на рынке свою графическую библиотеку DirectX, поддержка OpenGL в этой среде минимальна. |
Очень удобный редактор и отладчик. Полная поддержка WinAPI. Быстрый и маленький по размеру код, генерируемый компилятором. |
Слабая поддержка OpenGL. |
|||
|
Borland C++ Builder |
Альтернативная среда разработки от компании Borland. Представляет собой среду визуального программирования, являющуюся надстройкой над Win API. Однако программирование на чистом WinAPI поддерживается. |
Также удобный редактор и отладчик. Поддержка WinAPI. Более полная, чем в Visual Studio поддержка OpenGL. |
Более медленный и громоздкий результирующий код, в результате подключения библиотеки визуальных компонентов. |
|||
|
MinGW |
Является свободно распостраняемым набором компиляторов (в том числе и C, C++), а также библиотек (в том числе и заголовочных файлов WinAPI и OpenGL). Все операции выполняются из командной строки, какой-либо редактор и отладчик отсутствует. |
Бесплатный компилятор. |
Отсутствие редактора и отладчика. |
|||
В результате сравнения, наиболее удобной и функциональной оказалась среда разработки Microsoft Visual Studio (рассматривалась версия 2008) и было принято решение использовать ее в качестве основного инструмента разработки.
3 Теоретические сведения
-
WinAPI
Функции, составляющие Win32 интерфейс, организованы в виде нескольких динамически подключаемых библиотек (DLL) и исполняемых файлов. Говоря о Win32 API, следует в первую очередь упомянуть три основные библиотеки:
-
Kernel32.dll. Эта библиотека предназначена для работы с объектами ядра операционной системы и ее функции позволяют управлять памятью и другими системными ресурсами;
-
User32.dll. Здесь сосредоточены функции для управления окнами - основным видом объектов операционной системы. Обработка сообщений, работа с меню, таймерами, все это выполняют функции этой DLL;
-
GDI32.dll. Эта библиотека, обеспечивающая графический интерфейс операционной системы (Graphics Device Interface). Функции управления выводом на экран дисплея, управления выводом принтера, функции для работы со шрифтами - все они входят в состав этой библиотеки.
Программа для Win32 обычно состоит из следующих блоков:
-
блок инициализации;
-
цикл обработки событий;
-
обработка сообщений главного окна.
Каждое окно принадлежит определенному классу окон. Окна одного класса имеют схожий вид, обслуживаются общей процедурой обработки событий, имеют одинаковые иконки и меню. Обычно каждое приложение создает для главного окна программы свой класс. Если приложению требуются дополнительные нестандартные окна, оно регистрирует другие классы. Стандартные диалоги и управляющие элементы принадлежат к предопределенным классам окон, для них не надо регистрировать новые классы. Чтобы определить новый класс окон, надо заполнить структуру WNDCLASS, содержащую следующие поля:
-
UINT style - стиль (поведение) класса окон;
-
WNDPROC lpfnWndProc - процедура обработки событий окна;
-
int cbClsExtra - размер дополнительной памяти в системной структуре класса для данных пользователя;
-
int cbWndExtra - размер дополнительной памяти в системной структуре окна для данных пользователя;
-
HINSTANCE hInstance - дескриптор модуля (экземпляра программы), в котором реализована процедура обработки;
-
HICON hIcon - дескриптор иконки окна;
-
HCURSOR hCursor - дескриптор курсора мыши для окна;
-
HBRUSH hbrBackground - дескриптор "кисточки" для закрашивания фона окна;
-
LPCSTR lpszMenuName - имя ресурса, содержащего меню окна;
-
LPCSTR lpszClassName - имя класса.
Класс регистрируется при помощи функции:
WORD WINAPI RegisterClass(const WNDCLASS *lpwc)
При успешном завершении функция возвращает целочисленный код, соответствующий строке-имени класса в общесистемной таблице строк (такой код называется атомом). При ошибке возвращается 0.
Для создания окна вызывается функция:
HWND WINAPI CreateWindow(
LPCSTR lpClassName, /* имя класса */
LPCSTR lpWindowName, /* имя окна (заголовок) */
DWORD dwStyle, /* стиль (поведение) окна */
int x, /* горизонтальная позиция окна на экране */
int y, /* вертикальная позиция окна на экране */
int nWidth, /* ширина окна */
int nHeight, /* высота окна */
HWND hWndParent, /* дескриптор родительского окна */
HMENU hMenu, /* дескриптор меню */
HANDLE hInstance, /* дескриптор экземпляра программы */
LPVOID lpParam /* указатель на какую-нибудь ерунду */
)
Вместо параметров x, y, nWindth, nHeight можно передавать константу CW_USEDEFAULT, позволяющую операционной системе задать эти числа по ее усмотрению.
Интерпретация кода стиля определяется классом окна. Стиль определяет не только оформление окна, но и его поведение. Общие для всех классов константы стилей (при необходимости объединяются операцией побитовое ИЛИ):
WS_DISABLED - при создании окно заблокировано (не может получать реакцию от пользователя);
WS_VISIBLE - при создании окно сразу же отображается (не надо вызывать ShowWindow);
WS_CAPTION - у окна есть строка заголовка;
WS_SYSMENU - у окна есть системное меню;
WS_MAXIMIZEBOX - у окна есть кнопка разворачивания;
WS_MINIMIZEBOX - у окна есть кнопка сворачивания;
WS_SIZEBOX или WS_THICKFRAME - у окна есть рамка изменения размеров;
WS_BORDER - у окна есть рамка (не подразумевает изменение размеров);
WS_HSCROLL или WS_VSCROLL - у окна есть горизонтальная или вертикальная прокрутка;
WS_OVERLAPPED или WS_TILED - "перекрываемое" окно - обычное окно с рамкой и строкой заголовка;
WS_POPUP - "всплывающее" окно;
WS_OVERLAPPEDWINDOW - "перекрываемое" окно с системным меню, кнопками сворачивания/разворачивания, рамкой изменения размеров, короче, типичный стиль для главного окна приложения.
Во время выполнения функции CreateWindow процедуре обработки событий окна посылается сообщение WM_CREATE. При успешном выполнении функции возвращается дескриптор созданного окна, при неудаче - NULL.
После создания окна запускается так называемый цикл обработки сообщений:
MSG msg;
while(GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Функция GetMessage() извлекает сообщение из очереди сообщений и помещает его в структуру lpMsg типа MSG. Если сообщений в очереди нет, то текущий поток переводится в состояние ожидания и досрочно отдает управление другим потокам.
Возвращаемое значение:
Если функция извлекает сообщение отличное от WM_QUIT, то функция возвращает ненулевое значение.
Если функция извлекает сообщение WM_QUIT, то она возвращает 0.
Если произошла ошибка, то функция возвращает -1.
lpMsg - указатель на структуру куда будет помещено сообщение;
hWnd - хэндл окна для которого извлекается сообщение, если указать 0, то функция GetMessage() будет извлекать сообщения для всех окон;
wMsgFilterMin - нижняя граница диапазона извлечения, например, если указать 10, то будут извлекаться сообщения с кодами сообщений начиная с 10, если указать ноль, то граница отсутствует;
wMsgFilterMax - верхняя граница диапазона извлечения, например, если указать 300, то будут извлекаться сообщения с кодами сообщений до 300, если указать ноль, то граница отсутствует.
Функция TranslateMessage() транслирует сообщения от клавиатуры. Она переводит сообщения виртуальных клавиш (Virtual-key) в символьные сообщения.
Сообщения, обработанные в цикле обработки, передаются оконной процедуре.
Оконная процедура - функция обработки событий (сообщений). Она вызывается самой операционной системой Windows и получает ряд параметров: хэндл окна - hWnd, код сообщения - msg и два параметра lParam и wParam. Оконная процедура может иметь любое имя.
Система отправляет сообщение оконной процедуре, пересылая данные сообщения как параметры процедуры. Затем оконная процедура исполняет соответствующее действие с сообщением; она проверяет код сообщения и, при обработке сообщения, использует информацию, заданную его параметрами.
Оконная процедура обычно не игнорирует сообщение. Если она не обрабатывает сообщение, то должна отправить сообщение обратно системе для обработки по умолчанию. Оконная процедура делает это путем вызова функция DefWindowProc, которая исполняет заданное по умолчанию действие и возвращает какое-то значение, как результат обработки сообщения. Оконная процедура должна тогда возвратить это значение как свой собственный результат обработки сообщения. Большинство оконных процедур обрабатывает только несколько сообщений и передает остальные в систему путем вызова DefWindowProc.
Поскольку оконная процедура совместно используется всеми окнами, принадлежащими к одному и тому же классу, она может обрабатывать сообщения для нескольких различных окон. Чтобы идентифицировать заданное окно, на которое надо воздействовать сообщением, оконная процедура может проверить дескриптор окна, переданный с сообщением.
