assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 88
Текст из файла (страница 88)
Windows предоставляет в распоряжение программиста ряд стандартных изображений указателей мыши и значков. В файле winuser.hсодержатся символические имена констант, обозначающих стандартные указатели мыши и значки. Обратите внимание на первый параметр функций LoadCursorA390Глава 16. Создание Windows-приложений на ассемблереи LoadlconA — hlnst Это дескриптор приложения, содержащий базовый адрес ресурса значка или указателя мыши, загруженного в процесс. Если используются ихстандартные изображения, то параметр hlnst равен NULLКоманды в строках 96-99 формируют поле hbrBackground, которое должно содержать значение дескриптора кисти. Кисть представляет собой ресурс в видешаблона пикселов, которым закрашивается некоторый объект, в данном случае —фон окна приложения некоторого класса.
Для получения такого дескриптора необходимо использовать функцию GetStockObject. В качестве параметра ей передается имя нужной кисти. В файле wingdi.h содержатся символические имена констант, определяющих стандартные кисти.В строке 101 в поле IpszMenuName записывается указатель на ASCIIZ-строкус именем меню. Если меню не используется (как в нашем случае), то в поле записывается значение NULLПоле hlconSm в строке 103 можно рассматривать как альтернативу полю hlcon.В него помещается дескриптор значка, который будет связан с данным классомокна.
Если поле hlconSm нулевое, то система будет использовать значок, определенный полем hlcon.И последнее действие при описании класса окна — присвоение данному классууникального имени. Это имя описано в виде ASCIIZ-строки в поле szClassName сегмента данных, и указатель на него формируется в поле IpszClassName (строка 102).После инициализации структуры необходимо зарегистрировать класс окнав системе. Это действие выполняется в строках 105-108 с помощью функцииRegisterClassExA, которой в качестве параметра передается указатель на структуруWNDCLASSEX.Необходимо заметить, что после того как класс окна зарегистрирован, структура WNDCLASSEX больше не нужна.
У вас появляется возможность сэкономить немного памяти. Это можно сделать, используя предоставляемый ассемблером типданных объединения либо инициализируя поля структуры в стеке с последующимих выталкиванием. Здесь есть широкое поле для экспериментов. Дерзайте!Создание окнаПосле того как класс окна описан и зарегистрирован в системе, приложение на егооснове может создать множество различных окон. Создание окна (строки 109-126)выполняется функцией Win32 API CreateWindowEx. Для этого ей нужно передатьмножество параметров.
Назначение их мы рассмотрим далее. В качестве результата функция возвращает уникальный дескриптор окна hWnd, который необходимосохранить (строки 37,125,126).У читателя, видимо, возникает вопрос, почему для создания окна необходимыдва шага: сначала определение класса окна, а лишь затем непосредственно его создание. Даже если не рассматривать этот вопрос в контексте концепции объектноориентированного программирования, двухэтапный процесс создания окна оченьудобен для практической работы.
В качестве наглядного примера приведем кнопки редактора MS Word. На самом деле это маленькие окна, созданные на базе одногокласса. Они используют одну оконную функцию, которая обрабатывает сообщения, посланные этим окнам. Какой именно кнопке послано сообщение, оконнаяКаркасное Windows-приложение на ассемблере391функция определяет по полю hwnd в структуре сообщения (см.
далее). Наличиеодного класса для всех кнопок гарантирует их одинаковое поведение. В то же время, каждая из кнопок может отличаться внешним видом. Но это уже дополнительные свойства конкретного окна-кнопки, которые задаются при создании экземпляра окна параметрами функции CreateWindowEx.Рассмотрим на примере Windows-приложения (см. листинг 16.4) задание значений параметров функции CreateWindowEx (строки 113-124).Строка 113. Параметр IpParam используется при создании окна для передачиданных или указателя на них в оконную функцию. Делается это следующим образом. Все параметры, передаваемые функции CreateWindowEx, сохраняются в создаваемой Windows внутренней структуре CREATESTRUCT. Поля этой структуры идентичны параметрам функции CreateWindowEx.
Указатель на структуру CREATESTRUCTпередается оконной функции при обработке сообщения WM_CREATE. Сам указательнаходится в поле IParam сообщения. Значение параметра IpParam функции CreateWindowEx находится в поле IpCreateParams структуры CREATESTRUCT.Строка 114. Параметр hlnst — дескриптор приложения, создающего окно.Строка 115. Параметр hMenu — дескриптор главного меню окна. Так как в данном варианте Windows-приложения меню у окна отсутствует, то параметр hMenuимеет нулевое значение.Строка 116.
Параметр hWndParent— дескриптор родительского окна. Междудвумя окнами Windows-приложения можно устанавливать родовые отношения.Дочернее окно всегда должно появляться в области родительского окна. Так каку нас подобных отношений нет, то значение передаваемого параметра нулевое.Строки 117-120. Параметры, загружаемые в стек этими строками, задают начальные координаты и размеры окна приложения на экране. Константа CW_USEDEFAULT (SOOOOOOOh), определенная в файле winuser.h, позволяет «попросить» Windows использовать значения этих параметров по умолчанию.Строка 121.
Параметр dwStyle определяет стиль окна приложения. Значениеэтого параметра задается константой или комбинацией констант. Символическиеимена этих констант описаны во включаемом файле winuser.h (Visual C++ 6.0).В нашем приложении используется значение WS_OVERLAPPEDWINDOW (OOOOOOOOh),которое задает стиль обычного перекрывающегося окна с рамкой, имеющего системное меню, кнопки свертывания, развертывания и закрытия окна в правом верхнем углу.Строки 122 и 123.
Параметры szTitleName и szQassName — их значения являютсяуказателями на ASCIIZ-строки (строки 44-45) с именем класса окна и текстом,помещаемым в заголовок окна.Строка 124. Параметр dwExStyle позволяет задать дополнительные стили окна.В Win32 API существует две реализации функции создания окна: стандартнаяCreateWindowA и расширенная CreateWindowExA. Для их вызова используются одинаковые параметры, за исключением последнего — dwExStyle.
При использованиифункции CreateWindowA параметр в стек помещать не требуется, при использовании CreateWindowExA параметр dwExStyle должен быть помещен в стек последним.Дополнительные стили можно задействовать вместе со стилями, задаваемыми параметром dwStyle.392Глава 16. Создание Windows-приложений на ассемблереСтрока 125. Вызов функции CreateWindowExA. В качестве результата функциявозвращает дескриптор окна hWnd. Он имеет уникальное значение и является одним из важнейших описателей объектов приложения.
Он передается как параметрмногим функциям Win32 API и как значение полей в некоторых структурах. Одновременно в приложении может быть создано и совместно существовать несколькоокон, поэтому с помощью дескриптора hWnd Windows однозначно идентифицирует то окно, для работы с которым вызывается та или иная функция Win32 API.Другой важный результат работы функции CreateWindowExA — посылка асинхронного сообщения WM_CREATE в оконную функцию приложения. В нашей программеобработка этого сообщения заключается в вызове функции PlaySoundA, котораявоспроизводит звуковой файл. Более подробно о сообщениях и их обработке поговорим далее.Отображение окнаВ случае успешного выполнения функции CreateWindowExA требуемое окно будетсоздано, но пока это произойдет лишь внутри самой системы Windows — на экране это новое окно пока еще не отобразится.
Для того чтобы созданное окно появилось на экране, необходимо применить еще одну функцию Win32 API — ShowWindowA. В качестве параметров этой функции передаются дескриптор hWnd окна,которое необходимо отобразить на экране, и константа, задающая начальный видокна на экране. В зависимости от значения последнего параметра окно отображается в стандартном виде, развернутым на весь экран или свернутым в значок. Описание символических констант, задающих начальный вид окна на экране, содержится во включаемом файле winuser.h. Строки 127-131 нашего Windows-приложениязадают отображение окна в стандартном виде.Если окно создано, то в него нужно что-то выводить — текст или графику.
Здесьесть несколько тонких моментов, выяснение которых позволит нам «поднятьсясразу на несколько ступеней» в понимании принципов работы Windows. Поэтомузадержимся немного. Тем более что в литературе этим моментам не всегда уделяется достаточно внимания — в лучшем случае десяток строк, большая часть которых уходит на обсуждение функций и их параметров, а не на разъяснение сутипроисходящих при этом процессов. Ход наших рассуждений будем подкреплятьпрактическими наблюдениями за работой приложения.
Для этого можно использовать утилиты, которые позволят нам наблюдать за сообщениями, циркулирующими в системе, и вызовами функций API. В качестве таких программных средствможно использовать утилиты, входящие в комплект компиляторов для языкаC/C++. Например, в состав Visual C++ входит утилита Spy++ (шпион), котораяпозволяет наблюдать за приложениями, находящимися в данный момент в системе. Неплохие результаты для Windows-приложений дает дизассемблер W32Dasm,информацию о котором можно найти по адресу http://www.expage.com/page/w32dasm.Если у вас нет ничего подобного под рукой, отчаиваться не стоит. Можно провести необходимые исследования опытным путем, просто меняя логику работыприложения. Суть этой методики состоит в комбинировании последовательностивыполнения функций Win32 API, воспроизводящих звуковые файлы и выводя-Каркасное Windows-приложение на ассемблере393щих текст на экран.