📄 menubar.cpp
字号:
UpdateBar();
}
CControlBar::OnMouseMove(nFlags, point);
}
LRESULT CMenuBar::OnSetMenuNull(WPARAM wParam, LPARAM)
{
HWND hWnd = (HWND)wParam;
ASSERT(::IsWindow(hWnd));
::SetMenu(hWnd, NULL);
return 0;
}
LRESULT CMenuBar::OnSettingChange(WPARAM wParam, LPARAM lParam)
{
// reinitialize fonts etc
if (!_InitCommonResources(TRUE)) {
TRACE(_T("Failed to create bar resource\n"));
return FALSE;
}
VERIFY(InitItems());
CFrameWnd* pFrame = GetParentFrame();
ASSERT_VALID(pFrame);
pFrame->RecalcLayout();
return 0;
}
void CMenuBar::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO:
// LTRACE(_T("CMenuBar::OnLButtonUp\n"));
if (m_pMenuControl && m_pMenuControl->OnMouseMsg(WM_LBUTTONUP, nFlags, point)) {
CControlBar::OnLButtonUp(nFlags, point);
return;
}
CControlBar::OnLButtonUp(nFlags, point);
}
void CMenuBar::CheckActiveChildWndMaximized()
{
//LTRACE(_T("CMenuBar::CheckActiveChildWndMaximized\n"));
ASSERT(m_pMenuControl);
ASSERT(m_pMenuIcon);
BOOL bMaximized = FALSE;
GetActiveChildWnd(bMaximized);
if (m_bMDIMaximized != bMaximized) {
LTRACE(_T("CMenuBar::CheckActiveChildWndMaximized---state changed, refreshing\n"));
m_bMDIMaximized = bMaximized;
m_pMenuControl->OnActivateChildWnd();
m_pMenuIcon->OnActivateChildWnd();
RefreshBar();
}
}
void CMenuBar::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
LTRACE(_T("CMenuBar::OnInitMenuPopup\n"));
CMenu menu;
menu.Attach((HMENU)m_hWindowMenu);
// scan for first window command
int n = menu.GetMenuItemCount();
BOOL bAddSeperator = TRUE;
for (int iPos=0; iPos<n; iPos++) {
if (menu.GetMenuItemID(iPos) >= AFX_IDM_FIRST_MDICHILD) {
bAddSeperator = FALSE;
break;
}
}
// iPos is either first window item, or end if none found.
// delete everything after.
while (iPos < (int)menu.GetMenuItemCount())
menu.RemoveMenu(iPos, MF_BYPOSITION);
// get active window so I can check its menu item
ASSERT(m_hWndMDIClient);
HWND hwndActive = (HWND)::SendMessage(m_hWndMDIClient,
WM_MDIGETACTIVE, 0, NULL);
// append window names in the form "# title"
// *****fixed by VORGA, thanks!*****
int iWin;
int nID = AFX_IDM_FIRST_MDICHILD;
CString sWinName, sMenuItem;
HWND hwnd;
for (iWin = 1; iWin <= 10; iWin++, nID++)
{
hwnd = ::GetDlgItem(m_hWndMDIClient, nID);
if (hwnd == NULL)
break;
if (bAddSeperator)
{
menu.InsertMenu(iPos++, MF_BYPOSITION | MF_SEPARATOR);
bAddSeperator = FALSE;
}
if (iWin < 10)
{
CWnd::FromHandle(hwnd)->GetWindowText(sWinName);
sMenuItem.Format(_T("&%d %s"), iWin, (LPCTSTR)sWinName);
menu.InsertMenu(iPos, MF_BYPOSITION, nID, sMenuItem);
if (hwnd == hwndActive)
menu.CheckMenuItem(iPos, MF_BYPOSITION | MF_CHECKED);
}
else
{
menu.InsertMenu(iPos, MF_BYPOSITION, nID, _szMoreWindows);
}
iPos++;
}
menu.Detach();
}
void CMenuBar::OnSetMenu(HMENU hNewMenu, HMENU hWindowMenu)
{
ASSERT(m_pMenuIcon && m_pMenuControl);
// We can get active MDI child window on this message!
BOOL bMax = FALSE;
HWND hWndChild = GetActiveChildWnd(bMax);
if (!m_hWndActiveChild || m_hWndActiveChild != hWndChild) {// an active child window changed
LTRACE(_T("CMenuBar::OnSetMenu---an active child window changed\n"));
m_hWndActiveChild = hWndChild;
// tell MenuIcon child window has been changed
m_pMenuIcon->OnActivateChildWnd();
}
if (!m_hMenu || m_hMenu != hNewMenu) { // menu changed
LTRACE(_T("CMenuBar::OnSetMenu---menu changed\n"));
LoadMenu(hNewMenu, hWindowMenu); // set menubar menu
GetOwner()->SetMenu(NULL); // clear frame menu
}
}
void CMenuBar::OnNcPaint()
{
EraseNonClientEx();
}
UINT CMenuBar::OnNcHitTest(CPoint point)
{
// make nonclient area clickable
return HTCLIENT;
}
void CMenuBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
// calculate border space (will add to top/bottom, subtract from right/bottom)
CRect rect; rect.SetRectEmpty();
BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
_CalcInsideRect(rect, bHorz);
// ASSERT(_afxComCtlVersion != -1);
// ASSERT(_afxComCtlVersion >= VERSION_IE4 || rect.top >= 2);
// adjust non-client area for border space
lpncsp->rgrc[0].left += rect.left;
lpncsp->rgrc[0].top += rect.top;
// previous versions of COMCTL32.DLL had a built-in 2 pixel border
// if (_afxComCtlVersion < VERSION_IE4)
// lpncsp->rgrc[0].top -= 2;
lpncsp->rgrc[0].right += rect.right;
lpncsp->rgrc[0].bottom += rect.bottom;
}
void CMenuBar::OnDestroy()
{
CControlBar::OnDestroy();
// TODO:
DeleteItems();
if (m_nIDEvent)
KillTimer(m_nIDEvent);
// for SDI application
if (m_bMDIApp == FALSE && m_hMenu != NULL)
::FreeResource(m_hMenu);
}
void CMenuBar::OnTimer(UINT nIDEvent)
{
// TODO: 偙偺埵抲偵儊僢僙乕僕 僴儞僪儔梡偺僐乕僪傪捛壛偡傞偐傑偨偼僨僼僅儖僩偺張棟傪屇傃弌偟偰偔偩偝偄
if (m_nTrackingState == buttonmouse) {
CPoint pt; ::GetCursorPos(&pt);
CRect rect;
GetWindowRect(&rect);
if (!rect.PtInRect(pt)) {
UpdateBar();
if (m_nIDEvent) {
KillTimer(m_nIDEvent);
m_nIDEvent = NULL;
}
}
}
CControlBar::OnTimer(nIDEvent);
}
HWND CMenuBar::GetActiveChildWnd(BOOL& bMaximized)
{
if (!m_hWndMDIClient)
return NULL;
BOOL bMax = FALSE;
HWND hWnd = (HWND)::SendMessage(m_hWndMDIClient,
WM_MDIGETACTIVE, 0, (LPARAM)&bMax);
bMaximized = bMax;
return hWnd;
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar system hook
void CMenuBar::OnMenuSelect(HMENU hMenu, UINT nIndex)
{
// LTRACE(_T("CMenuBar::OnMenuSelect\n"));
if (m_nTrackingState == popup) {
m_bProcessRightArrow = (::GetSubMenu(hMenu, nIndex) == NULL);
HMENU hSubMenu = ::GetSubMenu(hMenu, m_nCurIndex);
if (hSubMenu == NULL)
return;
m_bProcessLeftArrow = (hMenu == hSubMenu);
}
}
void CMenuBar::OnFrameNcActivate(BOOL bActive)
{
CFrameWnd* pFrame = GetTopLevelFrame();
ASSERT_VALID(pFrame);
if (pFrame->m_nFlags & WF_STAYACTIVE)
bActive = TRUE;
if (!pFrame->IsWindowEnabled())
bActive = FALSE;
if (bActive == m_bFrameActive)
return;
if (!bActive) {
for (int i = 0; i < GetItemCount(); ++i) {
m_arrItem[i]->ModifyState(0, MISTATE_INACTIVE);
}
}
else {
for (int i = 0; i < GetItemCount(); ++i) {
m_arrItem[i]->ModifyState(MISTATE_INACTIVE, 0);
}
}
m_bFrameActive = bActive;
// InvalidateRect(NULL); is better, but too late
// while clicking the application title bar (like IE5)
// so we have to redraw now!
CClientDC dc(this);
DoPaint(&dc);
}
LRESULT CALLBACK CMenuBar::MenuInputFilter(int code, WPARAM wParam, LPARAM lParam)
{
return (
code == MSGF_MENU &&
g_pMenuBar &&
g_pMenuBar->OnMenuInput( *((MSG*)lParam) )
) ? TRUE : CallNextHookEx(g_hMsgHook, code, wParam, lParam);
}
void CMenuBar::TrackPopup(int nIndex)
{
ASSERT_VALID(this);
m_nCurIndex = nIndex;
m_bLoop = TRUE;
while (m_bLoop == TRUE) {
UpdateWindow(); // force to repaint when button hidden by other window
UpdateBar(popup, m_nCurIndex);
// install hook
ASSERT(g_pMenuBar == NULL);
g_pMenuBar = this;
ASSERT(g_hMsgHook == NULL);
m_bLoop = FALSE;
g_hMsgHook = ::SetWindowsHookEx(WH_MSGFILTER,
MenuInputFilter, NULL, AfxGetApp()->m_nThreadID);// m_bLoop may become TRUE
// popup!!
m_nTrackingState = popup;
_nPrevIndexForCmd = m_nCurIndex;
m_arrItem[m_nCurIndex]->TrackPopup(this, GetTopLevelParent());
// uninstall hook
::UnhookWindowsHookEx(g_hMsgHook);
g_hMsgHook = NULL;
g_pMenuBar = NULL;
}
UpdateBar();
}
BOOL CMenuBar::OnMenuInput(MSG& m)
{
ASSERT_VALID(this);
int nMsg = m.message;
CPoint pt = m.lParam;
ScreenToClient(&pt);
switch (nMsg) {
case WM_MOUSEMOVE:
if (pt != m_ptMouse) {
int nIndex = HitTestOnTrack(pt);
if (IsValidIndex(nIndex) && nIndex != m_nCurIndex) {
// defferent button clicked
AfxGetMainWnd()->PostMessage(WM_CANCELMODE); // destroy popupped menu
UpdateBar(); // clean up
m_nCurIndex = nIndex;
m_bLoop = TRUE; // continue loop
}
m_ptMouse = pt;
}
break;
case WM_LBUTTONDOWN:
if (HitTestOnTrack(pt) != -1 && HitTestOnTrack(pt) == m_nCurIndex) {
// same button clicked
AfxGetMainWnd()->PostMessage(WM_CANCELMODE); // destroy popupped menu
UpdateBar(button, m_nCurIndex);
m_bLoop = FALSE; // out of loop
return TRUE; // eat it!
}
break;
case WM_KEYDOWN: {
TCHAR vKey = m.wParam;
if (m_dwStyle & CBRS_ORIENT_VERT) { // if vertical
break; // do nothing
}
if ((vKey == VK_LEFT && m_bProcessLeftArrow) ||
(vKey == VK_RIGHT && m_bProcessRightArrow)) {
// no submenu
int nNewIndex = GetNextOrPrevButton(m_nCurIndex, vKey==VK_LEFT);
AfxGetMainWnd()->PostMessage(WM_CANCELMODE); // destroy popupped menu
UpdateBar();
m_nCurIndex = nNewIndex;
m_bLoop = TRUE; // continue loop
return TRUE; // eat it!
}
}
break;
case WM_SYSKEYDOWN:
// LTRACE(_T(" m_bIgnore = TRUE\n"));
m_bIgnoreAlt = TRUE; // next SysKeyUp will be ignored
break;
}
return FALSE; // pass along...
}
BOOL CMenuBar::TranslateFrameMessage(MSG* pMsg)
{
ASSERT_VALID(this);
ASSERT(pMsg);
/* if (_GetCmdSentWnd(NULL)->GetSafeHwnd() != GetTopLevelParent()->GetSafeHwnd()) {
if (m_nTrackingState == popup) {
LTRACE(_T("CMenuBar::TranslateMessage - SendMessage\n"));
pMsg->hwnd = _GetCmdSentWnd(NULL)->GetSafeHwnd();
_GetCmdSentWnd(NULL)->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
return TRUE;
}
}
*/
UINT nMsg = pMsg->message;
if (WM_LBUTTONDOWN <= nMsg && nMsg <= WM_MOUSELAST) {
if (pMsg->hwnd != m_hWnd && m_nTrackingState > 0) {
// clicked outside
UpdateBar();
}
}
else if (nMsg == WM_SYSKEYDOWN || nMsg == WM_SYSKEYUP || nMsg == WM_KEYDOWN) {
BOOL bAlt = HIWORD(pMsg->lParam) & KF_ALTDOWN; // Alt key presed?
TCHAR vkey = pMsg->wParam; // + X key
if (vkey == VK_MENU ||
(vkey == VK_F10 && !((GetKeyState(VK_SHIFT) & 0x80000000) ||
(GetKeyState(VK_CONTROL) & 0x80000000) || bAlt))) {
// only alt key pressed
if (nMsg == WM_SYSKEYUP) {
switch (m_nTrackingState) {
case none:
if (m_bIgnoreAlt == TRUE) {
// LTRACE(_T(" ignore ALT key up\n"));
m_bIgnoreAlt = FALSE;
break;
}
if (m_bMDIApp) {
UpdateBar(button, GetNextOrPrevButton(0, FALSE));
}
else {
UpdateBar(button, 0);
}
break;
case button:
UpdateBar();
break;
case buttonmouse:
break; // do nothing
}
}
return TRUE;
}
else if ((nMsg == WM_SYSKEYDOWN || nMsg == WM_KEYDOWN)) {
if (m_nTrackingState == button) {
if (m_dwStyle & CBRS_ORIENT_HORZ) { // if horizontal
switch (vkey) {
case VK_LEFT:
case VK_RIGHT: {
int nNewIndex = GetNextOrPrevButton(m_nCurIndex, vkey == VK_LEFT);
UpdateBar(button, nNewIndex);
return TRUE;
}
case VK_SPACE:
case VK_UP:
case VK_DOWN:
TrackPopup(m_nCurIndex);
return TRUE;
case VK_ESCAPE:
UpdateBar();
return TRUE;
}
}
else { // if vertical
switch (vkey) {
case VK_UP:
case VK_DOWN:{
int nNewIndex = GetNextOrPrevButton(m_nCurIndex, vkey == VK_UP);
UpdateBar(button, nNewIndex);
return TRUE;
}
case VK_SPACE:
case VK_RIGHT:
case VK_LEFT:
TrackPopup(m_nCurIndex);
return TRUE;
case VK_ESCAPE:
UpdateBar();
return TRUE;
}
}
}
// Alt + X pressed
if ((bAlt || m_nTrackingState == button) && _istalnum(vkey)) {
int nIndex;
if (MapAccessKey(vkey, nIndex) == TRUE) {
UpdateBar();
TrackPopup(nIndex);
return TRUE; // eat it!
}
else if (m_nTrackingState==button && !bAlt) {
// MessageBeep(0); // if you want
return TRUE;
}
}
if (m_nTrackingState > 0) { // unknown key
if (m_nTrackingState != buttonmouse) { // if tracked with mouse, don't update bar
UpdateBar();
}
}
}
}
return FALSE; // pass along...
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -