procedure ListSubmenus(s: string; memo: TMemo; menu: HMENU); var TmpArray : array[0..100 - 1] of Char; i, count: integer; submenu: HMENU; begin count := GetMenuItemCount(menu); Memo.Lines.Add('Menu items count: ' + IntToStr(count));
for i := 0 to Pred(count) do begin GetMenuString(menu, i, TmpArray, sizeof(TmpArray), MF_BYPOSITION); Memo.Lines.Add(Format('%sItem #%d : %s', [s, i, TmpArray])); submenu := GetSubMenu(menu, i); if submenu <> 0 then begin ListSubmenus(s + ' ', memo, submenu); end; end;
Спасибо! есть 2 вопроса GetMenuString(menu, i, TmpArray, sizeof(TmpArray), MF_BYPOSITION); что за параметр MF_BYPOSITION? Memo.Lines.Add(Format('%sItem #%d : %s', [s, i, TmpArray])); как тут задается формат?
Это параметр, который определяет, что передается в функцию вторым параметром. Если указываешь MF_BYPOSITION, то этот параметр расценивается как порядковый номер элемента меню, начиная с 0. Если указать MF_BYCOMMAND - значит, будет трактоваться как команда (т.е., сообщение, которое отсылается при выборе пункта меню).
Цитата
как тут задается формат?
Как в Сях, так и тут. В "DRKB -> Язык программирования Delphi -> Работа со строками -> Форматирование строк -> Функции форматирования строк" посмотри, там написано какие могут быть спецификаторы.
. Тогда в TmpArray возвращается метка элемента меню с индексом 4, то есть, нулевой, первый, второй и третий пропускаются, и берется четвертый. TmpArray будет хранить что? Правильно, "Выход". Если же MF_BYCOMMAND - то берется метка элемента меню, у которого идентификатор = 4, то есть, что? Правильно, "Пункт 2". Чувствуешь разницу?
теперь хочу скопировать меню из блокнота в меню в моей программе. Проблема в том, что не могу добавить элемент в Popupmenu. Вроде так PopupMenu1.Items.Add(), только какой параметр надо я не знаю Upd все уже понял)
А при чем тут PopupMenu? Ты ж хочешь меню скопировать оттуда себе? Вот и копируй меню... MSDN -> CreateMenu + там дальше по ссылкам: InsertMenuItem, AppendMenu, и InsertMenu - в помощь...
я пока создавал только VCL приложения (форма, кнопки). А для WinAPI надо консольное создавать? буду смотреть для примера как делать хоть что-то в консоли
Это не совсем консоль. Это оконное приложение, но безо всяких библиотек-оберток. Да, создается консольное приложение, и в нем пишется весь код. Ручками, потому что никаких компонентов нет.
function createmenuitem( hmenu, submenu: hmenu; cap: pchar; _uid, _wid: uint; sep: boolean ): boolean; var mi: menuiteminfo; begin with mi do begin cbsize := sizeof( mi ); fmask := miim_state or miim_type or miim_submenu or miim_id; if not sep then ftype := mft_string else ftype := mft_separator; fstate := mfs_enabled; wid := _wid; hsubmenu := submenu; dwitemdata := 0; dwtypedata := cap; cch := sizeof( cap ); end; result := insertmenuitem( hmenu, _uid, false, mi ); end;
function windowproc( wnd: hwnd; msg: uint; wparam: wparam; lparam: lparam ): lresult; stdcall; begin case msg of wm_destroy: begin postquitmessage( 0 ); result := 0; exit; end; wm_command: begin case loword( wparam ) of sexit: postmessage( wnd, wm_quit, 0, 0 ); scopy: messagebox( wnd, 'Пункт: copy', 'Меню: edit', 0 ); scut: messagebox( wnd, 'Пункт: cut', 'Меню: edit', 0 ); spaste: messagebox( wnd, 'Пункт: paste', 'Меню: edit', 0 ); sselect: begin if check then checkmenuitem( submenucheck, sselect, mf_unchecked ) else checkmenuitem( submenucheck, sselect, mf_checked ); check := not check; end; ssecondlevel: messagebeep( mb_iconhand ); end; end; else result := defwindowproc( wnd, msg, wparam, lparam ); end; end;
// Цикл обработки сообщений while getmessage( msg, 0, 0, 0 ) do begin translatemessage( msg ); dispatchmessage( msg ); end; halt( msg.wparam ); end.
Вот нашел щас буду учить)
Цитата
setmenu function setmenu( hwnd: hwnd; hmenu: hmenu ): bool; Функция setmenu связываем новое меню с окном. hwnd Идентификатор окна, которому должно быть назначено новое меню. hmenu Идентификатор меню, которое должно быть назначено окну. Если этот параметр нулевой, текущее меню окна удаляется.
Это не понятно, или у меня не что не связалось или не увидел
омг я не туда смотрел) Думал из блокнота в мой проект меню скопируется А почему блокнот не реагирует на нажатие по меню?
Добавлено через 4 мин.
Цитата
Подумай, как это можно сделать
Сохранив меню в переменную типа HMenu. А событие на закрытие формы
function windowproc( wnd: hwnd; msg: uint; wparam: wparam; lparam: lparam ): lresult; stdcall; begin case msg of wm_destroy: begin postquitmessage( 0 ); result := 0; //А здесь setmenu с начальным меню блокнота exit; end; ...
wnd1 := FindWindow('Notepad',nil); nbMenu := getmenu(wnd1); setmenu(wnd, nbmenu); // Копируем другое меню себе
Цитата
А почему блокнот не реагирует на нажатие по меню?
А потому что меню твое обрабатывается в ТВОЕЙ функции окна, а не в блокнотовской. Чтобы Блокнот реагировал на твое меню, мало заменить само меню, надо еще заменить (ну, или расширить) оконную функцию. Вот в приведенном здесь примере твое приложение тоже не будет реагировать на Блокнотовские команды, оно просто про них не знает.
case msg of wm_destroy: begin SetMenu(wnd1,hfirst); postquitmessage( 0 ); result := 0; exit; ... wnd1:=FindWindow('Notepad',nil); hfirst:=GetMenu(wnd1); //доп. переменная end;
Возвращает меню назад)
Добавлено через 11 мин. А почему нет обращения к функции
function windowproc
хоть она и выполняется? И зачем нужна регистрация класса?