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);
}
Пока на собственное сообщение не было ответов, его можно удалить.