Суббота, 19.07.2025, 05:48 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 3. Понятие ресурса. Редакторы и трансляторы ресурсов(2)

Рассмотрим теперь, как работает эта программа.

  1. Файл ресурсов должен быть Вам понятен, так как все используемые там ресурсы были подробно рассмотрены ранее. Замечу только, что файл ресурсов содержит сразу несколько элементов. При этом все ресурсы, кроме диалогового окна, должны иметь идентификатор. Для диалогового окна определяющим является его название, в нашем случае это DIAL1.
  2. Перед тем как вызвать диалоговое окно, демонстрируется то, как нужно работать с таким ресурсом, как строка. Как видите, это достаточно просто. При помощи функции LoadString строка загружается в буфер, после чего с ней можно работать, как с обычной строкой.
  3. Вызов диалогового окна достаточно очевиден, так что перейдем сразу к процедуре диалогового окна. Начнем с сообщения WM_INITDIALOG. Это сообщение, как и сообщение WM_CREATE для обычного окна, приходит один раз при создании окна. Это весьма удобно для проведения какой-то начальной инициализации. Мы используем это для определения иконки диалогового окна. В начале загружаем иконку, а далее посылаем сообщение установить иконку для данного окна (WM_SETICON). Вторым сообщением, которое мы обрабатываем, является WM_CLOSE. Это сообщение приходит, когда происходит щелчок мышью по крестику в правом верхнем углу экрана. По получении этого сообщения выполняется функция EndDialog, что приводит к удалению диалогового окна из памяти, выходу из функции DialogBoxParamA и в конечном итоге - к выходу из программы.

Выше было сказано, что процедура диалогового окна должна возвращать ненулевое значение, если она берет на себя обработку данного сообщения. Как видно из данного примера, в принципе в этом не всегда имеется необходимость. В дальнейшем мы акцентируем внимание на тех случаях, когда в этом есть необходимость.


31 Лично я предпочитаю использовать редактор ресурсов из пакета Borland C++ 5.00, либо простой текстовый редактор.


II

6. Меню. Меню также может быть задано в файле ресурсов. Как и диалоговое окно, в программе оно определяется по имени (строке). Меню можно задать и в обычном окне, и в диалоговом окне. Для обычного окна при регистрации класса следует просто заменить строку

 MOV DWORD PTR [WC.CLMENNAME],0

на

 MOV DWORD PTR [WC.CLMENNAME], OFFSET MENS

Здесь MENS - имя, под которым меню располагается в файле ресурсов. Меню на диалоговое окно устанавливается другим способом, который, разумеется, подходит и для обычного окна. В начале меню загружается при помощи функции LoadMenu, а затем устанавливается функцией SetMenu.

А теперь обо всем подробнее. Рассмотрим структуру файла ресурсов, содержащего определение меню. Ниже представлен текст файла, содержащего определение меню.

Далее представлена программа, демонстрирующая меню на диалоговом окне.

MENUP MENU
{
POPUP "&Первый пункт"
{
MENUITEM "&Первый",1
MENUITEM "В&торой",2
POPUP "Подмен&ю"
{
MENUITEM "Десятый пунк&т",6
}
}
POPUP "&Второй пункт"
{
MENUITEM "Трети&й",3
MENUITEM "Четверт&ый",4
}
MENUITEM "Вы&ход",5
}

Внимательно рассмотрите текст меню. Как видите, пункты меню имеют идентификаторы, по которым в программе можно определить, какой пункт меню выбран. Можно заметить, что выпадающее меню может содержать еще и подменю.

//файл menu.rc
//определение констант
#define WS_SYSMENU 0x00080000L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_MAXIMIZEBOX 0x00010000L
#define WS_POPUP 0x80000000L
#define WS_CAPTION 0x00C00000L

MENUP MENU
{
POPUP "&Первый пункт"
{
MENUITEM "&Первый",1
MENUITEM "В&торой",2
}
POPUP "&Второй пункт"
{
MENUITEM "Трети&й",3
MENUITEM "Четверт&ый",4

POPUP "Еще подмен&ю"
{

MENUITEM "Десятый пунк&т", 6
}
}
MENUITEM "Вы&ход", 5
}

// идентификаторы
#define IDI_ICON1 100

; определили иконку
IDI_ICON1 ICON "ico1.ico"

//определение диалогового окна
DIAL1 DIALOG 0, 0, 240, 120

STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX

CAPTION "Пример диалогового окна"
FONT 8, "Arial"
{
}

; файл menu.inc
; константы
; сообщение приходит при закрытии окна

WM_CLOSE equ 10h
WM_INITDIALOG equ 110h
WM_SETICON equ 80h
WM_COMMAND equ 111h

; прототипы внешних процедур
EXTERN MessageBoxA@16:NEAR
EXTERN ExitProcess@4:NEAR
EXTERN GetModuleHandleA@4:NEAR
EXTERN DialogBoxParamA@20:NEAR
EXTERN EndDialog@8:NEAR
EXTERN LoadStringA@16:NEAR
EXTERN LoadIconA@8:NEAR
EXTERN LoadMenuA@8:NEAR
EXTERN SendMessageA@16:NEAR
EXTERN SetMenu@8:NEAR

; структуры
; структура сообщения
MSGSTRUCT STRUC
 MSHWND DD ?
 MSMESSAGE DD ?
 MSWPARAM DD ?
 MSLPARAM DD ?
 MSTIME DD ?
 MSPT DD ?
MSGSTRUCT ENDS

; файл menu.asm
.386P

; плоская модель
.MODEL FLAT, stdcall

include menu. inc

; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;------------------------------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 MSG MSGSTRUCT <?>
 HINST DD 0 ; дескриптор приложения
 PA DB "DIAL1",0
 PMENU DB "MENUP",0
 STR1 DB "Выход из программы",0
 STR2 DB "Сообщение",0
_DATA ENDS

; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить дескриптор приложения
 PUSH 0
 CALL GetModuleHandleA@4
 MOV [HINST], EAX
;---------------------------------
 PUSH 0
 PUSH OFFSET WNDPROC
 PUSH 0
 PUSH OFFSET PA
 PUSH [HINST]
 CALL DialogBoxParamA@20
 CMP EAX,-1
 JNE KOL
KOL:
 PUSH 0
 CALL ExitProcess@4

; процедура окна
; расположение параметров в стеке

; [EBP+014Н] LPARAM
; [EBP+10H] WAPARAM
; [EBP+0CH] MES
; [EBP+8] HWND
WNDPROC PROC
 PUSH EBP
 MOV EBP,ESP
 PUSH EBX
 PUSH ESI
 PUSH EDI
;-----------------
 CMP DWORD PTR [EBP+0CH],WM_CLOSE
 JNE L1
; закрыть диалоговое окно
 PUSH 0
 PUSH DWORD PTR [EBP+08H]
 CALL EndDialog@8
 JMP FINISH
L1:
 CMP DWORD PTR [EBP+0CH],WM_INITDIALOG
 JNE L2
; загрузить иконку
 PUSH 100 ; идентификатор иконки
 PUSH [HINST] ; идентификатор процесса
 CALL LoadIconA@8
; установить иконку
 PUSH EAX
 PUSH 0 ; тип иконки (маленькая)
 PUSH WM_SETICON
 PUSH DWORD PTR [EBP+08H]
 CALL SendMessageA@16
; загрузить меню
 PUSH OFFSET PMENU
 PUSH [HINST]
 CALL LoadMenuA@8
; установить меню
 PUSH EAX
 PUSH DWORD PTR [EBP+08H]
 CALL SetMenu@8
 JMP FINISH
L2:
; проверяем, не случилось ли чего с управляющими элементами
; на диалоговом окне, в нашем случае имеется единственный
; управляющий элемент - это меню
 CMP DWORD PTR [EBP+0CH], WM_COMMAND
 JNE FINISH
; здесь определяем идентификатор, в данном случае
; это идентификатор пункта меню
 CMP WORD PTR [EBP+10Н],5
 JNE FINISH
; сообщение
 PUSH 0 ; МВ_ОК
 PUSH OFFSET STR2
 PUSH OFFSET STR1
 PUSH 0
 CALL MessageBoxA@16
; закрыть диалоговое окно
 PUSH 0
 PUSH DWORD PTR [EBP+08H]
 CALL EndDialog@8
FINISH:
 MOV EAX, 0
 POP EDI
 POP ESI
 POP EBX
 POP EBP
 RET 16
WNDPROC ENDP
_TEXT ENDS
END START

Рис. 2.3.3. Пример программы с меню.

Дадим небольшой комментарий к программе на Рис. 2.3.3. Прежде всего обращаю ваше внимание на довольно прозрачную аналогию между диалоговым окном и меню. Действительно, и в том и в другом случае ресурс определяется не по идентификатору, а по имени. Далее, и диалоговое окно, и меню содержат в себе элементы, определяющиеся по их идентификаторам, которые мы задали в файле ресурсов и которые помещаются в младшее слово параметра WPARAM. В программе на Рис. 2.3.3 мы программно загружаем меню. Можно поступить и по другому: указать меню в опциях определения диалогового окна следующим образом.

//определение диалогового окна
DIAL1 DIALOG 0, 0, 240, 120

STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
MENU MENUP

CAPTION "Пример диалогового окна"
FONT 8, "Arial"
{
}

Этого достаточно, чтобы меню загрузилось и отобразилось автоматически.

Хочу напомнить читателю одну вещь. В главе 1.3 приводился пример кнопки, которая создавалась как дочернее окно. То, что нажата имение эта кнопка, мы определяли по содержимому LPARAM, который содержал дескриптор кнопки.

Как видите, идентифицировать элемент, расположенный на диалоговом окне, можно и по дескриптору, и по идентификатору ресурса.

Вернемся к меню. Пункты меню могут содержать дополнительные параметры, которые определяют дополнительные свойства этих пунктов.

Вот эти свойства, понимаемые компилятором ресурсов:
CHECKED - пункт отмечен "птичкой".
GRAYED - элемент недоступен (имеет серый цвет).
HELP - элемент может быть связан с помощью. Редакторы ресурсов дополнительно создают ресурс - строку. При этом идентификатор строки совпадает с идентификатором пункта меню.
MENUBARBREAK - для горизонтального пункта это означает, что начиная с него горизонтальные пункты располагаются в новой строке. Для вертикального пункта - то, что начиная с него пункты расположены в новом столбце. При этом проводится разделительная линия.
MENUBREAK - аналогично предыдущему, но разделительная линия не проводится.
INACTIVE - пункт не срабатывает.
SEPARATOR - создает в меню разделитель. При этом идентификатор не ставится.

Заканчивая рассуждение о меню, замечу, что у Windows есть обширнейший набор функций, с помощью которых можно менять свойства меню (удалять и добавлять пункты меню, менять их свойства). В следующей главе приводятся примеры некоторых из этой группы.



Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0