Создание меню без файла описания ресурсов на основе функции LoadMenuIndirect
Министерство образования Российской Федерации
Институт переподготовки кадров
Уральского государственного технического
университета
Кафедра микропроцессорной техники
Курсовая работа
ТЕМА: Создание меню без файла описания ресурсов на
основе функции LoadMenuIndirect.
Руководитель доц., к.т.н. В.П.Кулюкин
Слушатель гр. СП-923
И.Г.
г.Нягань
2001г.
Введение.
Известно, что к
программированию на языке ассемблера обращаются тогда, когда от программы
требуется максимальная скорость исполнения, когда необходимо обеспечить
взаимодействие с нестандартными внешними устройствами, когда необходимо
полностью использовать
возможности процессора и
операционной системы. На языке ассемблера можно запрограммировать все, на что
способна соответствующая вычислительная машина, то есть ассемблер является
машинно-ориентированным языком программирования. Программируя на ассемблере
иногда в силу привычки, иногда в силу необходимости, особенно при организации
интерфейса пользователя, приходится многократно программировать одни и те же
элементарные задачи. В языках высокого уровня эта проблема решена применением
стандартных функций и процедур. В ассемблере эта проблема могла бы быть решена
за счет библиотек стандартных функций как на уровне исходных текстов, так и
объектных кодов, но такие библиотеки не стандартизованы и не распространяются
вместе с компиляторами. С появлением Windows 95 ситуация несколько
изменилась. Создание приложений на языке ассемблера представляет собой весьма
сложную задачу в связи с высоким уровнем интеграции прикладной программы и
операционной системы, но теперь нет необходимости многократно решать проблемы
пользовательского интерфейса и управления исполнением команд на уровне машинных
команд [I]. Они решаются теперь с помощью операционной системы
за счет обращения к функциям интерфейса прикладного программирования – Application Programming Interface (API).
Программирование
пользовательского интерфейса с применением функций Win32 API
основано на использовании так называемых ресурсов. Ресурсами являются
соответствующим образом оформленные данные, используемые операционной системой
для создания внешнего отображения органов управления приложением, и средства,
обеспечивающие ввод данных в процессе исполнения программы в режиме диалога.
Ресурсы описываются в текстовом файле с расширением
rc. Файл ресурсов после обработки компилятора ресурсов и
получения двоичного файла с расширением res с помощью
компоновщика объединяется с исполняемым файлом.
Общая часть.
Наиболее очевидным средством
управления приложением является меню. Строкаа меню выводится на экран
непосредственно под строкой заголовка. Это меню называется главным. Выбор
элемента меню влечет за собой выдачу приложения сообщения WD_COMMAND,
содержащего идентификатор пункта меню. Идентификаторы анализируются в оконной
процедуре приложения, что обеспечивает соответствующую реакцию на полученное
сообщение. Каждый пунк меню определяется тремя характеристиками. Первая
определяет то, что будет отображаться в данном пункте меню – это либо строка
текста, либо картинка. Вторая характеристика определяет либо константу,
посылаемую оконной процедуре сообщении WM_COMMAND,
либо всплывающее меню, которое выводится на экран, когда пользователь выбирает
данный пункт меню. Третья характеристика указывает, является ли данный пункт
меню разрешенным (enabled), запрешенным (disabled),
недоступным (grayed) или помеченным (checked). Эта
характеристика пункта меню не является обязательной.
Для того, чтобы включить меню
в приложение, необходимо реализовать следующую последовательность шагов:
·
разработать сценарий меню. Перед
тем как приступить к процессу включения меню в конкретное приложение,
разработаем логическую схему. Этот шаг необходим для того, чтобы уже на стадии
проектирования обеспечить эргономические свойства приложения. Ведь меню – это
один из немногих элементов интерфейса, с которым пользователь постоянно будет
иметь дело. Поэтому схема меню должна иметь наглядную иерархическую структуру,
с логически увязанными между собой пунктами этой иерархии, что поможет
пользователю эффективно использовать все возможности приложения. Для того,
чтобы вести предметный разговор, поставим себе задачу разработать для окна
нашего приложения главное меню. При этом мы исследуем возможности вывода в окно
приложения текста и графики, а также покажем способы решения общих проблем,
связанных с разработкой приложения. Наше меню достаточно простое и состоит из
трех элементов: “Текст”,”Графика”,”О приложении”. Иерархическая структура меню
представлена.
·
описать схему меню в файле
ресурсов. Для выполнения этого описания используются специальные операторы.
·
составить текст включаемого файла,
необходимого для компиляции ресурсного файла
·
компилировать ресурсный файл.
·
подключить меню на стадии
регистрации того окна приложения, для работы с которым оно будет
использоваться.
Меню можно создать тремя
способами. Можно определить меню в файле описания ресурсов, создать меню без
файла описания ресурсов непосредственно в программе с помощью функций CreatMenu, AppendMenu и InsertMenu или с помощью функции LoadMenuIndirect,
создав предварительно структуру MENUITEMPLATE. Наиболее простым и понятным при программировании под
Windows95 на языке ассемблера является определение меню в
файле описания ресурсов с помощью любого текстового редактора.
Основная часть.
Моя задача заключается в том,
чтобы написать программу на тему: “Создать меню без файла описания ресурсов на
основе функций LoadMenuIndirect”.
Одним из средств создания
меню без использования файла описания ресурсов является функция LoadMenuIndirect. Для применения этой функции необходимо создать
шаблон меню, определяемый структурами
MENUITEMTEMPLATEHEADER
и MENUITEMTEMPLATE.
Полный шаблон меню состоит из заголовка и хотя бы
одного описания пункта меню. Заголовок – структура MENUITEMTEMPLATEHEADER – cостоит из двух полей размером в слово. В первом слове
содержится номер версии функции. Для Windows NT и Win16
это 0, для Windows95-1. Во втором слове содержится смещение до первой
структуры MENUITEMTEMPLATE. Если между заголовком и описанием первого пункта
меню нет дополнительной информации, это поле содержит 0.
Описания пунктов меню,
следущие за заголовком, должны быть выравнены на границе двойного слова.
Структура MENUITEMTEMPLATE имеет, как правило, пять полей. Шестое поле имеет
смысл для пункта меню, указывающего на всплывающее меню.
В качестве примера приводится окно с главными и
всплывающими меню, созданными с помощью функции LoadMenuIndirect.
Программа.
p386
jumps
model flat,STDCALL
include win32.inc
;файл описания структур и констант
L equ
<LARGE>
IDM_QUIT equ 100
IDM_ABOUT equ 101
MF_ENABLED equ 0
MF_POPUP equ 1h
;Функции Win32
API, используемые программой
extrn
BeginPaint:PROC
extrn
CreateWindowExA:PROC
extrn
DefWindowProcA:PROC
extrn
DispatchMessageA:PROC
extrn
EndPaint:PROC
extrn
ExitProcess:PROC
extrn
GetMessageA:PROC
extrn
GetModuleHandleA:PROC
extrn
LoadCursorA:PROC
extrn
LoadIconA:PROC
extrn
RegisterClassA:PROC
extrn
PostQuitMessage:PROC
extrn
ShowWindow:PROC
extrn
TranslateMessage:PROC
extrn
UpdateWindow:PROC
extrn
LoadMenuIndirectA:PROC
extrn
MessageBoxA:PROC
.data
lppaint
PAINTSTRUCT <?>
msg MSGSTRUCT
<?>
wc
WNDCLASS <?>
hInst
dd 0
fl
dw 0
szTitleName
db 'Это наше окно',0
szClassName
db 'ASMCLASS32',0
szHello db 'Привет!',0
szAppName db 'Сообщение',0
hMenu
dd 0
align 4
MenuTemplate dw 1,0 ;Заголовок меню. 1 - признак
;структуры
для функции Windows95
align 4
dd 0 ;тип
пункта
dd 0,MF_ENABLED,0;IDM_ABOUT ;
dw 81h
dw '&','M','e','n','u','1',0
align 4
dd 0,0,0,IDM_QUIT
dw 0
dw 'E','&','x','i','t',0,0
align 4
dd 0,0,IDM_ABOUT
dw 0
dw '&','Q','u','i','t','1',0
align 4
dd 0,0,0;IDM_QUIT
dw 81h ;Признак вспл.
меню
dw 'Q','u','i','t','2',0,0,0
align 4
dd 0,0,IDM_ABOUT
dw 0
dw 'Q','u','i','t','3',0,0
align 4
dd 0,0,IDM_QUIT
dw 80h
dw 'E','&','x','i','t',0,0
.code
start:
push L
0
call
GetModuleHandleA
mov
[hInst], eax
;инициализация
структуры WndClass
mov
[wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
mov
[wc.clsLpfnWndProc], offset WndProc
mov
[wc.clsCbClsExtra], 0
mov
[wc.clsCbWndExtra], 0
mov
eax, [hInst]
mov
[wc.clsHInstance], eax
push L
IDI_APPLICATION
push L
0
call
LoadIconA
mov
[wc.clsHIcon], eax
push L
IDC_ARROW
push L
0
call
LoadCursorA
mov
[wc.clsHCursor], eax
mov
[wc.clsHbrBackground], COLOR_WINDOW + 1
mov
dword ptr [wc.clsLpszMenuName],0
mov
dword ptr [wc.clsLpszClassName], offset szClassName
push
offset wc
call
RegisterClassA
push offset MenuTemplate
call LoadMenuIndirectA
mov [hMenu],eax
push L
0 ; lpParam
push
[hInst] ; hInstance
push
[hMenu] ; menu
push L
0 ; parent hwnd
push L
CW_USEDEFAULT ; width
push L
CW_USEDEFAULT ; y
push L
CW_USEDEFAULT ; x
push L
WS_OVERLAPPEDWINDOW ; Style
push
offset szTitleName ; Title string
push
offset szClassName ; Class name
push L
0 ; extra style
call
CreateWindowExA
mov
[newhwnd], eax
push L
SW_SHOWNORMAL
push
[newhwnd]
call
ShowWindow
push [newhwnd]
call
UpdateWindow
msg_loop:
push L
0
push L
0
push L
0
push
offset msg
call
GetMessageA
cmp
ax, 0
je
end_loop
push
offset msg
call
TranslateMessage
push
offset msg
call
DispatchMessageA
jmp
msg_loop
end_loop:
push
[msg.msWPARAM]
call
ExitProcess
; we never
get to here
;----Оконная
процедура----
WndProc proc uses
ebx edi esi, hwnd:DWORD, wmsg:DWORD,\
wparam:DWORD,
lparam:DWORD
LOCAL
hDC:DWORD
cmp
[wmsg], WM_DESTROY
je
wmdestroy
cmp
[wmsg], WM_SIZE
je
wmsize
cmp
[wmsg], WM_CREATE
je
wmcreate
cmp
[wmsg],WM_PAINT
je
wmpaint
;**************************************
cmp [wmsg],WM_COMMAND
je wmcommand
;**************************************
jmp
defwndproc
wmcommand:
mov eax,lparam
cmp ax,0
jne m1
mov eax,wparam
cmp ax,IDM_ABOUT
jne m2
call MessageBoxA,0,offset
szHello,offset szAppName,MB_OK
jmp m1
m2: cmp ax,IDM_QUIT
jne m1
push 0
call PostQuitMessage
m1: mov eax,0
jmp finish
wmcreate:
mov
eax, 0
jmp
finish
defwndproc:
push
[lparam]
push
[wparam]
push
[hwnd]
call
DefWindowProcA
jmp
finish
wmdestroy:
push L 0
call PostQuitMessage
mov
eax, 0
jmp
finish
wmsize:
mov
eax, 0
jmp
finish
wmpaint:
push
offset lppaint
push
[hwnd]
call
BeginPaint
mov
[hDC],eax
push offset
lppaint
push
[hwnd]
call EndPaint
mov
eax,0
jmp
finish
finish:
ret
WndProc
endp
;---------------------------------
public WndProc
end start