Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прогр. в граф. ОС.doc
Скачиваний:
0
Добавлен:
21.02.2020
Размер:
167.94 Кб
Скачать

Федеральное агентство по образованию

Государственное образовательное учреждение

высшего профессионального образования

«Омский государственный технический университет»

А.Н. ФЛОРЕНСОВ

Программирование в графических операционных системах Методические указания к лабораторным работам

ОМСК 2007

Составитель Флоренсов А.Н.

Предназначены для профессиональной подготовки студентов и бакалавров направления «Информатика и вычислительная техника» по дисциплине "Программирование для графических операционных систем".

Печатается по решению редакционно-издательского совета Омского государственного технического университета.

Редактор Н.Н. Пачула

ИД №06039 от 12.10.2001

Сводный темплан 2006.

Подписано к печати . Бумага офсетная.

Формат 6084 1/16. Отпечатано на дупликаторе.

Усл. печ. л. 2,0. Уч.-изд. л. 2,0.

Тираж 150 экз. Заказ

Изд-во ОмГТУ. 644050, г. Омск, пр. Мира, 11

Типография ОмГТУ.

Лабораторная работа №1

Содержание работы. Ознакомление со строением программы графического приложения в MS Windows.

Предварительные сведения

Упрощенное стандартное строение главной части программы приложения для MS Windows имеет вид

int WINAPI WinMain(HINSTANSE hInst,

HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{HWND hwnd;

MSG msg;

WNDCLASS ws;

. . . // заполнение и вычисление полей структуры ws. (Этап С.)

rc=RegisterClass(&ws); // (Этап D.)

// сюда вставить проверку rc — удалось ли зарегистрировать класс

hwnd=CreateWindow( . . .); // (Этап E.)

// сюда вставить проверку hwnd на не нуль

ShowWindow(hwnd, nCmdShow); // (Этап F.)

while(GetMessage(&msg, 0, 0, 0)) // (Этап G.)

DispatchMessage(&msg);

return 0; // (Этап H.)

}

Процедура обслуживания окна должна иметь заголовок, строго отвечающий описанию в прототипе. Прототип процедуры обслуживания окна в 32-битной Windows имеет вид

LRESULT WINAPI WndProc(HWND hwnd, UINT tmsg,

WPARAM wPar, LPARAM lPar);

Процедура окна представляет собой по существу диспетчер обработки сообщений, поступающих в окно. По своей структуре основная часть процедуры окна представляет собой управляющую конструкцию выбора из множества вариантов и имеет на языке Си вид

switch (tmsg)

{case номер_сообщения:

действия по обработке этого сообщения;

break;

case номер_другого_сообщения:

действия по обработке этого сообщения;

break;

case номер_еще_одного_сообщения:

действия по обработке этого сообщения;

break;

. . .

default:

return вызов_функции_стандартной_обработки сообщения;

}

причем функция стандартной обработки сообщения вызывается с теми же самыми аргументами, что и получила в своем заголовке процедура окна. Функция стандартной обработки сообщения в Windows имеет имя DefWindowProc.

Простейший пример построения процедуры окна в Windows имеет вид

LRESULT WINAPI PrimWinProc(HWND hwnd, UINT tmsg,

WPARAM wPar, LPARAM lPar)

{switch(tmsg)

{case WM_LBUTTONDOWN:

{MessageBox(NULL, "Текст сообщения …",

"Заголовок окна сообщения ",

MB_OK | MB_ICONINFORMATION);

return 0;

}

case WM_RBUTTONDOWN:

{MessageBox(NULL, " Текст сообщения …",

"Заголовок окна сообщения",

MB_OK | MB_ICONINFORMATION);

return 0;

}

case WM_DESTROY:

{PostQuitMessage(0);

return 0;

}

}

return DefWindowProc(hwnd, msg, wPar, lPar);

}

Заполнение полей экземпляра wc структуры WNDCLASS с последующей регистрацией класса окна может быть выполнено последовательностью операторов

memset(&wc, 0, sizeof(wc));

wc.lpszClassName="MyClass1";

wc.lpfnWndProc= PrimWinProc;

wc.hCursor=LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

wc.hInstance= hInstance; // заданы только минимально

// необходимые поля

if (!RegisterClass(&wc)) return FALSE;

Главная часть программы, представляющая собой, с точки зрения языка Си, главную функцию программы, в системных соглашениях этого языка имеет обязательное имя main. При разработке системы программирования графических приложений для Windows было принято более частное соглашение от Microsoft, что главная функция должна иметь имя WinMain. Выбор конкретного варианта соглашения осуществляется компоновщиком. Если компоновщик вызывается неявно программой транслятора, то этот выбор определяется соответствующей опцией транслятора. Для транслятора Borland/Inprise по умолчанию используется главная функция с именем main. Для указания, что должно быть построено графическое приложение с главной функцией WinMain, в вызове транслятора используется опция –tW. Таким образом, трансляция простейшего графического приложения с исходным файлом prog.c на языке Си должна вызываться командной строкой

BCC32 -tW prog.c

При этом следует учитывать, что регистр букв (строчные или прописные) при задании опций должен строго учитываться.

Построить графическое приложение для Windows можно с использованием стандартного имени главной функции. Такой подход более универсален, поскольку позволяют использовать его из неспециализированных для Windows систем разработки программ. (Например, при программировании графических приложений на ассемблере.)

Существо универсального подхода заключается в использовании системных функций API для получения значений тех специальных аргументов, которые спроектированы для приложений Windows. Этими аргументами будут первый и два последних из списка аргументов прототипа функции WinMain, т. е. HINSTANCE hInst, LPSTR lpCmdLine и int nCmdShow. Второй из этих аргументов по содержанию аналогичен второму аргументу стандартного заголовка функции main, но может быть также получен вызовом системной функции GetCommandLine, которая имеет прототип

LPTSTR GetCommandLine(VOID).

Для получения хэндла экземпляра графического приложения следует воспользоваться системной функцией GetModuleHandle, которая имеет прототип

HMODULE GetModuleHandle( LPCTSTR lpModuleName)

и при нулевом указателе в качестве аргумента возвращает хэндл для текущего процесса, который в 32-битной версии Windows и служит требуемым хэндлом экземпляра приложения.

Несколько сложнее получить последний аргумент для списка функции WinMain. Для его получения следует использовать функцию GetStartupInfo, которая, при значении STARTF_USESHOWWINDOW, установленном в поле dwFlags получаемого от нее экземпляра структуры STARTUPINFO, в поле wShowWindow содержит переданное запускаемому приложению значение параметра видимости nCmdShow.

Таким образом, при ориентации на универсальную стартовую функцию языка Си начало главной программы будет иметь вид

int main(int argn, char** argv) // заголовок главной функции

{HINSTANCE hInst;

STARTUPINFO si;

int nCmdShow;

FreeConsole();

GetStartupInfo(&si);

if (si.dwFlags & STARTF_USESHOWWINDOW)

nCmdShow=si.wShowWindow;

else nCmdShow=SW_SHOWDEFAULT;

hInst = GetModuleHandle (NULL);

// следующие этапы

Поскольку системы разработки программ от Borland/Inprise и Microsoft являются коммерческими, то для учебного процесса и, особенно для домашней подготовки к лабораторным работам, практическое значение представляют свободно распространяемые программные продукты, которые имеют соответствующие лицензии на такое свободное использование. Наиболее значимое место среди них представляют программные продукты по лицензии GNU.

Среди них к настоящему времени имеются и системы разработки программ на языке Си, включающие средства разработки приложений для Windows. Наиболее известной из них является система MinGW. Это название является сокращением от Minimalist GNU for Win32. Все материалы по ней можно получить на сайте http://www.mingw.org

Эта система среди прочего имеет коллекцию трансляторов, вызываемых через исполняемый файл gcc. Опции этого исполняемого файла совершенно такие же, как известно из программирования под ОС Linux. В частности, трансляция исходного файла с языка Си, имеющего имя prog.c, в простейшем случае задается командной строкой

gcc prog.c

Получаемый при этом исполняемый файл по умолчанию имеет имя a.out, поэтому в Windows естественно использовать опцию принудительного переименования выходного файла, например, в виде

gcc prog.c –o prog.exe

Рассмотренные простейшие формы вызова транслятора GNU C предполагают стандартное имя главной функции программы. Поэтому при желании использовать соглашение Microsoft о форме и имени главной функции нужно указывать соответствующую опцию, которая для данной системы имеет вид ‑mwindows. Таким образом, использование транслятора GNU С для получения графического приложения из исходного файла prog.c будет вызываться командной строкой

gcc –mwindows prog.c –o prog.exe

Задание. Разработать в Windows программу простейшего графического приложения, которая обрабатывает сообщения WM_DESTROY и WM_LBUTTONDOWN с выдачей сообщения о нажатии клавиши стандартной функцией MessageBox.

Провести программные эксперименты:

  • как изменится функционирование программы, если из нее исключить обработку сообщения WM_DESTROY;

  • как изменится функционирование программы, если поле hCursor рабочего экземпляра структуры WNDCLASS задается нулевым;

  • как изменится функционирование программы, если поле hbrBackground задается числовым значением 4, 3, 1, 0.

По встроенной документации найти возможные значения четвертого параметра функции MessageBox и провести эксперименты по использованию трех любых из них.

Результаты объяснить.

Контрольные вопросы

1. Какие последствия для последующих запусков приложения имеет отсутствие обработки сообщения WM_DESTROY?

2. В чем особенность поведения окна после его перекрытия другим окном, если в качестве хэндла для параметра в поле hbrBackground структуры WNDCLASS используется значение 0?

3. Как изменится функционирование графического приложения, если оно запускается из консольного окна, использует в качестве главной функции main() и не выполняет вызов FreeConsole()?

4. Как изменится функционирование графического приложения, если в завершающей части процедуры окна программа не будет использовать вызов функции DefWindowProc(), в частности используя вместо него просто return 0?