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

📄 menubar.cpp

📁 在编写图形程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:

BOOL CMenuBar::MapAccessKey(TCHAR cAccessKey, int& nIndex)
{
	for (int i = 0; i < GetItemCount(); ++i) {
		// fixing point
		TCHAR cKey = m_arrItem[i]->GetAccessKey();
		if (toupper(cKey)/*_totupper(cKey)*/ == cAccessKey) {// *****fixed by andi, thanx!*****
			nIndex = i;
			return TRUE;
		}
	}
	return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CMenuBar layout
int CMenuBar::GetClipBoxLength(BOOL bHorz)
{
	CFrameWnd* pFrame = GetTopLevelFrame(); ASSERT_VALID(pFrame);
	CRect rcFrame; pFrame->GetWindowRect(rcFrame);

	CWnd* pParent = GetParent(); ASSERT_VALID(pParent);
	CRect rcParent; pParent->GetWindowRect(rcParent);

	const int cxFrameBorder = ::GetSystemMetrics(SM_CXFRAME);
	int cxNonClient = cxFrameBorder*2 + m_cxLeftBorder + m_cxRightBorder;
	if (m_dwExStyle & CBRS_GRIPPER)
		cxNonClient += CX_GRIPPER_ALL;

	if (m_dwStyle & CBRS_SIZE_DYNAMIC) {
		if (bHorz) {
			return rcFrame.Width() - cxNonClient;
		}
		else {
			int nResult = rcParent.Height();
			// I don't know the reason of the following code...
			nResult -= m_cxRightBorder + m_cxLeftBorder + cyBorder2*2;	
			if (m_dwExStyle & CBRS_GRIPPER)
				nResult -= CY_GRIPPER_ALL;

			return nResult;
		}
	}
	else {
		CRect rect; GetClientRect(rect);
		if (bHorz) {
			return rect.Width();
		}
		else {
			return rect.Height();
		}
	}
}

CSize CMenuBar::CalcLayout(DWORD dwMode, int nLength)
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));
	if (dwMode & LM_HORZDOCK)
		ASSERT(dwMode & LM_HORZ);

	// make SC_CLOSE button disable
	if (m_dwStyle & CBRS_FLOATING) {
		CFrameWnd* pMiniFrame = GetParentFrame(); ASSERT_KINDOF(CMiniFrameWnd, pMiniFrame);
//		Don't do this, cause right click menu turns unavairable
//		pMiniFrame->ModifyStyle(WS_SYSMENU, 0);
		CMenu* pSysMenu = pMiniFrame->GetSystemMenu(FALSE);	ASSERT_VALID(pSysMenu);
		pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
	}

	int nCount = GetItemCount();
	CSize sizeResult(0, 0);

	if (nCount > 0)
	{
		if (!(m_dwStyle & CBRS_SIZE_FIXED))
		{
			BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;

			if (bDynamic && (dwMode & LM_MRUWIDTH))
			{
				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_MRUWIDTH\n"));
				SizeMenuBar(m_nMRUWidth);
				CalcItemLayout(nCount);// added

				sizeResult = CalcSize(nCount);
			}
			else if (bDynamic && (dwMode & LM_HORZDOCK))
			{
				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_HORZDOCK\n"));
				if (IsFloating() || (m_dwStyle & CBRS_ORIENT_VERT)) {
					// I can't synchronize horz size on dragging with size on dock bar
					// as VC++ developer can't.
					SizeMenuBar(32767);
				}
				else {
					// Menu Button wrapped by frame width
					SizeMenuBar(GetClipBoxLength(TRUE));
				}

				CalcItemLayout(nCount);// added
				
				sizeResult = CalcSize(nCount);
				if (!IsFloating() && !(m_dwStyle & CBRS_ORIENT_VERT)) {
					if (m_pDockContext->m_pDC) {// while dragging (m_pDockContext->m_bDragging is helpless)
						sizeResult.cx = GetClipBoxLength(TRUE);
					}
				}
			}
			else if (bDynamic && (dwMode & LM_VERTDOCK))
			{
				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_VERTDOCK\n"));
				//SizeMenuBar(0);
				CalcItemLayout(nCount, TRUE);// added

				sizeResult = CalcVertDockSize(nCount);
				if (!IsFloating() && !(m_dwStyle & CBRS_ORIENT_HORZ)) {
					if (m_pDockContext->m_pDC) {// while dragging
						sizeResult.cy = GetClipBoxLength(FALSE);//GetrcParent.Height() - m_cxRightBorder - m_cxLeftBorder;
					}
				}
			}
			else if (bDynamic && (nLength != -1))
			{
				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---nLength != -1\n"));
				CRect rect; rect.SetRectEmpty();
				_CalcInsideRect(rect, (dwMode & LM_HORZ));
				BOOL bVert = (dwMode & LM_LENGTHY);
				int nLen = nLength + (bVert ? rect.Height() : rect.Width());

				SizeMenuBar(nLen, bVert);
				CalcItemLayout(nCount, bVert);// added

				sizeResult = CalcSize(nCount);
			}
			else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
			{
				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---CBRS_FLOATING\n"));
				SizeMenuBar(m_nMRUWidth);
				CalcItemLayout(nCount);// added

				sizeResult = CalcSize(nCount);
			}
			else
			{
				if (!bDynamic) {
					InvalidateRect(NULL);
					goto Junk;
				}

				LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---other\n"));
				BOOL bVert = !(dwMode & LM_HORZ);
				SizeMenuBar(GetClipBoxLength(TRUE));
				CalcItemLayout(nCount, bVert);// added

				if (bVert) {
					InvalidateRect(NULL);// draw forcefully for captions
					sizeResult = CalcVertDockSize(nCount);
					// DockBar not replaced yet, so I can't get precise size
					sizeResult.cy = 10000;
				}
				else {
					sizeResult = CalcSize(nCount);
					sizeResult.cx = GetClipBoxLength(TRUE);
				}
			}
		}
		else {// CBRS_SIZE_FIXED
			LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_FIXED)\n"));
Junk:
			BOOL bVert = !(dwMode & LM_HORZ);
			SizeMenuBar(32767);
			CalcItemLayout(nCount, bVert);// added

			if (bVert) {
				sizeResult = CalcVertDockSize(nCount);
			}
			else {
				sizeResult = CalcSize(nCount);
			}
		}

		if (dwMode & LM_COMMIT)
		{
			LTRACE(_T("CMenuBar::CalcLayout---LM_COMMIT\n"));
			int nControlCount = 0;
			BOOL bIsDelayed = m_bDelayedButtonLayout;
			m_bDelayedButtonLayout = FALSE;

			if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
				m_nMRUWidth = sizeResult.cx;

			//CalcItemLayout(nCount, dwMode);

			m_bDelayedButtonLayout = bIsDelayed;
		}
	}

	//BLOCK: Adjust Margins
	{
		CRect rect; rect.SetRectEmpty();
		_CalcInsideRect(rect, (dwMode & LM_HORZ));
		sizeResult.cy -= rect.Height();
		sizeResult.cx -= rect.Width();

		CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
		sizeResult.cx = max(sizeResult.cx, size.cx);
		sizeResult.cy = max(sizeResult.cy, size.cy);
	}
	return sizeResult;
}

CSize CMenuBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
	LTRACE(_T("CMenuBar::CalcFixedLayout\n"));
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));

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

	return CalcLayout(dwMode);
}

CSize CMenuBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
	LTRACE(_T("CMenuBar::CalcDynamicLayout\n"));
	if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
		((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
	{
		LTRACE(_T("    FixedLayout\n"));
		return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
	}
	return CalcLayout(dwMode, nLength);
}

// set m_bWrapped by nWidth
int CMenuBar::WrapMenuBar(int nCount, int nWidth)
{
//	LTRACE(_T("CMenuBar::WrapMenuBar\n"));
	int nResult = 0;
	int x = 0;

	for (int i = 0; i < nCount; ++i) {
		CMenuItem* pItem = m_arrItem[i];
		if (i+1 == nCount)
			return ++nResult;
		
		if (x + pItem->GetHorizontalSize().cx> nWidth) {// itself is over
			if (pItem->GetStyle() & MISTYLE_WRAPPABLE) {
				pItem->ModifyState(0, MISTATE_WRAP);
				++nResult;
				x = 0;
			}
		}
		else if (x + pItem->GetHorizontalSize().cx + 
				 m_arrItem[i+1]->GetHorizontalSize().cx> nWidth) {
			if (pItem->GetStyle() & MISTYLE_WRAPPABLE) {
				pItem->ModifyState(0, MISTATE_WRAP);
				++nResult;
				x = 0;
			}
		}
		else {
			pItem->ModifyState(MISTATE_WRAP, 0);
			x += pItem->GetHorizontalSize().cx;
		}
	}

	return nResult + 1;
}

// calc only size, by using m_bWrapped
CSize CMenuBar::CalcSize(int nCount)
{
	ASSERT(nCount > 0);
	CPoint cur(0,0);
	CSize sizeResult(0,0);
	int nWrap = 0;
	for (int i = 0; i < nCount; ++i) {
		CMenuItem* pItem = m_arrItem[i];
		sizeResult.cx = max(cur.x + pItem->GetHorizontalSize().cx, sizeResult.cx);
		sizeResult.cy = max(cur.y + pItem->GetHorizontalSize().cy, sizeResult.cy);

		cur.x += pItem->GetHorizontalSize().cx;
		
		if (pItem->GetState() & MISTATE_WRAP) {
			//LTRACE(_T("    nIndex:%d is wrapped\n"), i);
			cur.x = 0;// reset x pos
			cur.y += pItem->GetHorizontalSize().cy;
			++nWrap;
		}
	}

	return sizeResult;
}

void CMenuBar::Layout()
{
	ASSERT(m_bDelayedButtonLayout);

	m_bDelayedButtonLayout = FALSE;

	BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
	if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
		((CMenuBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT);
	else if (bHorz)
		((CMenuBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK | LM_COMMIT);
	else
		((CMenuBar*)this)->CalcDynamicLayout(0, LM_VERTDOCK | LM_COMMIT);
}

void CMenuBar::SizeMenuBar(int nLength, BOOL bVert)
{
	//LTRACE("CMenuBar::SizeMenuBar\n");
	int nCount = GetItemCount(); ASSERT(nCount > 0);

	if (!bVert) {				// nLength is horizontal length

		if (IsFloating()) {		// half size wrapping

			CSize sizeMax, sizeMin, sizeMid;

			// Wrap MenuBar vertically
			WrapMenuBar(nCount, 0);
			sizeMin = CalcSize(nCount);

			// Wrap MenuBar horizontally
			WrapMenuBar(nCount, 32767);
			sizeMax = CalcSize(nCount);

			// we can never understand this algorithm :), see CToolBar implementation
			while (sizeMin.cx < sizeMax.cx) {
//				LTRACE("looping sizeMin.cx:%d < sizeMax.cx:%d\n", sizeMin.cx, sizeMax.cx);
				sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
				WrapMenuBar(nCount, sizeMid.cx);
				sizeMid = CalcSize(nCount);
				if (sizeMid.cx == sizeMax.cx) {	// if you forget, it loops forever!
					return;
				}
//				LTRACE("    sizeMid : %d %d\n", sizeMid.cx, sizeMid.cy);

				if (nLength >= sizeMax.cx) {
//					LTRACE("    nLength:%d >= sizeMax.cx:%d\n", nLength, sizeMax.cx);
					if (sizeMin == sizeMid) {
						WrapMenuBar(nCount, sizeMax.cx);
//						LTRACE("out SizeMenuBar\n");
						return;
					}
					sizeMin = sizeMid;
				}
				else if (nLength < sizeMax.cx) {
//					LTRACE("    nLength:%d < sizeMax.cx:%d\n", nLength, sizeMax.cx);
					sizeMax = sizeMid;
				}
				else {
//					LTRACE("out SizeMenuBar\n");
					return;
				}
			}
		}
		else {								// each one wrapping
			//LTRACE("    just each one wrapping\n");
			WrapMenuBar(nCount, nLength);
		}
	}
	else {						// nLength is vertical length
		CSize sizeMax, sizeMin, sizeMid;

		// Wrap MenuBar vertically
		WrapMenuBar(nCount, 0);
		sizeMin = CalcSize(nCount);

		// Wrap MenuBar horizontally
		WrapMenuBar(nCount, 32767);
		sizeMax = CalcSize(nCount);

		while (sizeMin.cx < sizeMax.cx) {
			sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
			WrapMenuBar(nCount, sizeMid.cx);
			sizeMid = CalcSize(nCount);
			if (sizeMid.cx == sizeMax.cx) {
				return;
			}
			if (nLength < sizeMid.cy) {
				if (sizeMin == sizeMid) {
					WrapMenuBar(nCount, sizeMax.cx);
					//LTRACE("out SizeMenuBar\n");
					return;
				}
				sizeMin = sizeMid;
			}
			else if (nLength > sizeMid.cy)
				sizeMax = sizeMid;
			else {
				//LTRACE("out SizeMenuBar\n");
				return;
			}
		}
	}

	//LTRACE("out SizeMenuBar\n");
}

CSize CMenuBar::CalcVertDockSize(int nCount)
{
	ASSERT(nCount > 0);
	CSize sizeResult(0, 0);

	for (int i = 0; i < nCount; ++i) {
		CMenuItem* pItem = m_arrItem[i];
		sizeResult.cy += pItem->GetRect().Height();
	}

	sizeResult.cx = _cyMenuOnBar;
	return sizeResult;
}

void CMenuBar::CalcItemLayout(int nCount, BOOL bVert)
{
	ASSERT(nCount > 0);
	int x = 0; int y = 0;

	if (!bVert) {
		for (int i = 0; i < nCount; ++i) {
			CMenuItem* pItem = m_arrItem[i];
			CPoint ptItem(x, y);
			pItem->Layout(ptItem, TRUE);// layout by itself!
			if (pItem->GetState() & MISTATE_WRAP) {
				x = 0;// reset x to 0
				y += pItem->GetRect().Height();
			}
			else
				x += pItem->GetRect().Width();
		}		
	}
	else {
		for (int i = 0; i < nCount; ++i) {
			CMenuItem* pItem = m_arrItem[i];
			CPoint	ptItem(0, y);
			pItem->Layout(ptItem, FALSE);	// layout by itself
			y += pItem->GetRect().Height();
		}
	}
}

//////////////////////////////////////////////////////////////////////
// Added by Koay Kah Hoe. Thanx!
void CMenuBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
//	LTRACE(_T("CMenuBar::OnUpdateCmdUI\n"));
	/*
	// if mouse out of frame window, OnUpdateCmdUI never called...
	if (m_nTrackingState == buttonmouse) {
		CPoint pt; ::GetCursorPos(&pt);
		CRect rect;
		GetWindowRect(&rect);

		if (!rect.PtInRect(pt))
			UpdateBar();
	}
	*/

	// but thanks to Koay Kah Hoe,
	// I've found it's nice place for checking child window status.
	if (m_bMDIApp)
		CheckActiveChildWndMaximized();
}

//////////////////////////////////////////////////////////////////////
// CMenuBar decoration
void CMenuBar::EraseNonClientEx()
{
	// get window DC that is clipped to the non-client area
	CWindowDC dc(this);
	CRect rectClient;
	GetClientRect(rectClient);
	CRect rectWindow;
	GetWindowRect(rectWindow);
	ScreenToClient(rectWindow);
	rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
	dc.ExcludeClipRect(rectClient);

	// draw borders in non-client area
	rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);

	if (m_dwExStyle & CBRS_RAISEDBORDER)
		DrawRaisedBorders(&dc, rectWindow);
	else

⌨️ 快捷键说明

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