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

📄 menubar.cpp

📁 visual c++ 实例编程
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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
		DrawBorders(&dc, rectWindow);

	// erase parts not drawn
	dc.IntersectClipRect(rectWindow);
	SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);

	// draw gripper in non-client area
	_DrawGripper(&dc, rectWindow);
}


#define CX_BORDER   1
#define CY_BORDER   1
void CMenuBar::DrawRaisedBorders(CDC* pDC, CRect& rect)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pDC);

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

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

	// 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 += cyBorder2;
	if (dwStyle & CBRS_BORDER_BOTTOM)
		rect2.bottom -= cyBorder2;

	// draw left and top
	if (dwStyle & CBRS_BORDER_LEFT)
		pDC->FillSolidRect(0, rect2.top, CX_BORDER, rect2.Height(), clrBtnFace);
	if (dwStyle & CBRS_BORDER_TOP)
		pDC->FillSolidRect(0, 0, rect.right, CY_BORDER, clrBtnFace);

	// draw right and bottom
	if (dwStyle & CBRS_BORDER_RIGHT)
		pDC->FillSolidRect(rect1.right, rect2.top, -CX_BORDER, rect2.Height(), clrBtnShadow);
	if (dwStyle & CBRS_BORDER_BOTTOM)
		pDC->FillSolidRect(0, rect1.bottom, rect.right, -CY_BORDER, clrBtnShadow);

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

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

	if (dwStyle & CBRS_BORDER_LEFT)
		rect.left += cxBorder2;
	if (dwStyle & CBRS_BORDER_TOP)
		rect.top += cyBorder2;
	if (dwStyle & CBRS_BORDER_RIGHT)
		rect.right -= cxBorder2;
	if (dwStyle & CBRS_BORDER_BOTTOM)
		rect.bottom -= cyBorder2;		
}

int CMenuBar::GetNextOrPrevButton(int nIndex, BOOL bPrev)
{
	int nCount = GetItemCount();
	if (bPrev) {				// <-
		--nIndex;
		if (nIndex < 0)
			nIndex = nCount - 1;
	}
	else {						// ->
		++nIndex;
		if (nIndex >= nCount)
			nIndex = 0;
	}

	if (!(m_arrItem[nIndex]->GetStyle() & MISTYLE_TRACKABLE) ||
		(m_arrItem[nIndex]->GetState() & MISTATE_HIDDEN)) {
		return GetNextOrPrevButton(nIndex, bPrev);
	}

	return nIndex;
}

/////////////////////////////////////////////////////////////////////////////
// CMenuBar insists own bar line 
void CMenuBar::EnableDockingEx(DWORD dwDockStyle)
{
	// pasted from CFrameWnd implementation
	static const DWORD dwDockBarMap[4][2] =
	{
		{ AFX_IDW_DOCKBAR_TOP,      CBRS_TOP    },
		{ AFX_IDW_DOCKBAR_BOTTOM,   CBRS_BOTTOM },
		{ AFX_IDW_DOCKBAR_LEFT,     CBRS_LEFT   },
		{ AFX_IDW_DOCKBAR_RIGHT,    CBRS_RIGHT  },
	};

	EnableDocking(dwDockStyle);

	// must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
	ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);

	CFrameWnd* pFrame = CControlBar::GetParentFrame(); ASSERT_VALID(pFrame);
	//pFrame->m_pFloatingFrameClass = RUNTIME_CLASS(CMiniDockFrameWnd);
	for (int i = 0; i < 4; i++)
	{
		if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)
		{
			CDockBar* pDock = (CDockBar*)pFrame->GetControlBar(dwDockBarMap[i][0]);
			if (pDock == NULL)
			{
				pDock = new CMenuDockBar;// which wait for CMenuBar
				if (!pDock->Create(pFrame,
					WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
					dwDockBarMap[i][1], dwDockBarMap[i][0]))
				{
					AfxThrowResourceException();
				}
			}
		}
	}
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar OLE menu support
//		MFC does'nt do command routing for other process server.
//		::TrackPopupMenuEx won't accept HWND of other process and
//		we have to determine a message target(ole server window or not)
//		as ::OleCreateMenuDescriptor do.
//		This is a hard coding. 
//		First menu(ordinarily File menu) and WindowMenu regarded as container's own menu.
//		Some components can't update toolbar button and statusbar pane.
HWND CMenuBar::OleMenuDescriptor(BOOL& bSend, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	CWnd* pOleWnd = GetCmdSentOleWnd();
	if (pOleWnd == NULL)
		return NULL;
	HWND hWndSentCmd = NULL;

	CMenuEx* pMenu = NULL;
	HMENU hMenu = NULL;
	if (nMsg == WM_INITMENUPOPUP || nMsg == WM_INITMENU)
		hMenu = (HMENU)wParam;
	else if (nMsg == WM_MENUSELECT)
		hMenu = (HMENU)lParam;

	switch (nMsg) {
	case WM_INITMENUPOPUP:
		if (!((BOOL)HIWORD(lParam)) && 
			m_pMenu->IsMenu(CMenu::FromHandle((HMENU) wParam)))
			CMenuEx::UpdateMenu(m_pMenu);
	case WM_INITMENU:
	case WM_MENUSELECT:
		bSend = TRUE;
		if (m_nTrackingState == popup) {
			LTRACE2(_T("    now popup\n"));
			if (m_bMDIApp) {
				LTRACE2(_T("    this is MDI\n"));
				if (m_nCurIndex == 0 || m_nCurIndex == 1 || hMenu == m_pWindowMenu->m_hMenu) {
					LTRACE2(_T("    it's container menu, send to frame\n"));
					return NULL;
				}
			}
			else {
				LTRACE2(_T("    it's container menu, send to frame\n"));
				if (m_nCurIndex == 0) {
					return NULL;
				}
			}
			LTRACE2(_T("    it's server menu, send to server\n"));
			return pOleWnd->GetSafeHwnd();
		}
		break;

	case WM_COMMAND:
		bSend = FALSE;
		if (m_bMDIApp) {
			LTRACE2(_T("    this is MDI\n"));
			if (_nPrevIndexForCmd == 0 || _nPrevIndexForCmd == 1 || _bWindowMenuSendCmd) {
				LTRACE2(_T("    it's container menu, send to frame\n"));
				return NULL;
			}
		}
		else {
			if (_nPrevIndexForCmd == 0) {
				LTRACE2(_T("    it's container menu, send to frame\n"));
				return NULL;
			}
		}
		LTRACE2(_T("    it's server menu, send to server\n"));
		return pOleWnd->GetSafeHwnd();
	}

	return NULL;// send to frame
}

CWnd* CMenuBar::GetCmdSentOleWnd()
{
	// *****fixed by VORGA, thanks!*****
	CWnd* pWnd = AfxGetMainWnd();
	if (pWnd == NULL || !pWnd->IsFrameWnd())
		return NULL;
	
	CFrameWnd* pFrame = NULL;
	if (m_bMDIApp) {
		CMDIFrameWnd *pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pWnd);
		if (pMDIFrame == NULL)
			return NULL;
		pFrame = pMDIFrame->GetActiveFrame();
	}
	else {
		pFrame = STATIC_DOWNCAST(CFrameWnd, pWnd);
	}

	if (pFrame == NULL)
		return NULL;

	CDocument* pDoc = pFrame->GetActiveDocument();
	if (pDoc != NULL && pDoc->IsKindOf(RUNTIME_CLASS(COleDocument))) {
		COleDocument* pOleDoc = STATIC_DOWNCAST(COleDocument, pDoc);
		ASSERT_VALID(pOleDoc);
		COleClientItem* pClientItem = pOleDoc->GetInPlaceActiveItem(pFrame);
		CWnd* pWnd = (pClientItem == NULL) ? NULL : pClientItem->GetInPlaceWindow();
		if (pWnd != NULL) {
//			TCHAR str[256];

⌨️ 快捷键说明

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