Re[3]: Internet Explorer-style menu bar
От: karol  
Дата: 11.01.03 17:39
Оценка:
Вот так это сделал я:

const menuCount=... //сколько выпадающих меню

int curId; //текущее отображаемое подменю главного меню
HMENU menus[menuCount]; //хэндлы всех выпадающих меню

LRESULT CALLBACK menuHookProc(int cmd, WPARAM wp, LPARAM lp);//наш хук

void processMenu(int id){ //наш модальный цикл обработки меню

menuHook=SetWindowsHookEx(WH_MSGFILTER, menuHookProc, inst, 0);
for(;){
SendMessage(mbar, TB_PRESSBUTTON, id, 1); //нажимаем кнопку в строке меню
RECT r;
SendMessage(mbar, TB_GETRECT, id, (LPARAM)&r);
POINT pos={r.left, r.bottom};
ClientToScreen(mbar, &pos);
TrackPopupMenu(menus[id-1], TPM_LEFTALIGN|TPM_LEFTBUTTON, pos.x, pos.y, 0,
mainWnd, NULL);
SendMessage(mbar, TB_SETSTATE, id, MAKELONG(TBSTATE_ENABLED, 0)); //отжимаем кнопку
if(!curId || curId==id) break;
id=curId;
}
curId=0;
UnhookWindowsHookEx(menuHook);
menuHook=NULL;
}
void showMenu(int id){ //мы вызываем эту функцию, чтобы открыть одно из выпадающих меню
curId=id;
if(menuHook) SendMessage(mainWnd, WM_CANCELMODE, 0, 0);
}

LRESULT CALLBACK menuHookProc(int cmd, WPARAM wp, LPARAM lp){
if(cmd==MSGF_MENU){
MSG &m=*(MSG*)lp;
if(m.message==WM_MOUSEMOVE){ //транслируем событие строке меню
POINT p=m.pt;
ScreenToClient(mbar, &p);
SendMessage(mbar, WM_MOUSEMOVE, m.wParam, MAKELPARAM(p.x, p.y));
}else if(m.message==WM_KEYDOWN){ //обрабатываем кнопки
if(m.wParam==VK_LEFT){
if(curId==1) showMenu(menuCount-1); else showMenu(curId-1);
}else if(m.wParam==VK_RIGHT){
if(curId==menuCount-1) showMenu(1); else showMenu(curId+1);
}
... остальные кнопки
}
}
return CallNextHookEx(menuHook, cmd, wp, lp);
}

... где-то в оконной процедуре

case WM_NOTIFY:
if(wp==idMenubarControl){
NMTOOLBAR &n=*(NMTOOLBAR*)lp;
if(n.hdr.code==TBN_DROPDOWN){
showMenu(n.iItem);
return TBDDRET_DEFAULT;
}else if(n.hdr.code==TBN_HOTITEMCHANGE){
NMTBHOTITEM &n=*(NMTBHOTITEM*)lp;
if(menuHook && n.idNew && n.idNew!=curId) showMenu(n.idNew);
}
}
break;


... в цикле обработки сообщений

while(GetMessage(&msg, 0,0,0)){
...
if(curId && !menuHook) processMenu(curId);
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.