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

📄 menubar.cpp

📁 在编写图形程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		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 = 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 shapes 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;

	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:
	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_hWindowMenu) {
					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];
//			::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()
{
}

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);
			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(_T("CMenuBar::WM_MDIREFRESHMENU\n"));
		return 0;

//	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);
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrameHook 
CMainFrameHook::CMainFrameHook()
{
	m_pMenuBar = NULL;
}

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

CMainFrameHook::~CMainFrameHook()
{
}

LRESULT CMainFrameHook::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);
	}

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

	case WM_INITMENUPOPUP:
		if (!HIWORD(lParam) && (HMENU)wParam == m_pMenuBar->m_hWindowMenu)
			m_pMenuBar->OnInitMenuPopup(CMenu::FromHandle((HMENU)wParam),
				LOWORD(lParam), (BOOL)HIWORD(lParam));
		break;

	case WM_NCACTIVATE:
		m_pMenuBar->OnFrameNcActivate((BOOL)wParam);
		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;
	}

	if (nMsg == CMenuBar::WM_GETMENU)
		return (LRESULT)m_pMenuBar->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(HMENU hMenu, int nIndex)
{
	ASSERT(::IsMenu(hMenu));
	ASSERT(nIndex >= 0);

	m_fsStyle |= (MISTYLE_TRACKABLE | MISTYLE_WRAPPABLE);
	InitButtonStringAndSubMenuHandle(hMenu, nIndex);
	InitHorizontalButtonSize();
	InitAccessKeyAndVerticalLinePoint();
}

void CMenuButton::InitButtonStringAndSubMenuHandle(HMENU hMenu, int nIndex)
{
	// get menu button Text
	TCHAR szText[256];
	MENUITEMINFO info; ::memset(&info, 0, sizeof(MENUITEMINFO));
	info.cbSize		= sizeof(MENUITEMINFO);
	info.fMask		= MIIM_ID | MIIM_TYPE;
	info.dwTypeData = szText;
	info.cch		= sizeof(szText);
	::GetMenuItemInfo(hMenu, nIndex, TRUE, &info);
	m_strBtn = CString(szText);

	m_hSubMenu = ::GetSubMenu(hMenu, nIndex);
	if (!m_hSubMenu) {
		m_nID = ::GetMenuItemID(hMenu, 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;
}

void CMenuButton::InitAccessKeyAndVerticalLinePoint()
{
	int nIndex = m_strBtn.Find('&');
	if (nIndex + 1 == m_strBtn.GetLength()) {
		TRACE(_T("warning : & is bad position, access key is invalid.\n"));
		m_cAccessKey = 0;
		m_ptLineFrom = m_ptLineTo = CPoint(0, 0);
		return;
	}
	
	m_cAccessKey = m_strBtn[nIndex + 1];// -1 + 1 = 0; it's ok

	if (nIndex == -1) {
		m_ptLineFrom = m_ptLineTo = CPoint(0, 0);
	}
	else if (nIndex == 0) {
		m_ptLineFrom = CPoint(_cyTextMargin, CXTEXTMARGIN);
		m_ptLineTo	 = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex+2)));
	}
	else {
		m_ptLineFrom = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex)));
		m_ptLineTo = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex+2)));
	}
}

void CMenuButton::Layout(CPoint point, BOOL bHorz)
{
	if (bHorz)
		m_fsState |= MISTATE_HORZ;
	else
		m_fsState &= ~MISTATE_HORZ;

	if (m_fsState & MISTATE_HIDDEN) {
		m_rcItem.SetRectEmpty();
		return;
	}
	
	if (bHorz) {
		m_rcItem = CRect(point, m_sizeHorz);
	}
	else {
		m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx));
	}
}

void CMenuButton::Update(CDC* pDC)
{
	if (m_fsState & MISTATE_HIDDEN)
		return;
	
	// clean background
	COLORREF clr = ::GetSysColor(COLOR_BTNFACE);
	pDC->FillSolidRect(m_rcItem, clr);

	if (m_fsState & MISTATE_HOT){
		DrawHot(pDC);
	}
	else if (m_fsState & MISTATE_PRESSED){

⌨️ 快捷键说明

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