IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
> Меню, WinAPI
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


procedure TForm1.Button1Click(Sender: TObject);
var wnd:hwnd;
TmpArray : array[0..100 - 1] of Char;
mymenu:Hmenu;
begin
Wnd := FindWindow('Notepad',nil);
GetWindowText(wnd, @TmpArray, 100);
label1.caption:=tmparray;
mymenu:=getmenu(wnd);
label2.Caption:=inttostr(GetMenuItemCount(mymenu));
end;
Тут я нашел окно блокнота, узнал его заголовок и количество пунктов меню. Как узнать название пункта ? и если есть его подпунтков?

Сообщение отредактировано: Client -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Скажем, вот так:
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;

end;
procedure TForm1.Button3Click(Sender: TObject);
var
wnd: HWND;
TmpArray: array[0 .. 100 - 1] of Char;
mymenu: HMENU;
begin
Wnd := FindWindow('Notepad', nil);
GetWindowText(wnd, @TmpArray, 100);
Memo1.Lines.Add('Title: ' + TmpArray);
mymenu:= GetMenu(wnd);
ListSubMenus('', Memo1, mymenu);
end;
Вот чего получилось:


Эскизы прикрепленных изображений
Прикрепленное изображение
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Спасибо!
есть 2 вопроса
GetMenuString(menu, i, TmpArray, sizeof(TmpArray), MF_BYPOSITION); что за параметр MF_BYPOSITION?
Memo.Lines.Add(Format('%sItem #%d : %s', [s, i, TmpArray])); как тут задается формат?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
что за параметр MF_BYPOSITION?
Это параметр, который определяет, что передается в функцию вторым параметром. Если указываешь MF_BYPOSITION, то этот параметр расценивается как порядковый номер элемента меню, начиная с 0. Если указать MF_BYCOMMAND - значит, будет трактоваться как команда (т.е., сообщение, которое отсылается при выборе пункта меню).

Цитата
как тут задается формат?
Как в Сях, так и тут. В "DRKB -> Язык программирования Delphi -> Работа со строками -> Форматирование строк -> Функции форматирования строк" посмотри, там написано какие могут быть спецификаторы.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Цитата
Если указываешь MF_BYPOSITION, то этот параметр расценивается как порядковый номер элемента меню, начиная с 0
Т.е. берется название его?
Цитата
Если указать MF_BYCOMMAND - значит, будет трактоваться как команда
А это тоже самое что если бы нажать по этому пункту меню?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Нет, ты не понял... Смотри, допустим имеется вот такое описание меню в ресурсах:

POPUP "Название"
BEGIN
MENUITEM "Пункт 1", 3
MENUITEM SEPARATOR
MENUITEM "Пункт 2", 4
MENUITEM SEPARATOR
MENUITEM "Выход", 100
END
. Мы находим его Handle и делаем:
GetMenuString(menu, 4, TmpArray, sizeof(TmpArray), MF_BYPOSITION);
. Тогда в TmpArray возвращается метка элемента меню с индексом 4, то есть, нулевой, первый, второй и третий пропускаются, и берется четвертый. TmpArray будет хранить что? Правильно, "Выход". Если же MF_BYCOMMAND - то берется метка элемента меню, у которого идентификатор = 4, то есть, что? Правильно, "Пункт 2". Чувствуешь разницу?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Понял, спасибо.
Щас еще покапаю что-нибудь)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


smile.gif
теперь хочу скопировать меню из блокнота в меню в моей программе. Проблема в том, что не могу добавить элемент в Popupmenu. Вроде так PopupMenu1.Items.Add(), только какой параметр надо я не знаю
Upd
все уже понял)

Сообщение отредактировано: Client -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гость






А при чем тут PopupMenu? Ты ж хочешь меню скопировать оттуда себе? Вот и копируй меню... MSDN -> CreateMenu + там дальше по ссылкам: InsertMenuItem, AppendMenu, и InsertMenu - в помощь...

Иначе у тебя уже не WinAPI, а VCL получается...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Да я хочу скопировать МЕНЮ целиком из блокнота в свою программу.
Цитата
Иначе у тебя уже не WinAPI, а VCL получается...
Хм, у меня форма, на ней мемо и кнопка. Что не так? или лучше создать консольное приложение?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гость






В таком случае название темы не соответствует действительности. Реши для себя, ты хочешь чистый WinAPI, или хочешь пользоваться VCL-ными "плюшками".
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


я пока создавал только VCL приложения (форма, кнопки).
А для WinAPI надо консольное создавать? буду смотреть для примера как делать хоть что-то в консоли
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гость






Это не совсем консоль. Это оконное приложение, но безо всяких библиотек-оберток. Да, создается консольное приложение, и в нем пишется весь код. Ручками, потому что никаких компонентов нет.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


program Project1;
uses
windows,messages;
const
wndclass = 'twinapiwnd';
wndcaption = 'Главное меню формы на win api';
mfile = 100;
medit = 200;
mcheck = 300;
sexit = 101;
scopy = 201;
scut = 202;
spaste = 203;
sselect = 301;
snextmenu = 302;
ssecondlevel = 311;
separator = 1;

var
wc: twndclassex;
wnd: hwnd;
msg: tmsg;
mainmenu: hmenu;
submenufile: hmenu;
submenuedit: hmenu;
submenucheck: hmenu;
submenusecondlevel: hmenu;
check: boolean = false;

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;


begin
// Создаем меню
mainmenu := createmenu;
// Заполняем структуру twndclassex
with wc do
begin
cbsize := sizeof( wc );
style := cs_hredraw or cs_vredraw;
lpfnwndproc := @windowproc;
cbclsextra := 0;
cbwndextra := 0;
hinstance := hinstance;
hicon := loadicon( 0, idi_application );
hcursor := loadcursor( 0, idc_arrow );
hbrbackground := color_window;
lpszmenuname := @mainmenu;
lpszclassname := wndclass;
end;
// Регистрируем класс в системе
registerclassex( wc );
// Создаем подменю
submenufile := createpopupmenu;
submenuedit := createpopupmenu;
submenucheck := createpopupmenu;
submenusecondlevel := createpopupmenu;
// Создаем окно
wnd := createwindowex( 0, wndclass, wndcaption, ws_overlappedwindow,
10, 10, 300, 100, 0, mainmenu, hinstance, nil );
// Создаем пункты главного меню
createmenuitem( mainmenu, submenufile, 'file', 0, mfile, false );
createmenuitem( mainmenu, submenuedit, 'edit', 0, mfile, false );
createmenuitem( mainmenu, submenucheck, 'check', 0, mfile, false );
// Подменю для пункта file
createmenuitem( submenufile, 0, 'exit', 0, sexit, false );
// Подменю для пункта edit
createmenuitem( submenuedit, 0, 'copy', 0, scopy, false );
createmenuitem( submenuedit, 0, 'cut', 0, scut, false );
createmenuitem( submenuedit, 0, ' ', 0, separator, true );
createmenuitem( submenuedit, 0, 'paste', 0, spaste, false );
// Подменю для пункта check->nextmenu
createmenuitem( submenusecondlevel, 0, 'beep', 0, ssecondlevel, false );
// Подменю для пункта check
createmenuitem( submenucheck, 0, 'select', 0, sselect, false );
createmenuitem( submenucheck, submenusecondlevel, 'nextmenu', 0, snextmenu, false );
// Перерисовываем меню
drawmenubar( wnd );
// Показываем окно
showwindow( wnd, sw_shownormal );

// Цикл обработки сообщений
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 Идентификатор меню, которое должно быть назначено окну. Если этот параметр нулевой, текущее меню окна удаляется.
Это не понятно, или у меня не что не связалось или не увидел
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гость






Цитата
Это не понятно
Что именно не понятно?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


wnd1:=FindWindow('Notepad',nil);
SetMenu(wnd1,mainmenu)
Попробовал добавить в код выше. Ничего. И как можно вывести название окна тут? (label'а то нету)

Добавлено через 4 мин.
wnd1:=FindWindow('Notepad',nil);
GetWindowText(wnd1, @TmpArray, 100);
messagebox( wnd, TmpArray, 'Меню: edit', 0 );
Вывести смог smile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Гость






Цитата
Попробовал добавить в код выше. Ничего.
Ну, это уж я не знаю, как ты пробовал:
Прикрепленное изображение

Только перед тем, как закрыть свою программу надо было бы вернуть Notepad-ное меню назад... Подумай, как это можно сделать.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


омг я не туда смотрел) Думал из блокнота в мой проект меню скопируется
А почему блокнот не реагирует на нажатие по меню?

Добавлено через 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;
...
?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Гость






Цитата
Думал из блокнота в мой проект меню скопируется
Это тебе так надо:
wnd1 := FindWindow('Notepad',nil);
nbMenu := getmenu(wnd1);
setmenu(wnd, nbmenu); // Копируем другое меню себе

Цитата
А почему блокнот не реагирует на нажатие по меню?
А потому что меню твое обрабатывается в ТВОЕЙ функции окна, а не в блокнотовской. Чтобы Блокнот реагировал на твое меню, мало заменить само меню, надо еще заменить (ну, или расширить) оконную функцию. Вот в приведенном здесь примере твое приложение тоже не будет реагировать на Блокнотовские команды, оно просто про них не знает.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


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
хоть она и выполняется?
И зачем нужна регистрация класса?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

2 страниц V  1 2 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 20.10.2020 5:14
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name