Что такое код createpopupmenu


Что такое код createpopupmenu

Функция CreatePopupMenu создает «выскакивающее» меню, подменю или контекстное меню. Меню вначале пустое. Вы можете вставлять или добавлять в конец пункты меню при помощи использования функции InsertMenuItem. Вы можете также использовать функцию InsertMenu, чтобы вставить пункты меню, а функцию AppendMenu, чтобы добавлять в конец пункты меню.

Параметры
У этой функции нет параметров.

Возвращаемые значения
Если функция завершается успешно, величина возвращаемого значения — дескриптор недавно созданного меню.
Если функция не выполняет задачу, величина возвращаемого значения — ПУСТО (NULL).

Замечания
Прикладная программа может добавлять новое меню в существующее меню, или она может показывать на экране контекстное меню путем вызова функции TrackPopupMenuEx или TrackPopupMenu.
Ресурсы, связанные с меню, которое предназначены окну, освобождаются автоматически. Если меню окну не назначено, прикладная программа должна освободить ресурсы системы, связанные с меню перед закрытием. Приложение освобождает ресурсы меню путем вызова функция DestroyMenu.
Windows 95: система может поддерживать максимум 16,364 дескрипторов меню.

Смотри также
AppendMenu, CreateMenu, DestroyMenu, InsertMenu, SetMenu, TrackPopupMenu, TrackPopupMenuEx, InsertMenuItem

Размещение и совместимость CreatePopupMenu

Что такое код createpopupmenu

обычный код как всегда:
HandlePopUp:=CreatePopupMenu;
InsertMenu(HandlePopUp,MF_BYPOSITION,MF_STRING or MF_OWNERDRAW ,1,PChar(«item1»);
InsertMenu(HandlePopUp,MF_BYPOSITION,MF_STRING or MF_OWNERDRAW ,2,PChar(«item2»);
TrackPopupMenu(HandlePopUp,TPM_LEFTALIGN, p.X, p.Y,0,wnd,nil);

при появлении мне нужно перерисовать все элементы — item»ы при появлении меню, потому-что при появлении меню, оное является «чистым», кроме конечно первого item1, т.к. он по умолчанию выделяется, т.е. главное окно wnd получает WM_DRAWITEM для первого элемента (где я его и рисую)

WM_INITMENUPOPUP и WM_INITMENU вызываются до появления меню, т.е. дескриптора контекста рисования ещё нет.

как решить данный сабжжж?

Удалено модератором
Примечание: Создание пустых сообщений

Не совсем корректный код, писался очень давно.

Function DrawMenuItem(PDrwItStruct: PDrawItemStruct;PaintStruct:TPAINTSTRUCT;

HDrawBitmap,HDrawBitmapH: HBITMAP;TextToDraw: string):bool;

for x:=0 to 16 do begin

for y:=0 to 16 do begin

if PixRef=RGB(200,200,200) then begin

DT_SINGLELINE or DT_VCENTER or DT_LEFT);

if PDrwItStruct^.itemAction=ODA_SELECT then

if (PDrwItStruct^.itemState and ODS_SELECTED) <> 0 then begin

Программирование и комп-ры : Создать меню без файла описания ресурсов с помощью функций CreateMenu и CreatePopupMenu

Министерство образования Российской Федерации

Институт переподготовки кадров

Уральского государственного технического

Кафедра микропроцессорной техники

ТЕМА: Создать меню без файла описания ресурсов с помощью функций CreateMenu

Слушатель гр. СП-923 Г.Г.

Постановка задачи 5

Создание меню без описания ресурсов с помощью функций CreateMenu и

Текст программы 7

Библиографический список 14

Ассемблер- один из самых старых из существующих сегодня языков

программирования.Когда-то это был самый основной язык, без которого нельзя

было заставить компьютер сделать что-либо полезное.

Постепенно ситуация менялась. Появились более удобные средства общения

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

того он немог этого сделать в принципе.

Если коротко, то ассемблер- это символическое представление машинного

языка. Все процессы в машине на самом низком, аппаратном уровне приводятся

в действие только командами машинногшо языка.

Отсюда понятно, что несмотря на общее название, язык Ассемблера для

каждого типа компьютера свой. Это касается и внешнего вида программ,

написанных на Ассемблере, и идей, отражением которых этот язык является.

Известно, что к программированию на языке ассемблера обращаются тогда,

когда от программы требуется максимальная скорость исполнения, когда

необходимо обеспечить взаимодействие с нестандартными внешними

устройствами, когда необходимо полностью использовать возможности

процессора и операционной системы. На языке ассемблера можно

запрограммировать все, на что способна соответствующая вычислительная

машина, то есть ассемблер является машинно-ориентированным языком

программирования. Программируя на ассемблере иногда в силу привычки, иногда

в силу необходимости, особенно при организации интерфейса пользователя,

приходится многократно программировать одни и те же элементарные задачи. В

языках высокого уровня эта проблема решена применением стандартных функций

и процедур. В ассемблере эта проблема могла бы быть решена за счет

библиотек стандартных функций как на уровне исходных текстов, так и

объектных кодов, но такие библиотеки не стандартизованы и не

распространяются вместе с компиляторами. С появлением Windows 95 ситуация

несколько изменилась. Создание приложений на языке ассемблера представляет

собой весьма сложную задачу в связи с высоким уровнем интеграции прикладной

программы и операционной системы, но теперь нет необходимости многократно

решать проблемы пользовательского интерфейса и управления исполнением

команд на уровне машинных команд [I]. Они решаются теперь с помощью

операционной системы за счет обращения к функциям интерфейса прикладного

программирования – Application Programming Interface (API).

Программирование пользовательского интерфейса с применением функций

Win32 API основано на использовании так называемых ресурсов. Ресурсами

являются соответствующим образом оформленные данные, используемые

операционной системой для создания внешнего отображения органов управления

приложением, и средства, обеспечивающие ввод данных в процессе исполнения

программы в режиме диалога. Ресурсы описываются в текстовом файле с

rc. Файл ресурсов после обработки компилятора ресурсов и получения

двоичного файла с расширением res с помощью компоновщика объединяется с

Наиболее очевидным средством управления приложением является

меню. Строка меню выводится на экран непосредственно под строкой заголовка.

Это меню называется главным. Выбор элемента меню влечет за собой выдачу

приложению сообщения WM_COMMAND, содержащего идентификатор пункта меню.

Идентификаторы анализируются в оконной процедуре приложения, что

обеспечивает соответствующую реакцию на полученное сообщение. Каждый пункт

меню определяется тремя характеристиками. Первая определяет то, что будет

отображаться в данном пункте меню – это либо строка текста, либо картинка.

Вторая характеристика определяет либо константу, посылаемую оконной

процедуре в сообщении WM_COMMAND, либо всплывающее меню, которое выводится

на экран, когда пользователь выбирает данный пункт меню. Третья

характеристика указывает, является ли данный пункт меню разрешенным

(enabled), запрешенным (disabled), недоступным (grayed) или помеченным

(checked). Эта характеристика пункта меню не является обязательной.

Меню можно создать тремя способами. Можно определить меню в файле

описания ресурсов, создать меню без файла описания ресурсов непосредственно

в программе с помощью функций CreatMenu, AppendMenu и InsertMenu или с

помощью функции LoadMenuIndirect, создав предварительно структуру

MENUITEMPLATE. Наиболее простым и понятным при программировании под

Windows95 на языке ассемблера является определение меню в файле описания

ресурсов с помощью любого текстового редактора.

Моя задача заключается в создание меню без файла описания ресурсов с

помощью функций CreateMenu и CreatePopupMenu. Одним из средств создания

меню без использования файла описания ресурсов является функции CreateMenu

с последующим добавлением необходимого числа пунктов с помощью функции

Создание меню без описания ресурсов с помощью функций CreateMenu и

Windows-приложение на ассемблере содержит один сегмент данных .data и

один сегмент кода .code. В программе использовано 20 функций API. Параметры

этим функциям передаются через стек, результат возвращается в регистре ЕАХ.

Директива mode1 задает плоскую модель памяти (flat) и стиль передачи

параметров при входе в процедуры программы и выходе из них (stdcall).

Модель памяти flat обозначает плоскую модель памяти. В соответствии с

плоской моделью памяти компилятор создает программу, которая содержит 32-

Илон Маск рекомендует:  Псевдокласс only-child в CSS

битовый сегмент для данных и кода программы. Указание этой модели памяти

заставляет компоновщик создать исполняемый файл с расширением .exe.

Параметр stdcall определяет порядок передачи параметров через стек

Директива include включае в программу файл win32.inc.

Функции Win32 API, используемые в программе должны быть объявлены с

помощью директивы extrn для того, чтобы компилятор мог сгенерировать

При создании окна приложения с помощью CreateMenu получаем дескриптор

меню и используем его в качестве одного из параметров функций

CreateWindowExA. Затем с помощью функции CreatePopupMenu получаем

дескриптор выпадающего меню и вызовом AppendMenu определяем все пункты

Результат работы программы приведен на Рис.1.

1. p386 ; эта директива разрешает транслятору обрабатывать команды

2. jumps ; транслятор автоматически преобразует команду

; передачи управления в комбинацию условной и

; команд если условная команда в силу

; области своего действия ;не обеспечивает

; управления по нужному адресу


3. model flat, STDCALL ; выбирается модель памяти для 32- разрядного

4. include win32.inc ; файл описания структур и констант

5. L equ ; последовательности символов LARGE,

; следующий за ней операнд

; присваивается имя L

6. IDM_QUIT equ 100

7. IDM_ABOUT equ 101

8. MF_ENABLED equ 0

9. MF_POPUP equ 10h

10. MF_OWNERDRAW equ 100h

;Функции Win32 API, используемые программой

11. extrn BeginPaint :PROC

12. extrn CreateWindowExA :PROC

13. extrn DefWindowProcA :PROC

14. extrn DispatchMessageA :PROC

15. extrn EndPaint :PROC

16. extrn ExitProcess :PROC

17. extrn GetMessageA :PROC

18. extrn GetModuleHandleA :PROC

19. extrn LoadCursorA :PROC

20. extrn LoadIconA :PROC

21. extrn RegisterClassA :PROC

22. extrn PostQuitMessage :PROC

23. extrn ShowWindow :PROC

24. extrn TranslateMessage :PROC

25. extrn UpdateWindow :PROC

26. extrn CreateMenu :PROC

27. extrn MessageBoxA :PROC

28. extrn AppendMenuA :PROC

29. extrn DrawMenuBar :PROC

30. extrn CreatePopupMenu :PROC

31. .data ; переопределенное имя, означающее начало

32. newhwnd dd 0

33. lppaint PAINTSTRUCT

34. msg MSGSTRUCT

38. szTitleName db ‘Это наше окно’,0

39. szClassName db ‘ASMCLASS32’,0

40. szHello db ‘Привет!’,0

41. szAppName db ‘Сообщение’,0

43. hsubmenu dd 0

44. item1 db ‘Меню’,0

45. item2 db ‘Выход’,0

46. item3 db ‘Возврат’,0

47. .code ; переопределенное имя, означающее начало

50. call GetModuleHandleA

51. mov [hInst], eax

;инициализация структуры WndClass

52. mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW +

53. mov [wc.clsLpfnWndProc], offset WndProc

54. mov [wc.clsCbClsExtra], 0

55. mov [wc.clsCbWndExtra], 0

56. mov eax, [hInst]

57. mov [wc.clsHInstance], eax

58. push L IDI_APPLICATION

60. call LoadIconA

61. mov [wc.clsHIcon], eax

62. push L IDC_ARROW

64. call LoadCursorA

65. mov [wc.clsHCursor], eax

66. mov [wc.clsHbrBackground], COLOR_WINDOW + 1

67. mov dword ptr [wc.clsLpszMenuName],0

68. mov dword ptr [wc.clsLpszClassName], offset szClassName

69. push offset wc

70. call RegisterClassA

71. call CreateMenu

72. mov [hMenu],eax

73. push L 0 ; lpParam

74. push [hInst] ; hInstance

75. push [hMenu] ; menu

76. push L 0 ; parent hwnd

77. push L CW_USEDEFAULT ; height

78. push L CW_USEDEFAULT ; width

79. push L CW_USEDEFAULT ; y

80. push L CW_USEDEFAULT ; x

81. push L WS_OVERLAPPEDWINDOW ; Style

82. push offset szTitleName ; Title string

83. push offset szClassName ; Class name

84. push L 0 ; extra style

85. call CreateWindowExA

86. mov [newhwnd], eax

87. call CreatePopupMenu

88. mov [hsubmenu], eax

89. push offset item2

90. push L IDM_QUIT

93. call AppendMenuA

94. push offset item3

95. push L IDM_ABOUT

97. push [hsubmenu] ;eax

98. call AppendMenuA

99. push offset item1

100. push [hsubmenu]

101. push MF_POPUP

103. call AppendMenuA

105. push L SW_SHOWNORMAL

106. push [newhwnd]

107. call ShowWindow

108. push [newhwnd]

109. call UpdateWindow

110. push [newhwnd]

111. call DrawMenuBar

116. push offset msg

117. call GetMessageA

119. je end_loop

120. push offset msg

121. call TranslateMessage

122. push offset msg

123. call DispatchMessageA

124. jmp msg_loop

126. push [msg.msWPARAM]

127. call ExitProcess

128. ;—-Оконная процедура—-

129. WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD,\

130. wparam:DWORD, lparam:DWORD

131. LOCAL hDC:DWORD

132. cmp [wmsg], WM_DESTROY

133. je wmdestroy

134. cmp [wmsg], WM_SIZE

136. cmp [wmsg], WM_CREATE

137. je wmcreate

138. cmp [wmsg],WM_PAINT

141. cmp [wmsg],WM_COMMAND

142. je wmcommand

144. jmp defwndproc

146. mov eax,lparam

149. mov eax,wparam


150. cmp ax,IDM_ABOUT

152. call MessageBoxA,0,offset szHello,offset szAppName,MB_OK

154. m2: cmp ax,IDM_QUIT

157. call PostQuitMessage

158. m1: mov eax,0

164. push [lparam]

165. push [wparam]

168. call DefWindowProcA

172. call PostQuitMessage

179. push offset lppaint

181. call BeginPaint

183. push offset lppaint

185. call EndPaint

190. WndProc endp

192. public WndProc

193. end start ; конец программы

рис1. Окно программы

Моя задача состояла в создании программы без файла описания ресурсов с

помощью функций CreateMenu и CreatePopupMenu. Это приложение не выполняет

никакой полезной работы и служит для демонстрации некоторых возможностей

системы в организации интерфейса пользователя.

1. Зубков С.В. Assembler. Для DOS Windows и Unix. М.: ДМК, 1999

2. Пустоваров В.И. АССЕМБЛЕР. Программирование и анализ корректности

3. Применение TURBO ASSEMBLER для программирования ПЭВМ. Часть1,2.:

Методические указания к лабораторному практикуму по дисциплине :

«Системное программное обеспечение» / Составитель В.П.Кулюкин.

Что такое код createpopupmenu

Creates a new empty popup menu.

#Menu A number to identify the new menu. #PB_Any can be used to auto-generate this number.

Nonzero if the menu was successfully created, zero otherwise. If #PB_Any was used for the #Menu parameter then the generated number is returned on success.

To create a popup menu with support for images, use CreatePopupImageMenu().

Once created, this menu becomes the current menu for further item additions. It’s now possible to use functions such as MenuTitle(), MenuItem(), MenuBar(), OpenSubMenu() to populate the menu.

DisplayPopupMenu() can be used to display this popup menu at any position on the screen.

To handle menu events properly, see the description of following functions:
WaitWindowEvent() (alternatively WindowEvent())
EventWindow()
EventMenu()

Что такое код createpopupmenu

You can refer to this page:

and this sample:

For more details, you’d better ask on

  • Помечено в качестве ответа Mike Feng Moderator 12 мая 2013 г. 8:23

Все ответы

How are you? Btw, what kind of menu do you really want to create? And can you also post your existing code here? :)

Failure is not the worst thing in the world. The very worst is not to try. Email Address : ericjohnadamos@gmail.com. http://ericjohnadamos.blogspot.com/

.NET already provides wrappers around popup menus that make the necessary API calls. Is there any particular reason that you want to do this manually rather than relying on the framework?

Michael Taylor
http://msmvps.com/blogs/p3net

i write this , but i think its realy bad.

i want create menu like :File,Edit,etx i only want create menu with CreatePopupMenu()(api) but i cant make it. here is my code:

[DllImport(«user32.dll», CharSet = CharSet.Auto, SetLastError = true)]

private static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);

[DllImport(«user32.dll»)] static extern long

Что такое код createpopupmenu

  • CreateMenu
  • CreatePopupMenu
  • AppendMenu
  • InsertMenu
  • SetMenu
  • DrawMenuBar
  • EnableMenuItem
  • CheckMenuItem

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

Главное меню программы, это строка, которая располагается в верхней части формы. Она состоит из пунктов, нажатие на любой из них приведет к раскрытию подменю, принадлежащего данному пункту. Это всплывающее меню в Windows называется PopupMenu. Обратите внимание, понятие PopupMenu в Delphi и Windows различаются. В Windows PopupMenu — это подменю, принадлежащее другому пункту меню (который отмечается треугольником справа от текста пункта) или одному из пунктов главного меню. В Delphi PopupMenu — это меню, которое может «всплывать» в любой точке формы. Осознав вышесказанное, приступаем к работе.

Откроем шаблон, написанный в прошлый раз, и дополним список констант и переменных

Сначала разберемся с константами. Каждый пункт меню должен иметь свой уникальный идентификационный номер. Так как именно по этим номерам мы и будем работать с меню, удобнее всего оформить их как константы. Идея следующая. В главном меню будет 3 пункта: Menu, Edit и Check. Константы для него начинаются с буквы m и имеют номера 100, 200 и 300 соответственно. Каждому из этих пунктов будет сопоставлено свое подменю. Константы для них начинаются с буквы s и номеруются следующим образом: те, которые относятся к первому пункту, начинаются со 100+1, те, которые относятся ко второму пункту, начинаются с 200+1, ну и по аналогии, те, которые относятся к третьему пункту, начинаются с 300+1. В третьем пункте будет подменю второго уровня, константа для него равна 300+10+1. Отдельное значение имеет константа SEPARATOR, это просто разделитель между пунктами подменю.

Переходим к разделу var . Здесь появилось 5 переменных типа HMENU, они содержат Hendle соответствующего меню (какого, понятно из их названия). Переменная Check показывает, установлен или сброшен пункт меню (читайте дальше, и все поймете).

При добавлении нового пункта приходится выполнить ряд действий, в том числе инициализацию структуры MENUITEMINFO. Так как эти действия нужно производить при добавлении каждого пункта, чтобы избавиться от избыточности кода, оформим эти действия в виде отдельной процедуры.

Поясню входные параметры функции. hMenu — меню, в которое добавляется новый пункт; SubMenu — связанное с этим пунктом подменю (если оно есть); Cap — заголовок нового пункта; _uID — всегда 0 (этот параметр используется в функции InsertMenuItem); _wID — идентификатор, связанный с данным пунктом; Sep — признак, является ли новый пункт разделителем или нет.

Наше приложение должно реагировать на выбор того или иного пункта меню. Дополним оконную процедуру следующим образом:

При выборе пункта Exit (константа sExit) программа будет закрыта. Выбор пунктов Copy, Cut, Paste (константы sCopy, sCut и sPaste соответственно) приведет к появлению сообщения, соответствующего выбранному пункту. Пункт Select (константа sSelect) работает аналогично TCheckBox, то есть может быть установлен или сброшен. При выборе пункта Beep (константа sSecondLevel) мы услышим звуковой сигнал.

Теперь для создания меню все готово. Приступаем.

Разбираемся. Первым делом создаем главное меню. Указатель на него присваиваем полю lpszMenuName структуры Wc (раньше оно было равно nil ). После регистрации класса в системе создаем подменю. При создании окна, параметр hMenu функции CreateWindowEx равен MainMenu (Handle созданного меню, а не 0, как было в шаблоне). После создания всех пунктов, перерисовываем меню при помощи функции DrawMenuBar.

Теперь второй способ создания меню. Здесь я приведу его в сокращении, и поясню произведенные изменения (полный текст программы имеется в архиве с примерами в конце статьи).

Поле lpszMenuName структуры Wc остается равным nil . Главное меню создаем после регистрации класса в системе. При создании окна, параметр hMenu функции CreateWindowEx можно оставить равным 0, т.к. здесь мы не перерисовываем меню, а назначаем его форме, используя функцию SetMenu.

Все. Теперь у нашей формы есть меню. Это оказалось совсем не сложно. До новых встреч, удачи в программировании.

Что такое код createpopupmenu

Приветствую!
имеется меню.
hPopup:=CreatePopupMenu;
добавляю в него итем
AppendMenu(hPopup,MF_STRING,9,»test»);
теперь создаю второе popupmenu и добавляю в него итем.
hPopup_test:=CreatePopupMenu;
AppendMenu(hPopup_test,MF_STRING,9,»test_test»);

для того чтобы по нажатию на test открывалось второе меню делаю так.

function WindowProc(hwnd, msg, wparam, lparam:longint):longint;stdcall;
begin
Result:=DefWindowProc(hwnd,msg,wparam,lparam);
case Msg of
WM_COMMAND :
begin
if lparam=0 then
begin
case wparam of
9: Popup_Vis;
end;
end;
end;
end;
в приципе все работает за одним но. вернее за тремя..
1) хотелось бы чтобы пункт test после надписи (справа) имел такую стрелочку что означает что в нем есть подменю. как это сделать?
2) хотелось бы чтобы второе popupmenu открывалось по наведению курсора на надпись test а не по клику (но здесь думаю стоит повнимательнее почитать о WM_COMMAND).
3) самое важное. по клику на test — (когда появляется второе меню) основное меню пропадает а я хочу чтобы оно оставалось..
Спасибо!

grom ты извини конечно.. но где я итем то возьму? мне что menus подключать? это же winapi и максимумум что я имею — это хендл менюхи (как я понимаю).

//hPopupx:=createmenu; не надо

— вот за это спасибо! ) это у меня то и не получалось ))

PopupMenu

Иерархия наследования

Описание

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

Работа с компонентом

Для создания контекстного меню добавте компонент PopupMenu на форму и установите его в качестве значения свойства PopupMenu формы или компонента.

Список элементов контекстного меню создается так же, как и для компонента MainMenu.

После создания меню существует возможность изменения порядка расположения пунктов меню на панели меню с помощью механизма перетаскивания объектов Drag&Drop.

При отсутствии элементов в компоненте PopupMenu оно отображаться не будет.

Что такое код createpopupmenu

  • CreateMenu
  • CreatePopupMenu
  • AppendMenu
  • InsertMenu
  • SetMenu
  • DrawMenuBar
  • EnableMenuItem
  • CheckMenuItem

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

Главное меню программы, это строка, которая располагается в верхней части формы. Она состоит из пунктов, нажатие на любой из них приведет к раскрытию подменю, принадлежащего данному пункту. Это всплывающее меню в Windows называется PopupMenu. Обратите внимание, понятие PopupMenu в Delphi и Windows различаются. В Windows PopupMenu — это подменю, принадлежащее другому пункту меню (который отмечается треугольником справа от текста пункта) или одному из пунктов главного меню. В Delphi PopupMenu — это меню, которое может «всплывать» в любой точке формы. Осознав вышесказанное, приступаем к работе.

Откроем шаблон, написанный в прошлый раз, и дополним список констант и переменных

Сначала разберемся с константами. Каждый пункт меню должен иметь свой уникальный идентификационный номер. Так как именно по этим номерам мы и будем работать с меню, удобнее всего оформить их как константы. Идея следующая. В главном меню будет 3 пункта: Menu, Edit и Check. Константы для него начинаются с буквы m и имеют номера 100, 200 и 300 соответственно. Каждому из этих пунктов будет сопоставлено свое подменю. Константы для них начинаются с буквы s и номеруются следующим образом: те, которые относятся к первому пункту, начинаются со 100+1, те, которые относятся ко второму пункту, начинаются с 200+1, ну и по аналогии, те, которые относятся к третьему пункту, начинаются с 300+1. В третьем пункте будет подменю второго уровня, константа для него равна 300+10+1. Отдельное значение имеет константа SEPARATOR, это просто разделитель между пунктами подменю.

Переходим к разделу var . Здесь появилось 5 переменных типа HMENU, они содержат Hendle соответствующего меню (какого, понятно из их названия). Переменная Check показывает, установлен или сброшен пункт меню (читайте дальше, и все поймете).

При добавлении нового пункта приходится выполнить ряд действий, в том числе инициализацию структуры MENUITEMINFO. Так как эти действия нужно производить при добавлении каждого пункта, чтобы избавиться от избыточности кода, оформим эти действия в виде отдельной процедуры.

Поясню входные параметры функции. hMenu — меню, в которое добавляется новый пункт; SubMenu — связанное с этим пунктом подменю (если оно есть); Cap — заголовок нового пункта; _uID — всегда 0 (этот параметр используется в функции InsertMenuItem); _wID — идентификатор, связанный с данным пунктом; Sep — признак, является ли новый пункт разделителем или нет.

Наше приложение должно реагировать на выбор того или иного пункта меню. Дополним оконную процедуру следующим образом:

При выборе пункта Exit (константа sExit) программа будет закрыта. Выбор пунктов Copy, Cut, Paste (константы sCopy, sCut и sPaste соответственно) приведет к появлению сообщения, соответствующего выбранному пункту. Пункт Select (константа sSelect) работает аналогично TCheckBox, то есть может быть установлен или сброшен. При выборе пункта Beep (константа sSecondLevel) мы услышим звуковой сигнал.

Теперь для создания меню все готово. Приступаем.

Разбираемся. Первым делом создаем главное меню. Указатель на него присваиваем полю lpszMenuName структуры Wc (раньше оно было равно nil ). После регистрации класса в системе создаем подменю. При создании окна, параметр hMenu функции CreateWindowEx равен MainMenu (Handle созданного меню, а не 0, как было в шаблоне). После создания всех пунктов, перерисовываем меню при помощи функции DrawMenuBar.

Теперь второй способ создания меню. Здесь я приведу его в сокращении, и поясню произведенные изменения (полный текст программы имеется в архиве с примерами в конце статьи).

Поле lpszMenuName структуры Wc остается равным nil . Главное меню создаем после регистрации класса в системе. При создании окна, параметр hMenu функции CreateWindowEx можно оставить равным 0, т.к. здесь мы не перерисовываем меню, а назначаем его форме, используя функцию SetMenu.

Все. Теперь у нашей формы есть меню. Это оказалось совсем не сложно. До новых встреч, удачи в программировании.

Как отобразить контекстное меню?

Автор: Александр Шаргин

Опубликовано: 25.06.2001
Исправлено: 13.03.2005
Версия текста: 1.0

Создание контекстного меню

Прежде чем отображать контекстное меню, его необходимо загрузить из ресурсов приложения или создать его прямо на лету. Рассмотрим оба способа.

Вариант 1. Создание меню «на лету»

Меню создаётся с помощью функции CreatePopupMenu . Это очень простая функция, которая не принимает параметров и возвращает хэндл созданного меню. В этом меню изначально нет ни одного пункта. Добавить пункты можно, используя функции AppendMenu и InsertMenuItem . Например:

Этот код создаёт стандартное меню, содержащее пункты Undo/Cut/Copy/Paste.

Вариает 2. Загрузка меню из ресурсов

Загрузить меню из ресурсов приложения можно, используя функцию LoadMenu . Передавайте ей дескриптор модуля и идентификатор ресурса, содержащего нужное меню. Теоретически, можно использовать также функцию LoadMenuIndirect , но на практике контекстное меню редко отображают столь окольными путями.

Меню, которое размещается в ресурсах приложения, не является всплывающим, и его невозможно отобразить как контекстное. Поэтому вы должны поучить одно из его подменю с помощью функции GetSubMenu и отобразить его. Учитывая эту особенность, программисты часто создают в редакторе ресурсов фиктивное меню с одним единственным пунктом, с которым и связывается нужное всплывающее меню (рисунок 1).

ПРИМЕЧАНИЕ
В некоторых случаях можно даже не создавать отдельного меню, а «позаимствовать» одно из подменю главного. Например, при щелчке правой кнопкой на панели инструментов или строке состояния уместно отобразить подменю View из главного меню приложения.

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

Отображение меню

Для отображения контекстного меню в Win32 API предусмотрена функция TrackPopupMenu(Ex) . В MFC ей соответствует функция CMenu::TrackPopupMenu . Все эти функции выполняют следующие действия: отображают контекстное меню в заданной точке экрана, запускают собственный цикл сообщений, в котором отслеживают выбор пользователя, а в конце, когда пользователь выбрал какой-то пункт или закрыл меню, уведомляют программу о его выборе.

Рассмотрим прототип функции TrackPopupMenu .

Параметр hMenu определяет всплывающее меню, которое следует отобразить. Параметры x и y задают положение меню на экране, а hWnd — окно, которое будет получать все сообщения от меню (этот параметр не может быть равен NULL ). Параметры nReserved и prcRect не используются. Что касается опций, их полный список можно найти в документации. Я хочу обратить ваше внимание только на флаг TPM_RETURNCMD . Если он не задан, программа получит уведомление о выборе пользователя в виде сообщения WM_COMMAND . Если же его задать, функция TrackPopupMenu просто вернёт в программу идентификатор выбранного пользователем пункта меню, не отправляя никаких сообщений.

Уничтожение меню

По окончании работы с меню его следует уничтожить вызовом DestroyMenu . Эта функция получает один параметр — хэндл меню, которое подлежит уничтожению. Обратите внимание, что меню, полученное с помощью GetSubMenu , уничтожать не надо. Оно будет удалено в процессе уничтожения родительского меню, которое вы загрузили с помощью LoadMenu .

WM_CONTEXTMENU

Итак, мы научились отображать контекстное меню. Осталось ответить на последний вопрос: в каком месте программы вызывать рассмотренные выше функции. Первое, что приходит в голову — отобразить меню в ответ на сообщение WM_RBUTTONUP . Но предпочтительнее делать это в обработчике другого сообщения — WM_CONTEXTMENU . У этого сообщения есть целый ряд преимуществ перед WM_RBUTTONUP .

  • Координаты курсора мыши передаются обработчику сразу в экранных координатах и их не придётся конвертировать для передачи в TrackPopupMenu .
  • Дочерние окна, у которых нет собственного контекстного меню, автоматически пересылают WM_CONTEXTMENU родительскому окну. Благодаря этому вы можете, к примеру, написать контекстное меню для диалога, и оно будет вызываться также для всех контролов в этом диалоге (кроме контролов, имеющих собственное меню, таких как edit box).
  • Не будем забывать о клавиатуре. Стандартной комбинацией для вызова контекстного меню является Shift+F10. Когда пользователь нажимает эти клавиши, окно получает WM_CONTEXTMENU (в этом случае координаты курсора устанавливаются равными -1). Благодаря этому вам не придётся отслеживать отдельно вызов контекстного меню с помощью мыши и с помощью клавиатуры.

Вот полный пример обработчика WM_CONTEXTMENU .

В этом примере для извлечения координат курсора мыши используются макросы GET_X_LPARAM и GET_Y_LPARAM . Эти и многие другие полезные макросы описаны в заголовочном файле windowsx.h .

В MFC можно использовать этот код без изменений или переписать его через класс CMenu .

Автоматическое добавление контекстного меню

Если вы программируете с использованием MFC, у вас есть счастливая возможность переложить работу по созданию контекстного меню на среду Visual C++. Для этого откройте окно Project->Add To Project->Components and Controls , а затем выберите компонент Pop-up Menu из папки Visual C++ Components . Появится ещё одно окно, в котором вам предложат выбрать, к какому окну вы хотите добавить контекстное меню, а также идентификатор ресурса меню. Вводите нужные параметры, жмите ОК, и в выбранный класс добавится готовый обработчик OnContextMenu . Кроме этого, в ресурсы вашего приложения добавится новое меню, и вам останется только подредактировать его.

Илон Маск рекомендует:  Шаблон сайта для женского интернет магазина HTML, CSS, 12 страниц
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL