assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 93
Текст из файла (страница 93)
Содержание этого процесса стандартное, поэтому мы остановимся только на специфических моментах его реализации при разработке приложения на ассемблере. Для того чтобы включить меню в приложение, необходимореализовать следующую последовательность шагов.1. Разработка сценария меню. Перед тем как приступить к процессу включенияменю в конкретное приложение, разработаем его логическую схему. Этот шагнеобходим для того, чтобы уже на стадии проектирования обеспечить эргономические свойства приложения. Ведь меню — это один из немногих элементовинтерфейса, с которым пользователь вашего приложения будет постоянно иметьдело.
Поэтому схема меню должна иметь наглядную иерархическую структурус логически увязанными между собой пунктами, что поможет пользователюэффективно задействовать все возможности приложения. Для того чтобы вести предметный разговор, поставим себе задачу разработать для окна нашегоприложения главное меню. При этом мы исследуем возможности вывода в окноприложения текста и графики, а также покажем способы решения общих проблем, связанных с разработкой приложения. Наше меню будет довольно простым и состоять из трех пунктов: Текст, Графика и 0 приложении, — причем первые два пункта будут открывать доступ к подменю.
Иерархическая структураменю представлена на рис. 16.2.ТекстГрафикаО приложении -1 Отрезок— Примитивы —|—1— Прямоугольникт-— DrawText"— TextOut— Эффекты —г- Павлин'— КружеваРис. 16.2. Иерархическая структура меню2. Описание схемы меню в файле ресурсов. Для выполнения этого этапа требуются специальные операторы. В нашем случае файл ресурсов будет выглядетьследующим образом://Текст файла menu.rc#include"menu.h"MYHENU{MENUDISCARDABLEPOPUP "&Текст"{MENUITEM "&DrawText",IDM_DRAWTEXTMENUITEM "&TextOut",IDM_TEXTOUT}POPUP "&Графика"{POPUP "&Примитивы"{MENUITEM "&0трезок",IDMJ.ENGTHMENUITEM "&Прямоугольник", IDM_RECTANGLE>POPUP "&Эффекты"408Глава 16. Создание Windows-приложений на ассемблереMENUITEM "&Павлин", IDM_PEACOCKMENUITEM "&Кружева",IDM_LACES}}MENUITEM "&About",}IDM_ABOUT3.
Составление текста включаемого файла, необходимого для компиляции ресурсного файла. В нашем случае файл называется menu.h и выглядит следующимобразом:«define«define«define«define«define«define«define«defineMYMENU 999IDM_DRAWTEXT100IDM_TEXTOUT 101IDM_LENGTH 102IDM_RECTANGLE103IDM_PEACOCK 104IDMJ.ACES105IDM_ABOUT106В этом файле идентификаторам пунктов меню назначаются константы, которые впоследствии будут передаваться в оконную процедуру в младшем словепараметра wParam сообщения WM_COMMAND. Заметьте, что имени самого менютакже назначена константа.
К этому моменту мы вернемся чуть позже.4. Компиляция ресурсного файла. Для этого используется утилита brc32.exe:Ьгс32[ключи...]menu.гсЕсли утилита заканчивает свою работу нормально, то создается файл с расширением .res (menu.res). В случае, если утилита обнаруживает ошибки в исходном ресурсном файле, она выдает на экран соответствующие диагностическиесообщения. Для удобства работы с ними их можно записать в файл, перенаправив вывод сообщений с экрана в файл, используя оператор командной строкиЬгс32 [ключи ...] имя_файла.гс > Имя_Файла_Диагностикинапример, так:brc32 menu.гс > р5. Подключение меню на стадии регистрации того окна приложения, для работыс которым оно будет использоваться.
Для этого существуют два основных способа:D первый способ — поместить в поле IpszMenuName экземпляра структурыWNDCLASS (строка 101 листинга 16.4) указатель на поле, содержащее имяменю:.datamenu db "MYMENU".codemov dword ptr wcl.IpszMenuName, offset menuDвторой способ — назначить ресурсу меню символическую константу, которая расположена в поле имени оператора MENU файла ресурсов:56 M E N U D I S C A R D A B L E ; о п е р а т о р из файла ресурсовУглубленное программирование на ассемблере для Win32409Чтобы использовать упомянутую на последнем шаге символическую константу, необходимо вставить в файлы, из которых собирается приложение, дополнительные строки:ШФайл ресурсов:iiФайл menu.h:MYMENUMENUDISCARDABLEtfdefine MYMENU56si Файл menu.inc:MYMENUИequ56Строка 101 из листинга 16.4 должна выглядеть так:mov dword ptr w c l .
I p s z M e n u N a m e , MYMENUИли так:mov dword ptr wcl.IpszMenuName, 56Вторым способом мы фактически смоделировали макрос MAKEINTRESOURCE, известный Windows-программистам, пишущим приложения на языке C/C++.После внесения всех изменений в верхней части окна появится строка меню.Далее необходимо в оконную функцию включить команды, реализующие реакцию на выбор пунктов этого меню. Эта информация передается в младшем словеполя wParam сообщения WM_COMMAND.
В листинге 16.7 приведен измененный тексткаркасного приложения, дополненный меню.Листинг 16.7. Пример приложения с использованием меню<1> ;Пример приложения для W i n 3 2 с использованием меню<2> . 3 8 6<3> locals ;разрешает применение локальных меток в программе<4> .model flat, STDCALL;модель памяти flat,<5> ;STDCALL - передача параметров в стиле С (справа налево),<6> ;вызываемая процедура чистит за собой стек<7> include windowA.inc;включаемый файл с описаниями базовых структур;и констант Win32<8> include menu.incвключаемый файл с определением именидентификатор меню<9> ;0бъявление внешними используемых в данной программе;функций Win32 (ASCII):<10>extrnGetModuleHandleA:PROC<...><37>extrnGetClientRectiPROC<38>;объявление оконной функции объектом,;видимым за пределами данного кода<39>public WindowProc<40>.data<41>hwnddd 0<42>hlnstdd 0<43>;lpVersionInformationOSVERSIONINFO<?><44>wcl WNDCLASSEX <?><45>message MSG <?><46>ps PAINTSTRUCT <?><47>IpRect RECT<?><48>szClassName db 'Приложение Win32', 0<49>szTitleName db 'Каркасное приложение Win32 на ассемблере', 0<50>MesWindowdb 'Привет! Ну как вам процесс разработки приложенияна ассемблере?'<51>MesWindowLen=$-MesWindowпродолжение &410Глава 1 6.
Создание Windows-приложений на ассемблереЛистинг 16. 7 (продолжение)<52><53><54><55><56><57><58><59><60>playFi leCreate db ' c r e a t e . w a v ' , 0playFHePaintdb ' p a i n t . w a v ' , 0playFi leDestroy db ' d e s t r o y . w a v ' , 0.codestartproc near;точка входа в программу:;начало стартового кода<62><63><64><65><бб><67><68><69><70><71><72><73><74><75><76><77><78><79><80><81><82><83><84><85>;конец стартового кодаWinMain:<86><87><88><89><90><91><92><93><94><95><96><97><98><99><100><101><102><103><104><105><106><107><108><109><110>;строки 55-72 листинга 16.4;строки 75—100 л и с т и н г а 16.4mov dword ptr wcl .
IpszMenuName , MYMENU;строки 102-149 листинга 16.4startendp; ----- .......... -- ..... Wi ndowP roc ------- ...... ----- ..... - - - ...... - - WindowProc procarg @@hwnd: DWORD, @@mes:DWORD, @@wparam: DWORD, @@lparam: DWORDuses ebx, edi , esi , ebx ;эти регистры обязательно должны сохранятьсяlocal@@hdc: DWORDcmp @@mes, WM_DESTROYje wmdestroycmp @@mes, WM_CREATEje wmcreatecmp @@mes, WM_PAINTje wmpaintcmp @@mes, WM_COMMANDje wmcommandjmp defaultwmcreate:строки 176-212 листинга 16.4послать сообщение WM_QUITготовим вызов VOID PostQuitMessage(int nExitCode)push0callPostQuitMessagemoveax, 0 возвращаемое значение - 0jmpexit_wndprocwmcommand:; вызов процедуры обработки сообщений от меню;MenuProc (DWORD @@hwnd , DWORD @@wparam)push@@wparampush@@hwndcallMenuProcjmpexit_wndprocdefault:юбработка по умолчанию; готовим вызов LRESULT DefWindowProc (HWND hWnd UINT Msg;WPARAM wParam, LPARAM IParam)push@@lparampush@@wparampush@@mespush@@hwndcallDefWindowProcAjmpexit_wndproc<112> exi t_wndproc :<113>retУглубленное программирование на ассемблере для Win32<119><120><121><122><123><124><12S><126><127><128><129><130><131><132><133><134><135><136><137><138><139><140><141><142><143><144><145><146><147><148><149><150><151><152><153><154><1S5><156><157><158><159><160><161><162><163><164><165><166><167><168><169><170><171><172><173><174><175><176>WindowProc endp;MenuProc-.обработка сообщений от менюMenuProcprocarg@@hwnd:DWORD, @@wparam:DWORDusesebxlocal @@hdc: DWORDmov ebx, @@wparam;в bx идентификатор менюcmp bx, IDM_DRAWTEXTje@@idmdrawtextcmp bx, IDM_TEXTOUTje@@idmtextoutje@@idmlengthcmp bx, IDM_LENGTHcmp bx, IDM_RECTANGLEje@@idmrectanglecmp bx, IDM_PEACOCKje@@idmpeacockcmp b x , IDM_LACESje @@>idmlacescmp bx, IDM_ABOUTje @@idmaboutjmp @@exit@@idmdrawtext :;получаем контекст устройства HDC GetDC(HWND hWnd)push@@hwndcallGetDCmov@@hdc , eax;получаем размер рабочей области;BOOL GetClientRect(HWND hWnd, LPRECT IpRect)pushoffset IpRectpush@@hwndcallGetClientRectвыводим строку текста в окноint DrawText(HDC hDC, LPCTSTR IpString, int nCount ,LPRECT IpRect, UINT uFormat)pushDT_SINGLELINE+DT_BOTTOMpushpushoffset IpRect-1pushoffset @@TXT_DRAWTEXTpushoffset @@TXT_TEXTOUTpush@@hdccallDrawTextAосвобождаем контекст int ReleaseDC(HWND hWnd, HDC hDC)push@@hdcpush@@hwndcallReleaseDCjmp@@exit@@idmtextout :push@@hwndcallGetDC;получаем контекст устройстваmov@@hdc, eax;выводим строку текста в окно BOOL TextOut(HDC hdc, int nXStart,;int nYStart, LPCTSTR IpString, int cbString)pushlenTXT TEXTOUTpush150push10push@@hdccallTextOutApush@@hdcpush@@hwndcallReleaseDCjmp@@exit@@idmlength:pushосвобождаем контекст устройстваMB_ICONINFORMATION+MB_OKпоодолже411412Глава 16.