Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2002.12.26;
Скачать: [xml.tar.bz2];

Вниз

Popup меню   Найти похожие ветки 

 
Almaz   (2002-11-10 04:13) [0]

Господа !
Как известно при нажатии правой кнопки мыши на окне с классом EDIT, отображается popup меню (Отменить, Вырезать, Копировать и т.д.). Так вот вопрос в том как отловить момент создания (или отображения) этого меню в любом окне и добавить в него свой пункт ?
Заранее спасибо.


 
Almaz   (2002-11-10 04:15) [1]

Да, совсем забыл, что проблема возникла в основном потому, что это popup меню не генерирует при своем вызове сообщение WM_INITMENUPOPUP. (Его легко можно было бы отловить хуком)


 
Song   (2002-11-10 09:04) [2]

WM_CONTEXTMENU ?


 
Ученик   (2002-11-10 09:10) [3]

>Almaz © (10.11.02 04:13)
Наверно, проще пойти по пути написания наследника от TPopupMenu, возможность требуется достаточно часто, достаточно бросить компонент на форму.


 
Almaz   (2002-11-10 17:08) [4]


> Song © (10.11.02 09:04)
> WM_CONTEXTMENU ?

А где я HMENU popup"a возьму ? WM_INITMENUPOPUP содержит информацию о вызываемом меню, а WM_CONTEXTMENU нет.


 
Almaz   (2002-11-10 17:10) [5]


> Ученик © (10.11.02 09:10)
> >Almaz © (10.11.02 04:13)
> Наверно, проще пойти по пути написания наследника от TPopupMenu,
> возможность требуется достаточно часто, достаточно бросить
> компонент на форму.

Оно конечно можно было бы, но мне надо не на своей форме а на всех EDIT"ах в системе. В этом то и проблема :(((


 
Song   (2002-11-10 18:11) [6]

Ну а hMenu взять через GetMenu по факту возникновения WM_CONTEXMENU.


 
Suntechnic   (2002-11-10 18:39) [7]

>Almaz © (10.11.02 04:15)
Да, совсем забыл, что проблема возникла в основном потому, что это popup меню не генерирует при своем вызове сообщение WM_INITMENUPOPUP. (Его легко можно было бы отловить хуком)

Кстати это не совсем верно. Я не знаю где ты его пытался ловить(судя по посту где-то хуком), но это достаточно легко проверить. Подмени оконную процедуру любого едита и ты увидишь, что сообщение всё-таки генериться.


 
Almaz   (2002-11-10 23:20) [8]


> Song © (10.11.02 18:11)
> Ну а hMenu взять через GetMenu по факту возникновения WM_CONTEXMENU.

GetMenu не работает на EDIT"ах.


 
Almaz   (2002-11-10 23:34) [9]


> Suntechnic © (10.11.02 18:39)
> Кстати это не совсем верно. Я не знаю где ты его пытался
> ловить(судя по посту где-то хуком), но это достаточно легко
> проверить. Подмени оконную процедуру любого едита и ты увидишь,
> что сообщение всё-таки генериться.

Вы правы, сообщение я пытаюсь ловить именно хуком. Попробовал по вашему совету создать подкласс окна и проверять сообщение прямо в его оконнной процедуре - сообщения НЕТ.


 
Suntechnic   (2002-11-11 03:43) [10]

>Almaz © (10.11.02 23:34)
Вы правы, сообщение я пытаюсь ловить именно хуком. Попробовал по вашему совету создать подкласс окна и проверять сообщение прямо в его оконнной процедуре - сообщения НЕТ.

Я тоже попробовал, только несколько подругому. Окно я сам не создавал. Создал диалоговое окно на основе ресурса. Добавил туда едит. Подменил окнонную процедуру с помощью GetWindowLog/SetWindowLong. Вот оно сообщение...


 
Ученик   (2002-11-11 08:53) [11]

>Suntechnic © (11.11.02 03:43)
А почему его Spy++ не показывает ?


 
Suntechnic   (2002-11-11 09:14) [12]

>Ученик © (11.11.02 08:53)
Наверное по той же самой причине по которой вы его хуком не ловите.
А вообще Вы сами возьмите да попробуйте сделать то, о чём я писал.


 
Ученик   (2002-11-11 09:32) [13]

>Suntechnic © (11.11.02 09:14)
А какое сообщение ловится ?


 
Suntechnic   (2002-11-11 09:35) [14]

>Almaz © & Ученик ©
Сорри. После уточнения эксперимента выяснилось, что я всё-таки не то поймал :). Похоже что WM_INITMENUPOPUP всё-таки вообще не генерится как таковое.


 
Ученик   (2002-11-11 09:49) [15]

>Almaz ©
Вроде можно через перехват функции TrackPopupMenuEx, по-крайней мере она вызывается когда вызывается меню в Edit (поставил точку останова в TrackPopupMenuEx в отладчике), реализации пока нет.


 
Ученик   (2002-11-11 10:13) [16]

>Ученик © (11.11.02 09:49)
С перехватом проблема в том, что TrackPopupMenuEx вызывается внутри User32.dll, поэтому необходимо внедрять код внутрь TrackPopupMenuEx, а это уже завязка на версию Windows :(


 
Almaz   (2002-11-11 16:11) [17]


> >Ученик © (11.11.02 09:49)
> С перехватом проблема в том, что TrackPopupMenuEx вызывается
> внутри User32.dll, поэтому необходимо внедрять код внутрь
> TrackPopupMenuEx, а это уже завязка на версию Windows :(
>

Сейчас такое скажу... Перехватил я вызовы TrackPopupMenuEx и TrackPopupMenu (на всякий случай :))
Так вот ОНИ НЕ ВЫЗЫВАЮТСЯ при показе этого меню !!!!
Все остальные popup"ы других окон и контролов перехватываются на 100%, а это не отлавливается ! Т.е. похоже, что для показа этого "popup menu" используется что-то иное нежели TrackPopupMenu, что в общем то и объясняет отсутствие WM_INITMENUPOPUP, которое генериться этой функцией.
Теперь я окончательно не знаю, что делать...


 
Ученик   (2002-11-11 18:56) [18]

>Almaz © (11.11.02 16:11)
Вызов TrackPopupMenuEx (который также в User32.dll) происходит внутри User32.dll, там прямой вызов, обычные перехваты не работают


 
Ученик   (2002-11-11 21:42) [19]

>Ученик © (11.11.02 09:49)

Это для своего приложения, по аналогии, наверно, можно и для других (уже через Hook)

Содержимое команд MyTrackPopupMenuEx зависит от версии Windows,
это для Windows XP, для Windows 2000 они точно другие, наверно можно сделать универсально, копируя достаточно большой кусок оригинального кода.

function MyTrackPopupMenuEx(hMenu: HMENU; Flags: UINT; x, y: Integer;
Wnd: HWND; TPMParams: PTPMParams): BOOL; stdcall;
begin
InsertMenu(hMenu, DWORD(-1), MF_BYPOSITION or MF_MENUBREAK, 0, nil);
InsertMenu(hMenu, DWORD(-1), MF_BYPOSITION or MF_STRING, 1000, "Test");
asm
pop ecx
pop ebp
mov eax, $00001235
mov edx, $7FFE0300
call edx
ret $18
end
end;

const
MyTrackPopupMenuExPtr : Pointer = @MyTrackPopupMenuEx;

procedure TForm1.Button1Click(Sender: TObject);
var
JmpFrame : packed record
Command : Word;
Address : Pointer;
end;
pTrackPopupMenuEx : Pointer;
dwOldProtect, dwProtect : DWORD;
begin
JmpFrame.Command := $25FF;
JmpFrame.Address := @MyTrackPopupMenuExPtr;
pTrackPopupMenuEx := GetProcAddress(GetModuleHandle("user32.dll"), "TrackPopupMenuEx");
if VirtualProtect(pTrackPopupMenuEx, sizeof(JmpFrame),
PAGE_EXECUTE_READWRITE, dwOldProtect) then begin
MoveMemory(pTrackPopupMenuEx, @JmpFrame, sizeof(JmpFrame));
VirtualProtect(pTrackPopupMenuEx, sizeof(JmpFrame),
dwOldProtect, dwProtect)
end
end;


 
Ученик   (2002-11-11 22:05) [20]

Вариант для DLL-ного хука, проверил - все работает, хук ставил на WH_GETMESSAGE, замену TrackPopupMenuEx на обработку DLL_PROCESS_ATTACH

function MyTrackPopupMenuEx(hMenu: HMENU; Flags: UINT; x, y: Integer;
Wnd: HWND; TPMParams: PTPMParams): BOOL; stdcall;
begin
InsertMenu(hMenu, DWORD(-1), MF_BYPOSITION or MF_MENUBREAK, 0, nil);
InsertMenu(hMenu, DWORD(-1), MF_BYPOSITION or MF_STRING, 1000, "Test");
asm
{ какие именно регистры нужно восстанавливать, нужно смотреть на входе MyTrackPopupMenuEx}
pop esi
pop ebx
pop ebp
{ оригинальный TrackPopupMenuEx }
mov eax, $00001235
mov edx, $7FFE0300
call edx
ret $18
end
end;


 
Almaz   (2002-11-11 23:27) [21]


> Ученик © (11.11.02 18:56)

Огромное человеческое спасибо !!!
А я напрочь забыл про то, что там прямой вызов :((( Старею наверно... ;)
Перехват реализовал, но правда несколько другим способом чем Вы, получилось правда более громозко, но вроде универсально (в смысле версий, но не платформ, к сожалению).

Еще раз спасибо и удачи.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2002.12.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.62 MB
Время: 0.043 c
14-86092
dimich1978
2002-12-04 13:44
2002.12.26
Trial (work while IDE is running)


6-86058
Novichek
2002-10-16 01:07
2002.12.26
Как узнать ай-пи сервера


8-86047
Сергей Медяник
2002-09-11 00:57
2002.12.26
Блокировка PopUp меню в TWebBrowser


1-85957
Zolotov
2002-12-15 15:20
2002.12.26
Как сделать, чтобы она форма закрвалась, а вторая появлялась.


14-86075
Треугольник
2002-12-04 04:37
2002.12.26
Помогите кто может ....





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский