Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Не закрывающееся всплывающее меню


Автор: Igor_thief 14.6.2007, 15:54
Как сделать всплывающее меню, которое выполняет нужное действие по нажатию на пункте меню, но при этом не исчезает (например как в Office 2007 кликаешь по статус бару)? Например, если при нажатии на пункт меню должна пояиться отметка (галочка), то она появляется, но при этом меню не прячется.

Автор: _hunter 14.6.2007, 16:20
для этого придется сделать форму, выглядящую как меню и показывать эту форму...

Автор: Igor_thief 14.6.2007, 16:36
Ну это конечно же способ, но не очень удобный. Например, если я такое дело буду применять в главном меню у которого будет нескольго основных menuitem, то когда я покажу свою форму по нажатию на один из пунктов, а потом переведу курсор мыши на другой пункт основного меню, то моя форма не скроется. И вообще, не очень прикольный подход.

Ведь делают же люди даже так, например, выпало меню по нажатию на один из пунктов меню; в выпавшем меню есть 10 пункто; 5 имеет подмею; когда наводишь на 5 пункт, подменю не вываливавется, а вываливается только тогда, когда ты клацнешь на стрелочку (которая является индикатором что есть подменю). Ведь при клике развернутое меню тоже не спряталось!

Должен быть способ!

Автор: 0LineGate 14.6.2007, 17:52
onpopup запоминай координаты курсора, и при клике на кадый итем попайпой менюшку снова

Автор: aktuba 14.6.2007, 18:50
Цитата

Должен быть способ! 


Системные меню не предоставляют таких возможностей. Все, что ты назвал - это самописные варианты панелей/форм.

Цитата

onpopup запоминай координаты курсора, и при клике на кадый итем попайпой менюшку снова 


Мерцать будет.

Автор: Yanis 14.6.2007, 19:29
Цитата(Igor_thief @  14.6.2007,  17:36 Найти цитируемый пост)
Ведь при клике развернутое меню тоже не спряталось!

Ибо TrackPopupMenuEx smile

Автор: Igor_thief 14.6.2007, 20:37
Цитата(Yanis @  14.6.2007,  18:29 Найти цитируемый пост)
Ибо TrackPopupMenuEx smile 

А теперь бы еще популярнее и с примером  smile 

Для прояснение второй ситуации которую я описывал привожу два скриншота:
в принципе все понятно; если нажму на пункт меню, то тупо выполнится команда; если нажму на стрелочку то увижу второй скриншот smile


Автор: Igor_thief 14.6.2007, 20:37
скриншот 2

Ну а на третем видно какой компонент используется. Я конечно понимаю что можно достать компонент, но не хочется ради отдельной примочки ставить разные компоненты.

Автор: bems 14.6.2007, 20:38
фильтровать сообщения WH_MSGFILTER пробовал?

Автор: Igor_thief 14.6.2007, 20:42
Цитата(bems @  14.6.2007,  19:38 Найти цитируемый пост)
фильтровать сообщения WH_MSGFILTER пробовал? 

нет, еще нет. Просто не знал про него. Шас поищу инфу.

скриншот 3

Автор: bems 14.6.2007, 20:48
а на первом скриншоте это не команда меню, а подменю. дык оно и так работает для пунктов с подменю и разделителей

Автор: Igor_thief 14.6.2007, 21:40
Цитата(bems @  14.6.2007,  19:48 Найти цитируемый пост)
а на первом скриншоте это не команда меню, а подменю. дык оно и так работает для пунктов с подменю и разделителей 

Ты не прав! При нажатии ИМЕННО на самом пункте выполнится команда (у меня есть и другие примеры; например откроется окно)!; подменю появляется только если я кликну ИМЕННО на стрелочке, которая указывает на то что есть подменю и в этом случае я смогу выбрать другую команду. Просто поверь в это, а то пришлю еще скриншоты!  smile 

ПС: так неудобно постить в этот форум скриншоты! Только вот не надо говорить что сначала надо залить их кудато, а потом сувать сюда урл - это неудобно! 

Автор: Yanis 15.6.2007, 08:06
Цитата(Igor_thief @  14.6.2007,  22:40 Найти цитируемый пост)
ПС: так неудобно постить в этот форум скриншоты! Только вот не надо говорить что сначала надо залить их кудато, а потом сувать сюда урл - это неудобно!

Тебе http://forum.vingrad.ru/index.php?show_type=forum&showforum=316. Можешь возмутиться или сделать предложение по улучшению. Я поддержу.

Автор: Sunvas 15.6.2007, 11:15
Igor_thief, на последнем скрине ясно видно, что меню это на самом-то деле никакое не меню, а контрол бар.

Автор: Igor_thief 15.6.2007, 11:32
Цитата(Sunvas @  15.6.2007,  10:15 Найти цитируемый пост)
Igor_thief, на последнем скрине ясно видно, что меню это на самом-то деле никакое не меню, а контрол бар. 

Да хоть лейбл smile Выпадает в итоге МЕНЮ. Кая мне разница откудова выпадает smile Главное что это меню.  Если на форму бросить меню и тулбар и потом назначить это меню тулбару через соответсвуещее меню, то это будет тоже тулбар, при нажатии на кнопочки которого выпадает меню. Вот об выпавшем меню и идет речь.

Надеюсь что теперь уже все прояснилось и можно продвигаться дальше по сути.

Автор: bems 15.6.2007, 19:16
написал пример
вот такой модуль:
Код

unit MyMenus;

interface
uses Menus;

var OnMenuMouseMsg:procedure (Msg:cardinal;Item:TMenuItem;out Hide:boolean)=nil;

implementation
uses messages,windows,SysUtils;

type TMyPopupList=class(TPopupList)
                  private
                   FLastMenuItem:TMenuItem;
                   procedure Hook;
                   procedure Unhook;
                   function AllowHideMenu(msg:DWORD;Item:TMenuItem):boolean;
                  public
                   constructor Create(CreateFrom:TPopupList);
                   destructor Destroy;override;
                   procedure Assign(List:TPopupList);reintroduce;
                  protected
                   procedure WndProc(var Message:TMessage);override;
                  end;

var HHook:windows.HHOOK=0;

function TMyPopupList.AllowHideMenu(msg:DWORD;Item:TMenuItem):boolean;
begin
if (item=nil) or (@OnMenuMouseMsg=nil)
   then result:=true
   else OnMenuMouseMsg(msg,item,result);
end;

function FilterMenuMouseMsg(const msg:TMsg):integer;
begin
 if (msg.message>=WM_LBUTTONDOWN) and
    (msg.message<=WM_MBUTTONDBLCLK)
   then result:=SendMessage(PopupList.Window,msg.message,msg.wParam,msg.lParam)
   else result:=0;
end;

function HookProc(code:integer;wParam:WPARAM;var msg:TMSG):LRESULT;stdcall;
begin
result:=integer(code=MSGF_MENU);
if boolean(result) then result:=FilterMenuMouseMsg(msg);
if not boolean(result) then result:=CallNextHookEx(HHook,code,wParam,integer(@msg));
end;

procedure TMyPopupList.WndProc(var Message: TMessage);
var FindKind:TFindItemKind;i,Item:integer;info:TMenuInfo;
begin
case message.Msg of
 WM_EXITMENULOOP:FLastMenuItem:=nil;
 WM_LBUTTONDOWN..WM_MBUTTONDBLCLK:begin
                                  message.Result:=integer(not AllowHideMenu(message.msg,FLastMenuItem));
                                  if boolean(message.Result) then exit;
                                  end;
 WM_MENUSELECT:with TWMMenuSelect(Message) do//подглядел в menus.pas
                begin
                FindKind:=fkCommand;
                if MenuFlag and MF_POPUP<>0
                   then FindKind:=fkHandle;
                for i:=0 to Count-1 do
                    begin
                    if FindKind=fkHandle
                       then if Menu=0
                               then Item:=-1
                               else Item:=GetSubMenu(Menu,IDItem)
                       else Item:=IDItem;
                    FLastMenuItem:=TPopupMenu(Items[i]).FindItem(Item, FindKind);
                    end;
                end;
end;
inherited
end;

procedure TMyPopupList.Assign(List:TPopupList);
begin
inherited Assign(List);
FWindow:=List.Window;
end;

constructor TMyPopupList.Create(CreateFrom:TPopupList);
begin
inherited Create;
if assigned(CreateFrom)
   then begin
        Assign(CreateFrom);
        CreateFrom.Free
        end;
Hook;
end;

destructor TMyPopupList.Destroy;
begin
inherited;
Unhook
end;

procedure TMyPopupList.Hook;
begin
HHook:=SetWindowsHookEx(WH_MSGFILTER,@HookProc,0,GetCurrentThreadID);
end;

procedure TMyPopupList.Unhook;
begin
if HHook<>0 then begin
                 UnhookWindowsHookEx(HHook);
                 HHook:=0
                 end;
end;

initialization
PopupList:=TMyPopupList.Create(PopupList);

finalization

end.


в модуле формы:
Код

procedure MenuMsgHandler(Msg:cardinal;Item:TMenuItem;out Hide:boolean);
begin
hide:=(length(Item.Caption) mod 2) = 1 //тут твое решение
//а пока прячем при нажатии на пункты с нечетным числом букв :)
//или наоборот (в Item.Caption есть еще "&")
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
OnMenuMouseMsg:=MenuMsgHandler; //устанавливаешь свой обработчик
end;

пример неправильно работает когда щелкаешь мимо меню. Но есть с чего начать

Добавлено через 2 минуты и 28 секунд
тестил только с TPopupMenu

Автор: Igor_thief 15.6.2007, 23:11
bems, большое спасибо за пример. Только что вернулся с тренировки и очень устал, поэтому код еще особо не разбирал. Сейчас лягу посплю, а завтра утричком, первым же делом изучу код и напишу комментарии.

ПС: я очень рад что есть начало! это дает надежду! спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)