![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Отмена показа подменю
Юрий Зотов © (2002-06-03 18:51:00)Есть такая цепочка.
1. Оконный компонент инициирует показ подменю:
TrackPopupMenuEx(.., хэндл_своего_окна, nil);
2. Программа входит в Menu Loop но работает локальный хук WH_GETMESSAGE. При некотором условии он блокирует обычную обработку поступившего сообщения и посылает тому же компоненту другое сообщение, а тот должен убрать текущее подменю и показать другое. Делаю это так:
SendMessage(хэндл_своего_окна, WM_CANCELMODE, 0, 0);
TrackPopupMenuEx(.., хэндл_своего_окна, nil);
В итоге имеем вот что:
Первый вызов TrackPopupMenuEx работает нормально - окно получает сообщение WM_INITPOPUPMENU, подменю появляется, его пункты кликаются, их обработчики вызываются.
Посылка WM_CANCELMODE внешне тоже работает нормально (во всяком случае, подменю исчезает, а окно получает сообщение WM_UNINITPOPUPMENU).
Второй вызов TrackPopupMenuEx ничего не дает, а функция возвращает False. В чем дело - непонятно. Подозреваю, что что-то не так с освобождением захвата мыши в Menu Loop, но что именно и как с этим бороться?
Diamond Cat (2002-06-04 01:54:00) [1]Юрий , ура ты вновь объявился, слушай у меня опять сдох винт и сним все твои координаты, напиши мне пожалуйста.
Извините что не по теме
Shaman_Naydak (2002-06-03 21:49:00) [2]Как раз потому что возможно встроить свою цепочку в работу алгоритма и получаются сбои..
Вот представьте себе конечный автомат, произошло действие, переводящее его из состояние 0 в 1, сделались какие-то действия, на переход был вызван обработчик события,в котором программер принудительно перевел автомат в положение 2.. Но обработка перехода-то не закончилась!! Потому и получается глюк..
Конечно, правильнее было после каждого возврата из обработчика события проверять, в том ли мы состоянии находимся, в котором были до обработчика, и только в этом случае продолжать обработку.. но это геморрно, сами понимаете.
как вариант - вызов обработчика тоже ставить после завершения перехода (но это не всегда правильно и возможно, часто бывает нужно совсем даже наоборот)..
Несколько сумбурно, но я думаю, вы меня поймете
Юрий Зотов (2002-06-03 19:57:00) [3]Все, проблема решена, спасибо за подсказку. Конечно, отмену и перепоказ надо ставить в очередь, иначе к моменту второго вызова TrackPopupMenuEx первый вызов еще действительно не будет завершен.
Все это - иллюстрация на тему того, что никакого событийного программирования на самом деле не существует, а существует старое доброе линейное.
Юрий Зотов (2002-06-03 19:33:00) [4]Как и предполагалось, GetLastError говорит "Popup menu already active" (то есть, первый вызов TrackPopupMenuEx система еще не считает завершенным).
К тому же самому приводит и
Keybd_Event(VK_ESCAPE, MapVirtualKey(VK_ESCAPE, 0), 0, 0);
вместо посылки WM_CANCELMODE. Интересно, что при ФИЗИЧЕСКОМнажатии Esc все работает нормально. Как и при ФИЗИЧЕСКИХкликах мышкой куда-то мимо меню.
Shaman_Naydak (2002-06-03 19:09:00) [5]А что GetLastError говорит??
Попробуй действия по отмене старого/показу нового меню делать не из обработчика.. в обработчике просто поставь в очередь (через PostMessage) свое сообщение, а уже в обработчике оного соверши финт ушами..
Удачи