Ассемблерное программирование в Windows |
15.09.2004 |
||
Глава 5. Описание исходникаВ общем-то, приведенный исходный текст уже снабжен подробнейшими комментариями, поэтому рассмотрим здесь лишь основной смысл всех наших действий. Весь исходник для ясности мы разбили на 5 файлов. Первый файл «bloknot.asm» — это основной файл программы, в остальных файлах содержаться вспомогательные сведения: «bloknot.rc» — файл ресурсов. Здесь мы опишем структуру меню нашего приложения, и каждому пункту присвоим код сообщения, который он будет генерировать при его выборе. Кроме структуры меню в файле ресурсов может содержаться много другой информации, и для упрощения создания таких файлов в дальнейшем мы будем пользоваться специальной программой — редактором ресурсов. «def32.inc» — файл, содержащий присвоения имен стандартным константам, наиболее часто использующимся в приложениях Windows, а также описания трёх стандартных структур, использующихся для описания класса окна и передачи сообщений приложению. «kernel32.inc» — файл, содержащий объявления внешних функций и упрощающий их названия. Функции, отвечающие за управление программой. «user32.inc» — файл, содержащий объявления внешних функций и упрощающий их названия. Функции, отвечающие за оконный интерфейс. Файл ресурсов мы больше не трогаем — им будет пользоваться компилятор при сборке программы. Названия же оставшихся трех файлов прописываем в начало нашего основного файла bloknot.asm: include def32.inc ;Включить в исходник файл с определениями ;разных констант и структур. include kernel32.inc ;Включить файл с объявлениями внешних функций ;из библиотеки kernel32.dll. include user32.inc ;Включить файл с объявлениями внешних функций ;из библиотеки user32.dll, в которую входят все ;основные функции, отвечающие за оконный интерфейс. Это означает, что ассемблер при сборке программы вместо этих строчек подставит текст из этих файлов. Ниже следуют стандартные строки указания системы команд процессора и модели памяти — используем команды 386 процессора и плоскую модель памяти. Компьютер предоставит для программы с такой моделью память в виде сплошного пространства, и мы будем, в общем-то, не против… Теперь организуем сегменты программы — для неинициализированных, инициализированных данных и для кода: Директивой .data открываем сегмент инициализированных данных. В нём указываем несколько строковых констант, а также создаем структуру, помогающую описать класс основного окна. В структуру записываем известные параметры окна, а вместо неизвестных пока параметров ставим знаки вопроса. Директивой .data ? открываем сегмент неинициализированных данных (т.е. переменных). В нем создадим структуру, в которую будем считывать сообщения, приходящие в программу. Далее директивой .code открываем сегмент кода. Здесь, собственно, и начинается программа. Вначале нам надо создать основное окно приложения — базу нашей программы. Для этого напишем и зарегистрируем класс главного окна, дозаполнив структуру wc недостающими данными. Затем создадим само окно. В процессе дозаполнения структуры, вызовами соответствующих функций мы создаём иконку приложения и курсор мыши, и подключаем их к окну, передавая в структуру их идентификаторы. После создания окна управление должно передаться в цикл обработки сообщений, приходящих в программу. Организуем цикл обработки сообщений, работающий следующим образом: если пришло сообщение 0, значит выйдем из программы, иначе вызовем оконную процедуру для дальнейшей обработки сообщения. Замкнем цикл. Основная процедура завершена. Теперь напишем оконную процедуру, в которой будут обрабатываться все остальные сообщения (кроме уже обработанного сообщения о выходе из программы). Приходящее сообщение сначала проверяем на соответствие сообщению о закрытии окна. Если оно соответствует, то генерим сообщение о выходе из программы, и отправляем его в очередь сообщений. В следующем цикле обработки сообщений мы получим его и, не входя в оконную процедуру, выйдем из программы. Если сообщение не соответствует сообщению о выходе из программы, двигаемся дальше. Теперь нам надо перехватывать сообщения только от меню, поэтому если сообщение не от меню (не WM_COMMAND), то передадим его на обработку стандартной оконной процедуре, по умолчанию созданной операционной системой для нашего приложения. Иначе это сообщение от нашего меню, и мы обработаем его ниже. Идентификаторами пунктов меню у нас служат следующие по порядку цифры от 0 до 3, поэтому мы сможем организовать переключатель на соответствующие процедуры обработки пунктов меню довольно компактным образом. Запишем смещения к процедурам обработки в виде четырех следующих друг за другом значений: menu_handlers dd offset menu_about, offset menu_open dd offset menu_save, offset menu_exit а чуть выше организуем безусловный переход на адрес, составленный из идентификатора пункта (0, 1, 2 или 3), размерности смещений к процедурам (4 байта) и смещения к списку смещений: jmp dword ptr menu_handlers[eax*4] Идентификатор пункта меню содержится в регистре eax. Умножив на него размерность данных получим смещение к нужному смещению в списке смещений. По найденному таким образом нужному смещению и осуществляется переход на нужную нам подпрограмму. Подпрограммы организовывают вывод на экран окна с текстом, соответствующим выбранному пункту меню. В случае выбора пункта «Выход» отправляем сообщение о закрытии окна и возвращаемся в цикл нашей программы. Мы написали шаблонное приложение, которое можем использовать при создании любых других наших проектов. В программе мы использовали ряд API-функций. Подробное их описание на английском языке можно найти в файле win32.hlp, входящем пакет среды программирования любого языка высокого уровня. Поищите этот файл у себя в папке: «C:\Program Files\Common Files\Borland Shared\MSHelp». Русифицированную справку по большенству
API функций вы можете скачать |
|||
[Вернуться в начало] |
Глава
4 |
Глава 6–7 | [Оставить отзыв в гостевой] |