⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menubar.cpp

📁 一个很好的LFP规约调试器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		m_bIgnoreAlt = TRUE;					// next SysKeyUp will be ignored
		break;
	}

	return FALSE;	// pass along...
}

BOOL CMenuBar::TranslateFrameMessage(MSG* pMsg)
{
	ASSERT_VALID(this);
	ASSERT(pMsg);

	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("    ignore ALT key up\n");
						m_bIgnoreAlt = FALSE;
						break;
					}

					UpdateBar(button, GetNextOrPrevButton(0, FALSE));

					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) && isalnum(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...
}

BOOL CMenuBar::MapAccessKey(TCHAR cAccessKey, int& nIndex)
{
	for (int i = 0; i < GetItemCount(); ++i) {
		TCHAR cKey;
		if (m_arrItem[i]->GetAccessKey(cKey) == TRUE &&
			cKey == cAccessKey) {
			nIndex = i;
			return TRUE;
		}
	}
	return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CMenuBar layout

// calculate only layout from m_bWrapped
void CMenuBar::CalcFloatingLayout()
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));

	int xStart = CXGAP;

	if (!IsFloating()) {
		xStart += CXGRIPPER;
	}

	int xOffset = xStart;
	int yOffset = CYGAP;

	for (int i = 0; i < GetItemCount(); ++i) {
		CMenuItem* pItem = m_arrItem[i];
		if (pItem->IsValid()) {
			CPoint ptItem(xOffset, yOffset);
			pItem->Layout(ptItem, TRUE);	// layout by itself!
			if (pItem->m_bWrapped == TRUE) {
				xOffset = xStart;			// reset xOffset
				yOffset += pItem->m_sizeHorz.cy;
			}
			else
				xOffset += pItem->m_sizeHorz.cx;
		}
	}
}

// calulate ordinary layout and size without m_bWrapped 
CSize CMenuBar::CalcLayout(DWORD dwMode, int nLength)
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));
	if (dwMode & LM_HORZDOCK)
		ASSERT(dwMode & LM_HORZ);
	CSize sizeResult(0, 0);

	if (!(dwMode & LM_HORZ)) 	{				// if vertical
		int yOffset = CXGAP;
		if (!IsFloating())
			yOffset += CXGRIPPER;

		for (int i = 0; i < GetItemCount(); ++i) {
			CMenuItem* pItem = m_arrItem[i];
			if (pItem->IsValid()) {
				CPoint	ptItem(CYGAPVERT, yOffset);
				pItem->Layout(ptItem, FALSE);	// layout by itself
				yOffset += pItem->m_rcItem.Height();
			}
		}
		int cxBar = max(::GetSystemMetrics(SM_CXSMICON), cyMenuButton + (CYGAPVERT)*2);
		sizeResult =  CSize(cxBar, yOffset+CXGAP);
	}
	else {										// if horizontal
		int xOffset = CXGAP;
		if (!IsFloating())
			xOffset += CXGRIPPER;

		for (int i = 0; i < GetItemCount(); ++i) {
			CMenuItem* pItem = m_arrItem[i];
			if (pItem->IsValid()) {
				CPoint ptItem(xOffset, CYGAP);
				pItem->Layout(ptItem, TRUE);	// layout by itself
				xOffset += pItem->m_rcItem.Width();
			}
		}
		int cyBar = max(::GetSystemMetrics(SM_CYSMICON), cyMenuButton + CYGAP*2);
		sizeResult = CSize(xOffset+CXGAP, cyBar);
	}

	return sizeResult;
}

// in fact, it's never called
CSize CMenuBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
//	LTRACE("CMenuBar::CalcFixedLayout\n");

	DWORD dwMode = bStretch ? LM_STRETCH : 0;
	dwMode |= bHorz ? LM_HORZ : 0;

	return CalcLayout(dwMode);
}

CSize CMenuBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
	LTRACE("CMenuBar::CalcDynamicLayout\n");

	// Who can understand what "dwMode" means?
	// 
	// If you want it be pricisely same as DevStudio style,
	// I think you have to create a "CDockContext" derived class.
	// This is the reason why everyone think "CControlBar class" junk ? 

	ASSERT_VALID(this);
	ASSERT_VALID(m_pDockSite);
	ASSERT_VALID(m_pDockBar);

	if (m_hMenu == NULL)	// if have no menu yet, just return
		return CSize(0, 0);

	if (IsFloating()) {
		CFrameWnd* pFrame = GetParentFrame();
		ASSERT_VALID(pFrame);
		CMenu* pSysMenu = pFrame->GetSystemMenu(FALSE);
		ASSERT_VALID(pSysMenu);
		pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_DISABLED);
	}

	if (dwMode & LM_HORZ) {						// horizontal
	//	LTRACE("    horizontal\n");
		if (dwMode & LM_HORZDOCK) {
			if (IsFloating() || (m_dwStyle & CBRS_ORIENT_VERT)) {	// if Floating->Docking, return min size
	//			LTRACE("    return min size\n");
				return CalcLayout(dwMode);
			}
			else {
				if (m_pDockContext->m_pDC) {	// now dragging
					// return DockBar size
					//LTRACE("    now dragging, so calc with DockBar\n");
					CSize size = CalcSize(GetItemCount());//CalcLayout(dwMode);
					CRect rcFrame;
					m_pDockBar->GetWindowRect(rcFrame);
					CRect rcBar;
					GetWindowRect(rcBar);
					rcBar.right = rcFrame.right;
					return CSize(rcBar.Width() + cxBorder2, size.cy);
				}
				else {
					//LTRACE("    no draggin calc bigger size\n");
					CRect rcFrame;
					m_pDockSite->GetWindowRect(rcFrame);
					SizeMenuBar(GetItemCount(), rcFrame.Width() - cxBorder2*2, FALSE);
					CalcFloatingLayout();
					CSize size1 = CalcSize(GetItemCount());
					return CSize(rcFrame.Width(), size1.cy);
				}
			}
		}
		else if (dwMode & LM_MRUWIDTH) {		// floating size
			//LTRACE("    return floating size\n");
			SizeMenuBar(GetItemCount(), m_nMRUWidth, FALSE);	// load floating Bar Width! 
			CalcFloatingLayout();
			return CalcSize(GetItemCount());
		}
		else if (dwMode & LM_COMMIT) {
			//LTRACE("    commit, just calc: %d\n", nLength);
			m_nMRUWidth = nLength;								// save floating Bar Width!!! (used when SaveBarState)
			CalcFloatingLayout();
			return CSize(0, 0);									// MFC does'nt use this Size
		}
		else if (dwMode & LM_LENGTHY) {
			//LTRACE("    nLength is height : %d\n", nLength);
			SizeMenuBar(GetItemCount(), nLength, TRUE);
			return CalcSize(GetItemCount());
		}
		else {
			//LTRACE("    nLength is width  : %d\n", nLength);
			SizeMenuBar(GetItemCount(), nLength, FALSE);
			return CalcSize(GetItemCount());
		}
		ASSERT(TRUE);
	}
	else {														// vertical
		InvalidateRect(NULL);									// force to repaint!!!
		//LTRACE("    vertical\n");
		if (IsFloating() || (m_dwStyle & CBRS_ORIENT_HORZ)) {	// if Floating->Docking, return min size
			//LTRACE("    return min size\n");
			return CalcLayout(dwMode);
		}
		else {									// return large size
			if (m_pDockContext->m_pDC) {		// CDockContext::m_bDragging is not helpful :(
				//LTRACE("    now dragging, so calc with DockBar\n");
				CSize size = CalcLayout(dwMode);
				CRect rcFrame;
				m_pDockBar->GetWindowRect(rcFrame);
				CRect rcBar;
				GetWindowRect(rcBar);
				rcBar.bottom = rcFrame.bottom;
				return CSize(size.cx, rcBar.Height());
			}
			else {
				//LTRACE("    no dragging, return biggest size\n");
				
				CSize size = CalcLayout(dwMode);
				CRect rcFrame;
				m_pDockSite->GetWindowRect(rcFrame);
				CRect rcBar;
				GetWindowRect(rcBar);
				rcBar.bottom = rcFrame.bottom;
				return CSize(size.cx, rcFrame.Height());
			}
		}
	}

	ASSERT(TRUE);								// never come here
	return CalcLayout(dwMode, nLength);
}

void CMenuBar::DrawGripper(CDC* pDC)
{
	if( (m_dwStyle & CBRS_FLOATING) || m_dwDockStyle == 0 )
		return;

	CRect rcGrip;
	GetClientRect(&rcGrip);

	if(m_dwStyle & CBRS_ORIENT_HORZ) {
		// gripper at left
		rcGrip.DeflateRect(4, 3);
		rcGrip.right = rcGrip.left + 3;
		pDC->DrawEdge(rcGrip, BDR_RAISEDINNER, BF_RECT);
		rcGrip.OffsetRect(4, 0);
        pDC->DrawEdge(rcGrip,	BDR_RAISEDINNER, BF_RECT);
	}
	else {
		// gripper at top
		rcGrip.DeflateRect(3, 4);
		rcGrip.bottom = rcGrip.top + 3;
		pDC->DrawEdge(rcGrip, BDR_RAISEDINNER, BF_RECT);
		rcGrip.OffsetRect(0, 4);
		pDC->DrawEdge(rcGrip, BDR_RAISEDINNER, BF_RECT);
	}
}

#define CX_BORDER   1
#define CY_BORDER   1

void CMenuBar::DrawBorder(CDC* pDC)
{
	if( (m_dwStyle & CBRS_FLOATING) || m_dwDockStyle == 0 )
		return;

	CRect rect;
	GetClientRect(rect);

	DWORD dwStyle = m_dwStyle;
	if (!(dwStyle & CBRS_BORDER_ANY))
		return;

	CRect rect3 = rect;
	if (m_dwStyle & CBRS_ORIENT_HORZ) {
		rect3.left += cxBorder2;//rect.DeflateRect(2, 0);
		pDC->DrawEdge(rect3, BDR_RAISEDINNER,  BF_LEFT);	
	}
	else {
		rect3.top += cyBorder2;//rect.DeflateRect(0, 2);
		pDC->DrawEdge(rect3, BDR_RAISEDINNER,  BF_TOP);	
	}

	// prepare for dark lines
	ASSERT(rect.top == 0 && rect.left == 0);
	CRect rect1, rect2;
	rect1 = rect;
	rect2 = rect;
	COLORREF clr = ::GetSysColor(COLOR_BTNSHADOW);//afxData.bWin4 ? afxData.clrBtnShadow : afxData.clrWindowFrame;

	// draw dark line one pixel back/up
	if (dwStyle & CBRS_BORDER_3D)
	{
		rect1.right -= CX_BORDER;
		rect1.bottom -= CY_BORDER;
	}
	if (dwStyle & CBRS_BORDER_TOP)
		rect2.top += CY_BORDER;//cyBorder2;
	if (dwStyle & CBRS_BORDER_BOTTOM)
		rect2.bottom -= CY_BORDER;

	if (dwStyle & CBRS_BORDER_LEFT)
		rect2.left += CX_BORDER;

	if (dwStyle & CBRS_BORDER_RIGHT)
		rect2.right -= CX_BORDER;

	if (dwStyle & CBRS_BORDER_3D)
	{
		// draw left and top
		if (dwStyle & CBRS_BORDER_LEFT)
			pDC->DrawEdge(rect2, BDR_RAISEDINNER, BF_LEFT);//pDC->FillSolidRect(1, rect2.top, CX_BORDER, rect2.Height(), clr);
		if (dwStyle & CBRS_BORDER_TOP)
			pDC->DrawEdge(rect2, BDR_RAISEDINNER, BF_TOP);//pDC->FillSolidRect(0, 1, rect.right, CY_BORDER, clr);

		// draw right and bottom
		if (dwStyle & CBRS_BORDER_RIGHT)
			pDC->DrawEdge(rect2, BDR_RAISEDINNER, BF_RIGHT);//pDC->FillSolidRect(rect.right, rect2.top, -CX_BORDER, rect2.Height(), clr);
		if (dwStyle & CBRS_BORDER_BOTTOM)
			pDC->DrawEdge(rect2, BDR_RAISEDINNER, BF_BOTTOM);//pDC->FillSolidRect(0, rect.bottom, rect.right, -CY_BORDER, clr);
	}
	
}

/////////////////////////////////////////////////////////////////////////////
// CMenuBarFrameHook implementation

CMenuBarFrameHook::CMenuBarFrameHook()
{
	m_pMenuBar = NULL;
}

BOOL CMenuBarFrameHook::Install(CMenuBar* pMenuBar, HWND hWndToHook)
{
	ASSERT_VALID(pMenuBar);
	ASSERT(m_pMenuBar == NULL);
	m_pMenuBar = pMenuBar;
	return HookWindow(hWndToHook);//CWnd::FromHandlePermanent(hWndToHook));
}

CMenuBarFrameHook::~CMenuBarFrameHook()
{
}

LRESULT CMenuBarFrameHook::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	ASSERT_VALID(m_pMenuBar);

	switch (nMsg) {
	case WM_MENUSELECT:
		m_pMenuBar->OnMenuSelect((HMENU)lParam, (UINT)LOWORD(wParam));
		break;

	// The following messages are trapped for the MDI client window
	case WM_INITMENUPOPUP:
		LTRACE("CMenuBar::WM_INITMENUPOPUP\n");
		if (!HIWORD(lParam) && (HMENU)wParam == m_pMenuBar->m_hWindowMenu)
			m_pMenuBar->OnInitMenuPopup();
		break;


	case WM_MDISETMENU:			// only sent to MDI client window
		// Setting new frame/window menu: bypass MDI. wParam is new menu.
		if (wParam) {
			LTRACE("CMenuBar::WM_MDISETMENU 0x%04x\n", wParam);
//			HMENU hNewMenu = (HMENU)wParam;
			m_pMenuBar->OnSetMenu((HMENU)wParam, (HMENU)lParam);			
		}
		return 0;

	case WM_MDIREFRESHMENU:		// only sent to MDI client window
		// Normally, would call DrawMenuBar, but I have the menu, so eat it.
//		LTRACE("CMenuBar::WM_MDIREFRESHMENU\n");
		return 0;

	case WM_PAINT:
		// 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->OnPaintMDIClient();//CheckMinMaxState();
		break;
	}

	return CSubclassWnd::WindowProc(nMsg, wParam, lParam);
}

void CMenuBar::OnLButtonUp(UINT nFlags, CPoint point) 
{
	//LTRACE("CMenuBar::OnLButtonUp\n");
	// TODO: 
	ASSERT(m_pMenuControl);
	if (m_pMenuControl->OnMouseMsg(WM_LBUTTONUP, nFlags, point)) {
		CControlBar::OnLButtonUp(nFlags, point);
		return;
	}	

	int nIndex = HitTestOnTrack(point);
/*
	if (IsValidIndex(nIndex) && m_bDown == TRUE) {
		HMENU hSubMenu = ::GetSubMenu(m_hMenu, nIndex);
		if (hSubMenu == NULL) {
			UINT nID = ::GetMenuItemID(m_hMenu, nIndex);
			ASSERT(nID != -1);
			GetOwner()->SendMessage(WM_COMMAND, (WPARAM)nID, (LPARAM)GetSafeHwnd());

			UpdateBar();
		}
	}
*/
	CControlBar::OnLButtonUp(nFlags, point);
}

void CMenuBar::DoPaint(CDC* pDC)
{
	//LTRACE("CMenuBar::DoPaint\n");
	CRect rect;
	GetClientRect(rect);

	// draw buttons
	for (int i = 0; i < m_arrItem.GetSize(); ++i) {
		CMenuItem* pItem = m_arrItem[i];
		if (pItem->IsValid())
			m_arrItem[i]->Update(pDC);
	}

	// draw decorations
	DrawGripper(pDC);
	DrawBorder(pDC);

	// draw captions
	if (m_pMenuControl) {
		CRect rcDockBar;
		m_pDockBar->GetClientRect(rcDockBar);
		if (m_dwStyle & CBRS_ORIENT_HORZ) {
			m_pMenuControl->DelayLayoutAndDraw(pDC, CSize(rcDockBar.Width() + cxBorder2, rect.Height()));
		}
		else {
			m_pMenuControl->DelayLayoutAndDraw(pDC, CSize(rect.Width(), rcDockBar.Height()));
		}
	}
}

void CMenuBar::_KillTimer()
{
	if (m_nIDEvent) {
		KillTimer(m_nIDEvent);
		m_nIDEvent = NULL;
	}
}


int getPrevValidIndex(int nIndex)
{
	--nIndex;
	return nIndex;
}

// set only m_bWrapped by nWidth
int CMenuBar::WrapMenuBar(int nCount, int nWidth)
{
//	LTRACE("CMenuBar::WrapMenuBar\n");
	int nResult = 0;
	int xStart = CXGAP;
	if (!IsFloating() && !m_pDockContext->m_pDC)	// if not floating and ****not dragging!!!****
		xStart += CXGRIPPER;
	
	int x = xStart;
	
	for (int i = 0; i < nCount; ++i) {
		CMenuItem* pItem = m_arrItem[i];
		if (pItem->IsValid()) {

			if (i+1 == nCount)
				return ++nResult;
			
			if (x + pItem->m_sizeHorz.cx + CXGAP> nWidth) {// itself is over
				if (pItem->CanWrap()) {
					pItem->m_bWrapped = TRUE;
					++nResult;
					x = xStart;
				}
			}
			else if (x + pItem->m_sizeHorz.cx + m_arrItem[i+1]->m_sizeHorz.cx + CXGAP > nWidth) {
				if (pItem->CanWrap()) {
					pItem->m_bWrapped = TRUE;
					++nResult;
					x = xStart;
				}
			}
			else {
				pItem->m_bWrapped = FALSE;
				x += pItem->m_sizeHorz.cx;
			}
		}
	}
/*			//another algorithm

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -