![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с меню в чужом приложении [D7, Win2k, WinXP]
ANB © (2005-04-15 17:08:00)Киньте, плз, инфу, какими сообщениями можно работать с текстами элементов меню чужого приложения. Я нашел только как выташить Handle главного меню. Теперь мне нужно обработать команду типа "Файл->Открыть" без использования горячих клавиш и &Буква.
Хотя бы перечень сообщений, дальше я сам разгребу потихоньку.
ANB (2005-04-21 11:17:00) [1]Дамс. Rational Robot тоже его не видит, то есть я могу не парится, а просто записывать ID.
alpet (2005-04-21 11:14:00) [2]Дело в том что указатель dwTypeDataтеперь указывает на данные определенные приложением, а не ASCIIZ строку.
ANB © (21.04.05 10:42) [17]
> Как выташить текст элемента меню с типом MFT_OWNERDRAW
1. В своем приложении: через VCL :)
2. В стороннем почти не реально, разве что через перехват API, DrawText,TextOut (доступно будет после отрисовки меню, что можно попытаться сделать назначив меню окну созданному из dll внедренной в АП исходного процесса). На какое-то конкретное приложение можно потратить время и исследовать что передается в указателе. Как правило это структура данных MFC / VCL или других библиотек.
ANB (2005-04-21 10:42:00) [3]Разобрался, как я сломал свое меню. Как только пункту меню присваиваешь значок, то он меняет свой тип на MFT_OWNERDRAW. Причем меняются тип всего уровня. А я как раз дурью маялся, засунул картинку в верхний уровень главного меню, не понравилось - убрал. Но строки меню теперь вытащить не могу.
Переформулирую вопрос :
Как выташить текст элемента меню с типом MFT_OWNERDRAW ?
if (MenuItemInfo.cch = 0) then begin- вот это тоже не работает.
SetLength(MenuText, 1024);
iSize := GetMenuString(hCurMenu, iMenu, PChar(MenuText), 1023, MF_BYPOSITION);
SetLength(MenuText, iSize);
end;
ANB (2005-04-21 10:32:00) [4]Вторая странность - у IE вижу хэндл меню, а пытаюсь вытащить количество пунктов в главном меню :
MainMenuCount := GetMenuItemCount(hCurMenu);
- получаю 0; :(((
ANB (2005-04-21 10:29:00) [5]Так, начал разбираться.
У моего меню у всех пунктов тип определяется как MFT_OWNERDRAW
(а у разделителей вообще не определяется непонятно чем).
У блокнота элементы меню типа MFT_STRING, посему строка и вытаскивается. И чего делать ?
ANB (2005-04-21 09:52:00) [6]
procedure MenuTree(sPrevMenu : String; hCurMenu : HMENU);
var MenuItemInfo : TMenuItemInfo;
MenuText : String;
MainMenuCount : Integer;
iMenu : UINT;
begin
// Если меню не определено - выйдем
if (hCurMenu = 0) then Exit;
// Найдем количество элементов меню
MainMenuCount := GetMenuItemCount(hCurMenu);
if (MainMenuCount <= 0) then Exit;
// Переберем все элементы
for iMenu := 0 to MainMenuCount - 1 do begin
// Достанем текст очередного элемента
SetLength(MenuText, 1024);
ZeroMemory(@MenuItemInfo, SizeOf(MenuItemInfo));
MenuItemInfo.cbSize := 44;
MenuItemInfo.fMask := MIIM_SUBMENU or MIIM_STRING or MIIM_ID;
// or MIIM_TYPE
// or MIIM_CHECKMARKS or MIIM_STATE or MIIM_DATA;
MenuItemInfo.dwTypeData := PChar(MenuText);
MenuItemInfo.cch := Length(MenuText) - 1;
if (GetMenuItemInfo(hCurMenu, Cardinal(iMenu), LongBool(True), MenuItemInfo))
then begin
SetLength(MenuText, MenuItemInfo.cch);
if (sPrevMenu <> '')
then MenuText := sPrevMenu + ' -> ' + MenuText;
if (MenuItemInfo.fType <> MFT_SEPARATOR)
then begin
Inc(Menu_No);
// Добавление в виртуальную таблицу, можно заменить
with fmWindowBrowser.vtMenu do begin
Append;
FieldByName('No').AsInteger := Menu_No;
FieldByName('Text').AsString := MenuText;
// FieldByName('ID').AsInteger := wID;
FieldByName('ID').AsInteger := MenuItemInfo.wID;
Post;
end;
end;
// Если есть подчиненное меню, то вызовем его
if (MenuItemInfo.hSubMenu <> 0)
then MenuTree(MenuText, MenuItemInfo.hSubMenu);
end;
end;
end;
ANB (2005-04-21 09:32:00) [7]
> GetMenuItemInfo (Menu.Items[0].Handle, 0, true, mi);
- это конечно, клево. Но Menu.Items[0] - это уже, кажись, меню "File", а мне по всему дереву надо пройти. В hSubMenu лежит хэндл вложенного меню. Короче, я поставил все флаги, какие можно, из половины приложений все приехало. А из моего и из IE нет. Точнее, меню достаются, но без текста. Ща я еше поэкспериментирую и окончательный вариант уже выложу в исходнике.
GetMenuString (Menu.Handle, GetMenuItemID (Menu.Handle, 1), dst, 256, MF_BYCOMMAND);- почему то тоже не помогло.
Особенность - если меню без значков - все ОК, если воткнул значки, то текст пропадает. Причем срубание значков не помогает.
alpet (2005-04-20 18:21:00) [8]> Да, мне еще чилды доставать надо, посему mi.fMask := MIIM_STRING; - мне мало, он hSubMenu не вертает.
Еще как возвращает:
...
GetMenuItemInfo (Menu.Items[0].Handle, 0, true, mi);
...
Мне совершенно правильно выдает "Exit".
TMenuItem
Indicates the Windows menu handle of the drop-down menu associated with the menu item.
property Handle: HMENU;
Description
Use Handle when calling a Windows API function that requires a menu handle. Handle is only valid if the Count property is greater than 0.
alpet (2005-04-20 18:05:00) [9]С помощью GetMenuString:
procedure TForm1.FormCreate(Sender: TObject);
var dst: array [0..255] of char;
begin
GetMenuString (Menu.Handle, GetMenuItemID (Menu.Handle, 1), dst, 256, MF_BYCOMMAND);
caption := dst;
end;
ANB (2005-04-20 18:00:00) [10]Ща попробую. Самый прикол - другие Delphi приложения ест. Не ест IE и мое. Да, мне еще чилды доставать надо, посему mi.fMask := MIIM_STRING; - мне мало, он hSubMenu не вертает.
alpet (2005-04-20 17:56:00) [11]Может не все иницируешь правильно?
А у меня работает:
Например, если у меня первый элемент меню "Файл" - код устанавливает заголовок формы в "Файл", а если "File" - "&File".
procedure TForm1.FormCreate(Sender: TObject);
var mi: TMenuItemInfo;
dst: array [0..255] of char;
begin
FillChar (mi, sizeof (mi), 0);
mi.cbSize := sizeof (mi);
mi.fMask := MIIM_STRING;
mi.dwTypeData := @dst;
mi.cch := 256;
GetMenuItemInfo (Menu.Handle, 0, true, mi); // get item by index
caption := mi.dwTypeData;
end;
ANB (2005-04-20 17:34:00) [12]Не, все доступно. Получаю количество пунктов, а текст не едет. Я уже и GetMenuItemInfo и GetMenuString(hMenu, MenuItemInfo.wID, PChar(MenuText), 1023, MF_BYCOMMAND); попробовал. Только вместо текста - пустая строка.
alpet (2005-04-20 17:29:00) [13]Не доступна переменная Form.Menu или Form.Menu.Handle ?
ANB (2005-04-20 17:25:00) [14]Интересно, меню блокнота и редактора реестра достается, а вот меню собственного приложения (Delphi) вытащить не могу. Почему бы это и как с этим бороться ?
ANB (2005-04-18 11:15:00) [15]
> alpet © (15.04.05 18:12) [4]
спасибо. Дальше разберусь по хэлпам.
alpet (2005-04-15 18:12:00) [16]У тебя есть дескриптор основного меню. У меню есть наверняка несколько элементов (см. GetMenuItemCount). Для каждого элемента ты можешь получить информацию (в структуре TMenuItemInfo) с помощью GetMenuItemInfo. Например элемент структуры hSubMenu - дает возможность проделать тоже самое и с подменю (просмотреть элементы). С помощью указанной функции можно получать также ID, Text и Bitmap для каждого элемента.
ANB (2005-04-15 17:55:00) [17]
> или в качестве альтернативы перебирать по пунктикам с помощью
> GetMenuItemInfo.
- во во, отсель поподробнее, плз.
alpet (2005-04-15 17:32:00) [18]Для того что бы вызвать обработчик нужного пункта меню - отправь мессагу WM_COMMAND (wParam = menu item ID).
Что бы узнать ID - придется раскапывать ресурсы этого приложения, и осуществлять "поиск по тексту", или в качестве альтернативы перебирать по пунктикам с помощью GetMenuItemInfo.
Eraser (2005-04-15 17:18:00) [19]ANB ©
Со всеми меню работать не удастья, максимум можно повторить то что делает программа Windows Scanner от Inq Soft.