📄 menubar.cpp
字号:
// ::GetClassName(pWnd->GetSafeHwnd(), str, 256);
// LTRACE2(_T(" server wnd : %s\n"), str);
return pWnd;
}
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CMDIClientHook
CMDIClientHook::CMDIClientHook()
{
m_pMenuBar = NULL;
}
BOOL CMDIClientHook::Install(CMenuBar* pMenuBar, HWND hWndToHook)
{
ASSERT_VALID(pMenuBar);
ASSERT(m_pMenuBar == NULL);
m_pMenuBar = pMenuBar;
return HookWindow(hWndToHook);
}
CMDIClientHook::~CMDIClientHook()
{
HookWindow((HWND)NULL);
}
LRESULT CMDIClientHook::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
ASSERT_VALID(m_pMenuBar);
switch (nMsg) {
case WM_MDISETMENU: // only sent to MDI client window
// Setting new frame/window menu: bypass MDI. wParam is new menu.
if (wParam) {
//LTRACE(_T("CMenuBar::WM_MDISETMENU 0x%04x\n"), wParam);
CMenuEx* pMenuTmp=(CMenuEx*)CMenu::FromHandle((HMENU)wParam);
CMenuEx* pMenuTmp2=(CMenuEx*)CMenu::FromHandle((HMENU)lParam);
if(pMenuTmp && !pMenuTmp->IsKindOf(RUNTIME_CLASS(CMenuEx))) return 0;
if(pMenuTmp2 && !pMenuTmp2->IsKindOf(RUNTIME_CLASS(CMenuEx))) return 0;
m_pMenuBar->OnSetMenu(pMenuTmp,pMenuTmp2);
}
return 0;
case WM_MDIREFRESHMENU: // only sent to MDI client window
// Normally, would call DrawMenuBar, but I have the menu, so eat it.
//LTRACE(_T("CMenuBar::WM_MDIREFRESHMENU\n"));
return 0;
case WM_MDIACTIVATE:
{
m_pMenuBar->EnableGrayedDraw(FALSE);
if (!::IsWindow((HWND)wParam)) break;
CMDIChildWnd* pClient=(CMDIChildWnd*) CMDIChildWnd::FromHandle((HWND)wParam);
CMDIFrameEx* pFrame=((CMDIFrameEx*)(m_pMenuBar->m_pParent/*GetParentFrame()*/));
if (!pFrame->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) break;
if (pClient && pClient->IsKindOf(RUNTIME_CLASS(CMDIChildWnd)))
{
CView* pView=pClient->GetActiveView();
if(!pView) break;
CDocument* pDoc=pView->GetDocument();
if(!pDoc) break;
CMultiDocTemplateEx* pTemplate =(CMultiDocTemplateEx*)pDoc->GetDocTemplate();
if (!pTemplate->IsKindOf(RUNTIME_CLASS(CMultiDocTemplateEx))) break;
m_pMenuBar->OnSetMenu(&(pTemplate->m_mnuDocMenu),
pFrame->GetWindowMenuPopup(&(pTemplate->m_mnuDocMenu)));
}
else
{
m_pMenuBar->OnSetMenu(pFrame->GetMainMenu(),
pFrame->GetWindowMenuPopup(pFrame->GetMainMenu()));
break;
}
break;
}
case WM_MDIDESTROY:
{
CSubclassWnd* p = GetHookMap().Lookup((HWND)wParam);
ASSERT (p->IsKindOf(RUNTIME_CLASS(CMDIChildHook)));
p->HookWindow((HWND)NULL);
delete (CMDIChildHook*)p;
AfxGetMainWnd()->PostMessage(WM_ACTIVATE,WA_ACTIVE,NULL);
break;
}
case WM_MDIRESTORE:
case WM_MDIMAXIMIZE:
m_pMenuBar->EnableGrayedDraw(FALSE);
break;
// case WM_PAINT:
//LTRACE(_T("CMenuBar:WM_PAINT\n"));
// If you use no Doc-View project, when child window maximized,
// WM_PAINT never sent! so this trick never do.
// So this code moved to OnUpdateCmdUI.
// After changing the MDI maximized state, the client window gets a
// paint message. This is the most convenient place to find out; there
// is no WM_MDIMAXIMIZED message.
// if (/*m_pWndHooked->*/m_hWnd == m_pMenuBar->m_hWndMDIClient)
// m_pMenuBar->CheckActiveChildWndMaximized();
// break;
}
return CSubclassWnd::WindowProc(nMsg, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// CMDIChildHook
IMPLEMENT_DYNAMIC( CMDIChildHook, CSubclassWnd );
CMDIChildHook::CMDIChildHook()
{
m_pMenuBar = NULL;
}
BOOL CMDIChildHook::Install(CMenuBar* pMenuBar, HWND hWndToHook)
{
ASSERT_VALID(pMenuBar);
ASSERT(m_pMenuBar == NULL);
m_pMenuBar = pMenuBar;
return HookWindow(hWndToHook);
}
CMDIChildHook::~CMDIChildHook()
{
HookWindow((HWND)NULL);
}
LRESULT CMDIChildHook::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
ASSERT_VALID(m_pMenuBar);
switch (nMsg)
{
case WM_MDIACTIVATE:
{
m_pMenuBar->EnableGrayedDraw(FALSE);
CMDIFrameEx* pFrame=((CMDIFrameEx*)(m_pMenuBar->m_pParent/*GetParentFrame()*/));
if (!pFrame->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) break;
if (!::IsWindow((HWND)lParam))
{
m_pMenuBar->OnSetMenu(pFrame->GetMainMenu(),
pFrame->GetWindowMenuPopup(pFrame->GetMainMenu()));
break;
}
CMDIChildWnd* pClient=(CMDIChildWnd*) CMDIChildWnd::FromHandle((HWND)lParam);
if (pClient && pClient->IsKindOf(RUNTIME_CLASS(CMDIChildWnd)))
{
CView* pView=pClient->GetActiveView();
if(!pView) break;
CDocument* pDoc=pView->GetDocument();
if(!pDoc) break;
CMultiDocTemplateEx* pTemplate =(CMultiDocTemplateEx*)pDoc->GetDocTemplate();
if (!pTemplate->IsKindOf(RUNTIME_CLASS(CMultiDocTemplateEx))) break;
m_pMenuBar->OnSetMenu(&(pTemplate->m_mnuDocMenu),
pFrame->GetWindowMenuPopup(&(pTemplate->m_mnuDocMenu)));
}
else
{
m_pMenuBar->OnSetMenu(pFrame->GetMainMenu(),
pFrame->GetWindowMenuPopup(pFrame->GetMainMenu()));
break;
}
break;
}
case WM_SIZE:
m_pMenuBar->EnableGrayedDraw(FALSE);
break;
}
return CSubclassWnd::WindowProc(nMsg, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
// CMDIFrameHook
CMDIFrameHook::CMDIFrameHook()
{
m_pMenuBar = NULL;
m_bTimerSet=FALSE;
}
BOOL CMDIFrameHook::Install(CMenuBar* pMenuBar, HWND hWndToHook)
{
ASSERT_VALID(pMenuBar);
ASSERT(m_pMenuBar == NULL);
m_pMenuBar = pMenuBar;
return HookWindow(hWndToHook);
}
CMDIFrameHook::~CMDIFrameHook()
{
HookWindow((HWND)NULL);
if (m_bTimerSet)
{
m_pMenuBar->m_pParent->KillTimer((UINT)this);
m_bTimerSet=FALSE;
m_pMenuBar->EnableGrayedDraw(FALSE);
}
}
LRESULT CMDIFrameHook::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
ASSERT_VALID(m_pMenuBar);
// be care for other windows(MainFrame) hooking
// possible called when already this wnd destroyed (WM_NCACTIVATE is)
if (!::IsWindow(m_pMenuBar->m_hWnd)) {
return CSubclassWnd::WindowProc(nMsg, wParam, lParam);
}
BOOL bSend = FALSE;
if (HWND hWndServer = m_pMenuBar->OleMenuDescriptor(bSend, nMsg, wParam, lParam)) {
// OLE wnd will handle message
if (bSend)
return ::SendMessage(hWndServer, nMsg, wParam, lParam);
else
return ::PostMessage(hWndServer, nMsg, wParam, lParam);
}
CMenuEx* pMenuTmp;
m_pMenuBar->m_pMenu->TrapWindowProc(nMsg, wParam, lParam);
switch (nMsg) {
case WM_MOUSEACTIVATE:
if(m_pMenuBar->m_pMenu)
{
m_pMenuBar->EnableGrayedDraw(FALSE,1);
}
break;
case WM_COMMAND:
if (lParam==NULL && LOWORD(wParam)==(WORD)ID_SHOWFULL)
{
m_pMenuBar->m_pParent->KillTimer((UINT)this);
m_bTimerSet=FALSE;
if(m_pMenuBar->m_pMenu)
m_pMenuBar->EnableGrayedDraw(TRUE,TRUE);
CRect r;
if(m_pMenuBar->GetItemRect(m_pMenuBar->m_nLastIndex,r))
{
m_pMenuBar->m_bNoTimer=TRUE;
int j;
j=m_pMenuBar->m_arrDepth;
//如去掉ID_SHOWFULL判断时,应注释掉下面一行,以避免选择菜单项后,菜单仍不消失问题。
m_pMenuBar->PostMessage(WM_LBUTTONDOWN,MK_LBUTTON,r.left+(r.top<<16));
m_pMenuBar->ReOpenMenu(j);
m_pMenuBar->m_bNoTimer=FALSE;
m_pMenuBar->m_bLoop = TRUE; // continue loop
}
m_pMenuBar->m_Rect.SetRectEmpty();
}
else
{
if(m_pMenuBar->m_pMenu)
{
m_pMenuBar->EnableGrayedDraw(FALSE,1);
}
m_pMenuBar->UpdateMenuRefresh(LOWORD(wParam));
}
break;
case WM_TIMER:
{
if(wParam==(WPARAM)this)
{
m_pMenuBar->m_pParent->KillTimer((UINT)this);
m_bTimerSet=FALSE;
CRect r;
if(m_pMenuBar->GetItemRect(m_pMenuBar->m_nLastIndex,r))
{
m_pMenuBar->m_bNoTimer=TRUE;
int j;
j=m_pMenuBar->m_arrDepth;
m_pMenuBar->PostMessage(WM_KEYDOWN,VK_F10,0);
m_pMenuBar->PostMessage(WM_LBUTTONDOWN,MK_LBUTTON,r.left+(r.top<<16));
m_pMenuBar->m_bNoTimer=FALSE;
m_pMenuBar->m_arrDepth=j;
m_pMenuBar->PostMessage(WM_COMMAND,ID_SHOWFULL,NULL);
}
}
else
{
if (m_bTimerSet)
{
m_pMenuBar->EnableGrayedDraw(FALSE);
}
m_pMenuBar->m_pParent->KillTimer(wParam);
}
break;
}
case WM_MENUSELECT:
{
if(!lParam) break;
pMenuTmp=(CMenuEx*)CMenu::FromHandle((HMENU)lParam);
if (!pMenuTmp->IsKindOf(RUNTIME_CLASS(CMenuEx))) break;
m_pMenuBar->OnMenuSelect(pMenuTmp, (UINT)LOWORD(wParam));
break;
}
case WM_DRAWITEM:
{
if (wParam==0)
{
LPDRAWITEMSTRUCT pStruct=(LPDRAWITEMSTRUCT)lParam;
UINT stateex = (((CMenuExData*)(pStruct->itemData))->nFlagsEx);
if(pStruct->itemState&ODS_SELECTED)
{
if ((stateex & MF_LASTARROW) && (!(m_pMenuBar->m_pMenu->CheckIfGrayedDraw())))
{
m_pMenuBar->m_pParent->SetTimer((UINT)this,1000,NULL);//&TimerFunc);
m_bTimerSet=TRUE;
POINT p;
CDC* pDC = CDC::FromHandle(pStruct->hDC);
CWnd *pWnd=pDC->GetWindow();
HWND hwnd=pWnd->m_hWnd;
p.y=pStruct->rcItem.top;
p.x=pStruct->rcItem.left;
ClientToScreen(hwnd,&p);
m_pMenuBar->m_Rect.top=p.y;
m_pMenuBar->m_Rect.left=p.x;
p.y=pStruct->rcItem.bottom;
p.x=pStruct->rcItem.right;
ClientToScreen(hwnd,&p);
m_pMenuBar->m_Rect.bottom=p.y;
m_pMenuBar->m_Rect.right=p.x;
}
else
{
if(m_bTimerSet)
{
m_pMenuBar->m_pParent->KillTimer((UINT)this);
m_bTimerSet=FALSE;
m_pMenuBar->m_Rect.SetRectEmpty();
}
}
}
}
break;
}
case WM_INITMENUPOPUP:
if (!((BOOL)HIWORD(lParam)) &&
m_pMenuBar->m_pMenu->IsMenu(CMenu::FromHandle((HMENU) wParam)))
CMenuEx::UpdateMenu(m_pMenuBar->m_pMenu);
if (!HIWORD(lParam) && m_pMenuBar->m_pWindowMenu &&
(HMENU)wParam == m_pMenuBar->m_pWindowMenu->m_hMenu)
{
if(!wParam) break;
pMenuTmp=(CMenuEx*)CMenu::FromHandle((HMENU)wParam);
if (!pMenuTmp->IsKindOf(RUNTIME_CLASS(CMenuEx))) break;
m_pMenuBar->OnInitMenuPopup(pMenuTmp, LOWORD(lParam), (BOOL)HIWORD(lParam));
}
break;
case WM_NCACTIVATE:
m_pMenuBar->OnFrameNcActivate((BOOL)wParam);
m_pMenuBar->EnableGrayedDraw(FALSE);
break;
case WM_SYSCOLORCHANGE:
case WM_SETTINGCHANGE:
LTRACE(_T("CMenuBar::WM_SETTINGCHANGE\n"));
// It's enough to reinitialize common resources once.
m_pMenuBar->OnSettingChange(wParam, lParam);
break;
case WM_MEASUREITEM:
if(((LPMEASUREITEMSTRUCT) lParam)->CtlType==ODT_MENU && m_pMenuBar->m_pMenu)
{
m_pMenuBar->m_pMenu->MeasureItem((LPMEASUREITEMSTRUCT) lParam);
return TRUE;
}
break;
case WM_MENUCHAR:
if (m_pMenuBar->m_pMenu)
{
pMenuTmp=(CMenuEx*)CMenu::FromHandle((HMENU) lParam);
if (!pMenuTmp->IsKindOf(RUNTIME_CLASS(CMenuEx))) break;
return m_pMenuBar->m_pMenu->FindKeyboardShortcut((TCHAR) LOWORD(wParam),
(UINT) HIWORD(wParam), pMenuTmp);
}
case WM_ACTIVATE:
{
if(m_bTimerSet)
{
m_pMenuBar->m_pParent->KillTimer((UINT)this);
m_bTimerSet=FALSE;
}
m_pMenuBar->EnableGrayedDraw(FALSE);
CMDIFrameEx* pFrame=((CMDIFrameEx*)(m_pMenuBar->m_pParent/*GetParentFrame()*/));
if (!pFrame->IsKindOf(RUNTIME_CLASS(CMDIFrameEx))) break;
CWnd* pWnd=m_pMenuBar->m_pParent;
if (!pWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameEx))) break;
CMDIChildWnd* pClient=(CMDIChildWnd*) pFrame->MDIGetActive();
if (pClient && pClient->IsKindOf(RUNTIME_CLASS(CMDIChildWnd)))
{
CView* pView=pClient->GetActiveView();
if(!pView) break;
CDocument* pDoc=pView->GetDocument();
if(!pDoc)
{
m_pMenuBar->OnSetMenu(pFrame->GetMainMenu(),
pFrame->GetWindowMenuPopup(pFrame->GetMainMenu()));
break;
}
CMultiDocTemplateEx* pTemplate =(CMultiDocTemplateEx*)pDoc->GetDocTemplate();
if (!pTemplate->IsKindOf(RUNTIME_CLASS(CMultiDocTemplateEx))) break;
m_pMenuBar->OnSetMenu(&(pTemplate->m_mnuDocMenu),
pFrame->GetWindowMenuPopup(&(pTemplate->m_mnuDocMenu)));
}
else
{
m_pMenuBar->OnSetMenu(pFrame->GetMainMenu(),
pFrame->GetWindowMenuPopup(pFrame->GetMainMenu()));
break;
}
break;
}
case WM_SETFOCUS:
case WM_NCHITTEST:
{
m_pMenuBar->EnableGrayedDraw(FALSE);
break;
}
}
if (nMsg == CMenuBar::WM_GETMENU)
return (LRESULT)m_pMenuBar->m_pMenu->m_hMenu;
return CSubclassWnd::WindowProc(nMsg, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////
// CMenuItem interface
CMenuItem::CMenuItem()
{
m_fsStyle = 0;
m_fsState = 0;
m_rcItem.SetRectEmpty();
m_sizeHorz = CSize(0, 0);
m_cAccessKey = 0;
}
void CMenuItem::ModifyState(BYTE fsRemove, BYTE fsAdd)
{
m_fsState = (m_fsState & ~fsRemove) | fsAdd;
}
CSize CMenuItem::GetHorizontalSize() const
{
if (m_fsState & MISTATE_HIDDEN)
return CSize(0, 0);
else
return m_sizeHorz;
}
//////////////////////////////////////////////////////////////////////
// CMenuButton class
CMenuButton::CMenuButton(CMenuEx* pMenu, int nIndex)
{
ASSERT(nIndex >= 0);
m_fsStyle |= (MISTYLE_TRACKABLE | MISTYLE_WRAPPABLE);
InitButtonStringAndSubMenuHandle(pMenu, nIndex);
InitHorizontalButtonSize();
InitAccessKeyAndVerticalLinePoint();
}
void CMenuButton::InitButtonStringAndSubMenuHandle(CMenuEx* pMenu, int nIndex)
{
pMenu->GetMenuText(nIndex,m_strBtn);
m_pSubMenu = (CMenuEx*)pMenu->GetSubMenu(nIndex);
if (!m_pSubMenu) {
m_nID = pMenu->GetMenuItemID(nIndex);
ASSERT(m_nID != -1);
}
else {
m_nID = -1;
}
}
void CMenuButton::InitHorizontalButtonSize()
{
// get menu button Text size
ASSERT(m_strBtn.IsEmpty() == FALSE);
m_sizeHorz.cx = _CalcTextWidth(m_strBtn) + CXTEXTMARGIN*2;
m_sizeHorz.cy = _cyHorzFont + _cyTextMargin*2;
}
voi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -