assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 94
Текст из файла (страница 94)
Создание Windows-приложений на ассемблереЛистинг 16.7 (продолжение)<177><178><179><180><181><182><183><184><185><186><187><188><189><190><191><192><193><194><195><196><197><198><199><200><201><202><203><204><205><206><207><208><209><210><211><212><213><214><215><216><217><218><219><220><221><222><223>pushoffset szTitleNamepushoffset @@TXT_LENGTHpush@@hwndcallMessageBoxAjmp@@exit@@idmrectangle:pushMB_ICONINFORMATION+MB_OKpushoffset szTitleNamepushoffset @@TXT_RECTANGLEpush@@hwndcallMessageBoxAjmp@@exit@@idmpeacock:pushMB_ICONINFORMATION+MB_OKpushpushpushcalljmp@@idmlaces :offset szTitleNameoffset @@TXT_PEACOCK@@hwndMessageBoxA@@exitpushpushpushcalljmp@@idmabout :offset szTitleNameoffset @@TXT_LACES@@hwndMessageBoxA@@exitpushpushpushpushpushcalljmpM.B_ICONINFORMATION+MB_OKMB_ICONINFORMATION+MB_OKoffset szTitleNameoffset @@TXT_ABOUT@@hwndMessageBoxA@@exiti • • •@@exit :mov eax , 0ret@@TXT@@TXT@@TXT@@TXT@@TXTABOUT dbLACES dbPEACOCKRECTANGLELENGTHdb@@TXT TEXTOUT'IDM ABOUT', 0'IDM LACES', 0db 'IDM PEACOCK', 0db 'IDM R E C T A N G L E 1 , 0'IDM LENGTH', 0db'Текст выведен функцией TEXTOUT'lenTXT TEXTOUT=$-@@TXT TEXTOUT@@TXT_DRAWTEXT db 'Текст выведен функцией DRAWTEXT'MenuProcendpend startСтроки 98-100 листинга 16.7 показывают, что для обработки сообщения WM_COMMAND вызывается процедура MenuProc.
Подход, при котором программа на ассемблере структурируется на более мелкие части с использованием механизмапроцедур, при программировании для Windows особенно полезен и должен бытьпреобладающим. Для большей наглядности мы не задействуем макрокоманды.Применение макрокоманд полезно и даже необходимо, так как они позволяют получать компактный и структурированный код.В заключение этого раздела обратитесь к файлам, прилагаемым к книге, гдев каталоге данной главы вы найдете все исходные тексты, необходимые для сборки и запуска приложения (см. листинг 16.7).
Собрав с помощью утилиты make.exeисполняемый файл, вы увидите, что реакция программы на выбор большинстваУглубленное программирование на ассемблере для Win32413пунктов меню стандартная и заключается в выводе сообщения с использованиемфункции Win32 API MessageBox. Определена реакция лишь на два пункта менюТекст — пункты DrawText и TextOut.
При их выборе на экран выводится текст. Темсамым демонстрируются различные способы вывода текста в окно приложения.Далее в материале этой и последующих глав мы определим реакцию и на остальные пункты меню.Давайте теперь рассмотрим еще одну ключевую проблему программированиядля Windows — перерисовку изображения. Для того чтобы понять ее смысл и важность, в любом порядке выберите пункты меню Текст > DrawText и Текст > TextOut Наэкране появятся строки текста. Далее сверните и разверните окно приложения.Строки текста исчезнут, оставив только строку, которая выводится как реакция насообщение WM_PAINT.
Причина этой ситуации в том, что Windows не хранит содержимое окна, и заботиться о его восстановлении после различных действий с окномдолжно приложение, создавшее это окно. Windows лишь посылает приложениюсообщение WM_PAINT в случаях, когда с окном были произведены некоторые действия, например, свертывание-развертывание окна, изменение его размеров и т. д.Приложение, получив сообщение WM_PAINT, в качестве реакции на него должнообновить в необходимой степени содержимое своего окна. Более подробно эта проблема и пути ее решения рассмотрены в любом хорошем учебнике по программированию для Windows. Отметим лишь, что в конечном итоге все сводится к необходимости организовать вывод в окно приложения как реакцию на сообщениеWM_PAINT.
Существует несколько подходов к решению проблемы перерисовки. Мырассмотрим наиболее общий и широко используемый.Перерисовка изображенияРассмотрим следующую абстракцию, цель которой — показать, что за содержимоеокон на экране отвечают оконные процедуры тех приложений, которым эти окнапринадлежат.
Роль Windows в этом процессе минимальна и состоит в том, что приопределенных действиях с окном оконной процедуре, отвечающей за связь с этимокном, посылается сообщение WM_PAINT. Получив это сообщение, оконная процедура должна уметь заново перерисовать содержимое всего окна или его части. Дляобщего случая это, если задуматься, не такая уж простая задача.Если у вас возникают трудности с пониманием этого момента работы приложений в Windows, попробуйте развить абстракцию со школьной доской. Представьте себе школьный класс, в котором процесс обучения выглядит очень необычно.Вместо обычной школьной доски на стене есть некоторая ограниченная область(экран монитора).
У каждого ученика (исполняемого файла) есть в портфеле своядоска (окно приложения), которая может (или не может, в зависимости от конструкции) менять свой размер. На всех учеников один комплект цветных мелков(контекст устройства), обладание которым разрешает ученику что-то рисовать насвоей доске. Ученик объясняется с присутствующими графическими образами,выводя их на свою доску. Но прежде доску нужно повесить на стену в пределахограниченной области.
Для этого ученик, как ему и положено, подымает руку. Учитель (Windows) обязательно помогает ученику выйти к ограниченной области настене (запускает на выполнение задачу) и повесить свою доску. Действия учителяи ученика в ходе этого процесса соответствуют определенному алгоритму и дей-414Глава 16. Создание Windows-приложений на ассемблерествиям каркасного приложения. В результате могут быть закрыты частично илиполностью доски учеников, вышедших к доске ранее и не ушедших пока на своиместа в классе. При этом информация в скрытых частях расположенных ниже досок других учеников уничтожается в пределах ограниченной области.Итак, доска ученика с помощью учителя повешена в пределах области на стене,и для того чтобы рисовать на ней, ученик должен попросить у учителя комплектмелков (см. функцию API GetDC или BeginPaint в листинге 16.4).
Если ученик егополучает, то он может начинать процесс рисования на своей доске. Как только ученик заканчивает этот процесс, он должен вернуть учителю комплект мелков (функция EndPaint). Далее ученик может закончить ответ и, забрав свою доску, занятьсвое место в классе (приложение завершило работу и «ушло» на диск). Если ученик делает это, то, забирая свою доску, он открывает доски других учеников, и...
наэтих досках обнаруживаются черные дыры, причем местоположение этих дыр соответствует местам, которые были скрыты доской их ушедшего товарища. Чтобысгладить этот конфуз, учитель срочно оповещает об этом (Windows посылает сообщение WM_PAINT) учеников, у которых было испорчено содержимое досок. Каждый из этих учеников должен, попросив у учителя комплект мелков, перерисоватьсодержимое своей доски.Данная абстракция довольно точно отражает логику работы Windows, причемне только в обозначенном нами контексте. Вы можете дополнить и развить еев нужную вам сторону.Как решается проблема перерисовки изображения практически? Для этого существует несколько способов, самый общий из которых заключается в использовании виртуального окна. Суть перерисовки изображения на основе виртуальногоокна заключается в использовании приложением некоторой области памяти длянаправления в него всего вывода программы.
Реальный вывод в окно приложенияосуществляется только как реакция на получение сообщения WM_PAINT. He забывайте, что программа с помощью функции InvalidateRectQ может сама себе послатьсообщение WM_PAINT, когда ей потребуется вывести новый фрагмент изображенияв окно приложения. Понятие виртуального окна настолько важно для организации работы Windows, что Win32 API содержит ряд функций, поддерживающихработу с этим окном: CreateCompatibleDCQ, SelectObjectQ, GetStockObjectQ, BitBltQ,CreateCompatibleBitmapQ и PatBltQ. Рассмотрим порядок их использования в реальном приложении.Работа с виртуальным окном в программе организуется в два этапа: созданиевиртуального окна и организация непосредственной работы с ним.
Создать виртуальное окно целесообразно при обработке сообщения WM_CREATE, то есть в моментсоздания окна приложения. Работать с этим окном можно в любое время, когдатребуется вывод в окно.Для наглядности обсуждения приведем фрагмент программы на языке C/C++:/ / ф р а г м е н т оконной процедуры из п р о г р а м м ы на я з ы к е C/C++case WM_CREATE://определить размеры экранаmaxX = GetSystemMetrics (SM_CXSCREEN);maxY = GetSystemMetrics (SM_CXSCREEN);//строим растровое изображение, совместимое с окномУглубленное программирование на ассемблере для Win32415hdc = GetDC (hwnd);memdc = CreateCompatibleDC (hdc);hbit = CreateCompatibleBitmap (hdc, maxX, maxY);SelectObject (memdc, hbit);//закрашиваем окно серым цветомhbrush = GetStockObject (GRAY_BRUSH);SelectObject (memdc, hbrush);PatBU (memdc, 0, 0, maxX, maxY, PATCOPY);ReleaseDC (hwnd, hdc);case WM_PAINT: //перерисовываем окноhdc = BeginPaint (hwnd, &paintstruct); //получаем дескриптор реального окна//копируем растровое изображение из памяти на экранBitBlt (hdc, 0, 0, maxX, maxY, memdc, 0, 0, SRCCOPY);E n d P a i n t (hwnd, &paintstruct); //освобождаем дескриптор...*//выводим в окно где-то в программеTextOut(memdc, X, Y, str, strlen(str)); //выводим строку//для немедленного вывода в окно вызываем функцию InvalidateRect:InvalidateRect (hwnd, NULL, 1);Физически виртуальное окно представляет собой растровое изображение, хранящееся в памяти.
Работа с этой областью памяти организуется так же, как и с окном приложения на экране монитора. Это означает, что для работы с ним необходимо создать контекст устройства памяти, совместимый с контекстом окна. Этодействие реализуется двумя функциями: с помощью функции GetDCQ приложение получает контекст окна; функция CreateCompatibleDCQ создает совместимыйс контекстом окна контекст памяти memdc. После этого функцией CreateCompatibleBitmapQ создается совместимое с реальным окном на экране растровое изображение.
Его размеры должны соответствовать размеру окна, для работы с которымоно строится. Поэтому предварительно с помощью функции GetSystemMetricsQдолжны быть получены размеры окна и переданы как параметры в функциюCreateCompatibleBitmapQ, которая возвращает дескриптор на созданное растровоеизображение. После этого функция SelectObjectQ выбирает созданное растровоеизображение в контекст памяти, который, в свою очередь, является совместимымс контекстом окна.