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

📄 menubar.cpp

📁 在编写图形程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		DrawPressed(pDC);
	}
	else {
		DrawNone(pDC);
	}
}

void CMenuButton::TrackPopup(CWnd* pBar, CWnd* pWndSentCmd)
{
	LTRACE(_T("CMenuButton::TrackPopup\n"));
	ASSERT_VALID(pBar);
	ASSERT(!(m_fsState & MISTATE_HIDDEN));
	CMenuBar* pMenuBar = STATIC_DOWNCAST(CMenuBar, pBar);
	ASSERT_VALID(pMenuBar);

	// "! menu" (no sub menu)
	if (!m_hSubMenu) {
		ASSERT(m_nID != -1);
		pWndSentCmd->SendMessage(WM_COMMAND, (WPARAM)m_nID, (LPARAM)pBar->GetSafeHwnd());		
		return;
	}

	CRect rcItem(m_rcItem);	pMenuBar->ClientToScreen(rcItem);
	UINT fuFlags; TPMPARAMS tpm;
	CPoint pt = _ComputeMenuTrackPoint(rcItem, pMenuBar->GetBarStyle(), fuFlags, tpm);

	if (m_hSubMenu == pMenuBar->m_hWindowMenu)
		_bWindowMenuSendCmd = TRUE;
	else
		_bWindowMenuSendCmd = FALSE;

	::TrackPopupMenuEx(m_hSubMenu, fuFlags,
		pt.x, pt.y, pWndSentCmd->GetSafeHwnd(), &tpm);
}

void CMenuButton::DrawHorzText(CDC* pDC, CPoint ptOffset)
{
	COLORREF clr = (m_fsState & MISTATE_INACTIVE) ? 
		::GetSysColor(COLOR_GRAYTEXT) : ::GetSysColor(COLOR_MENUTEXT);
	pDC->SetTextColor(clr);

	CRect rcBtn = m_rcItem;
	pDC->SetBkMode(TRANSPARENT);
	CFont* pOldFont = pDC->SelectObject(&_fontHorzMenu);
	// I know precise text size, but better to leave this job to Windows
	// *****fixed by andi, thanks!*****
	pDC->DrawText(m_strBtn, rcBtn + ptOffset,
		DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	
	pDC->SelectObject(pOldFont);
}

void CMenuButton::DrawVertText(CDC* pDC, CPoint ptOffset)
{
	COLORREF clr = (m_fsState & MISTATE_INACTIVE) ? 
		::GetSysColor(COLOR_GRAYTEXT) : ::GetSysColor(COLOR_MENUTEXT);
	pDC->SetTextColor(clr);

	CRect rcBtn = m_rcItem;
	int nLength = m_strBtn.GetLength();
	int nIndex = m_strBtn.Find('&');
	CString strBtn = m_strBtn.Left(nIndex) + m_strBtn.Right(nLength - (nIndex+1));

	// fixed for WinNT. *****fixed by Simon, thanks!*****
	int iGraphicsMode = ::GetGraphicsMode(pDC->m_hDC);
	::SetGraphicsMode(pDC->m_hDC, GM_ADVANCED);

	pDC->SetBkMode(TRANSPARENT);
	CFont* pOldFont = pDC->SelectObject(&_fontVertMenu);
	// I know precise text size
	CRect rcString = CRect(
		CPoint(rcBtn.right - _cyTextMargin, rcBtn.top + CXTEXTMARGIN), m_sizeHorz);
	pDC->DrawText(strBtn, rcString + ptOffset,
		DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX);// don't forget DT_NOCLIP
	
	pDC->SelectObject(pOldFont);

	// CDC::DrawText is poor, so we have to draw vertical line by ourselves
	CPen pen(PS_SOLID, 0, clr);
	CPen* pOldPen = pDC->SelectObject(&pen);

	pDC->MoveTo(rcBtn.TopLeft() + m_ptLineFrom + ptOffset);
	pDC->LineTo(rcBtn.TopLeft() + m_ptLineTo + ptOffset);

	pDC->SelectObject(pOldPen);
	::SetGraphicsMode( pDC->m_hDC, iGraphicsMode );
}

void CMenuButton::DrawHot(CDC* pDC)
{
	if (m_fsState & MISTATE_HORZ) {
		// draw pressed button
		pDC->DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
		DrawHorzText(pDC);
	}
	else {
		pDC->DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
		DrawVertText(pDC);
	}
}

void CMenuButton::DrawPressed(CDC* pDC)
{
	if (m_fsState & MISTATE_HORZ) {
		pDC->DrawEdge(m_rcItem, BDR_SUNKENOUTER, BF_RECT);// draw pressed button
		DrawHorzText(pDC, CPoint(1, 1));
	}
	else {
		pDC->DrawEdge(m_rcItem, BDR_SUNKENOUTER, BF_RECT);
		DrawVertText(pDC, CPoint(1, 1));
	}
}

void CMenuButton::DrawNone(CDC* pDC)
{
	if (m_fsState & MISTATE_HORZ) {
		DrawHorzText(pDC);
	}
	else {
		DrawVertText(pDC);
	}
}

//////////////////////////////////////////////////////////////////////
// CMenuIcon class
CMenuIcon::CMenuIcon(CWnd* pMenuBar)
{
	ASSERT_VALID(pMenuBar);
	m_pMenuBar = pMenuBar;
	m_hIconWinLogo = AfxGetApp()->LoadStandardIcon(IDI_WINLOGO);
	ASSERT(m_hIconWinLogo);

	m_fsStyle |= MISTYLE_TRACKABLE;
	m_fsState |= MISTATE_HIDDEN;
	m_sizeHorz = CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
}

CMenuIcon::~CMenuIcon()
{
	if (m_hIconWinLogo != NULL)
		::FreeResource(m_hIconWinLogo);
}

void CMenuIcon::OnActivateChildWnd()
{
	//LTRACE(_T("CMenuIcon::OnActivateChildWnd\n"));

	ASSERT_VALID(m_pMenuBar);
	
	CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
	ASSERT_VALID(pFrame);
	CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
	HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
	ASSERT(::IsWindow(hWndMDIClient));

	BOOL bMaximized = FALSE;
	HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
		WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);

	if (bMaximized == FALSE) {
		//LTRACE(_T("    not maximized\n"));
		m_fsState |= MISTATE_HIDDEN;
	}
	else {
		//LTRACE(_T("    maximized\n"));
		m_fsState &= ~MISTATE_HIDDEN;
	}

	m_hDocIcon = (HICON)::GetClassLong(hWndChild, GCL_HICONSM);

	if (m_hDocIcon == NULL) // if hWndChild doesn't have own icon
		m_hDocIcon = m_hIconWinLogo;
}

void CMenuIcon::Update(CDC* pDC)
{
	if (m_fsState & MISTATE_HIDDEN)
		return;

	ASSERT(m_hDocIcon);
	ASSERT(m_rcItem.IsRectEmpty() == FALSE);
	::DrawIconEx(pDC->m_hDC, m_rcItem.left, m_rcItem.top, m_hDocIcon,
		m_rcItem.Width(), m_rcItem.Height(), 0, NULL, DI_NORMAL);
}

void CMenuIcon::TrackPopup(CWnd* /*pBar*/, CWnd* pWndSentCmd)
{
	ASSERT(!(m_fsState & MISTATE_HIDDEN));
	ASSERT_VALID(m_pMenuBar);
	
	CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
	ASSERT_VALID(pFrame);
	CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
	HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
	ASSERT(::IsWindow(hWndMDIClient));

	BOOL bMaximized = FALSE;
	HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
		WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
	ASSERT(bMaximized);
	HMENU hSysMenu = ::GetSystemMenu(hWndChild, FALSE);
	ASSERT(::IsMenu(hSysMenu));	

	CControlBar* pControlBar = STATIC_DOWNCAST(CControlBar, m_pMenuBar);
	ASSERT_VALID(pControlBar);
	CRect rcItem(m_rcItem);	m_pMenuBar->ClientToScreen(rcItem);
	UINT fuFlags; TPMPARAMS tpm;
	CPoint pt = _ComputeMenuTrackPoint(rcItem, pControlBar->GetBarStyle(), fuFlags, tpm);

	::TrackPopupMenuEx(hSysMenu, fuFlags, pt.x, pt.y, pWndSentCmd->GetSafeHwnd(), &tpm);
}

void CMenuIcon::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;
	}
	
	m_rcItem = CRect(point, CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON)));
}

//////////////////////////////////////////////////////////////////////
// CMenuControl class
#define CX_GAP_CAPTION 2

CMenuControl::CMenuControl(CWnd* pMenuBar)
{
	ASSERT_VALID(pMenuBar);
	m_pMenuBar = pMenuBar;
	m_bDown = FALSE;
	m_nTracking = -1;

	m_fsState |= MISTATE_HIDDEN;

	CSize sizeCaption = GetCaptionSize();
	m_sizeHorz = CSize(sizeCaption.cx*3 + CX_GAP_CAPTION + 1, sizeCaption.cy + 2);
}

void CMenuControl::Update(CDC* pDC)
{
	// do nothing
}

void CMenuControl::Layout(CPoint point, BOOL bHorz)
{
	//LTRACE(_T("CMenuControl::Layout bHorz:%d\n"), bHorz);

	if (bHorz)
		m_fsState |= MISTATE_HORZ;
	else
		m_fsState &= ~MISTATE_HORZ;

	if (m_fsState & MISTATE_HIDDEN) {
		m_rcItem.SetRectEmpty();
		return;
	}

	// just layout easily
	if (bHorz) {
		m_rcItem = CRect(point, m_sizeHorz);
	}
	else {
		m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx));
	}
}

void CMenuControl::DelayLayoutAndDraw(CDC* pDC, CSize sizeBar)
{
	//LTRACE(_T("CMenuControl::DelayLayoutAndDraw\n"));
	//LTRACE(_T("    %d, %d\n"), sizeBar.cx, sizeBar.cy);
	// layout
	CSize sizeCaption = GetCaptionSize();
	int cxCaption = sizeCaption.cx;
	int cyCaption = sizeCaption.cy;

	if (m_fsState & MISTATE_HORZ) {
		CRect rcCaption;
		rcCaption.right = sizeBar.cx;
		rcCaption.bottom = sizeBar.cy;
		rcCaption.left = rcCaption.right - cxCaption;
		rcCaption.top = rcCaption.bottom - cyCaption;

		m_arrCaption[0] = rcCaption;

		rcCaption -= CPoint(cxCaption+CX_GAP_CAPTION, 0);
		m_arrCaption[1] = rcCaption;

		rcCaption -= CPoint(cxCaption, 0);
		m_arrCaption[2] = rcCaption;

		m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top,
			m_arrCaption[0].right, m_arrCaption[0].bottom);
	}
	else {
		CRect rcCaption;
		rcCaption.left = 0;
		rcCaption.bottom = sizeBar.cy;
		rcCaption.right = rcCaption.left + cxCaption;
		rcCaption.top = rcCaption.bottom - cyCaption;

		m_arrCaption[0] = rcCaption;	

		rcCaption -= CPoint(0, cyCaption+CX_GAP_CAPTION);
		m_arrCaption[1] = rcCaption;

		rcCaption -= CPoint(0, cyCaption);
		m_arrCaption[2] = rcCaption;

		m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top,
			m_arrCaption[0].right, m_arrCaption[0].bottom);
	}

	if (m_fsState & MISTATE_HIDDEN) {
		//LTRACE(_T("    hidden\n"));
		return;
	}

	// draw frame controls
	for (int i = 0; i < 3; ++i) {
		DrawControl(pDC, i, FALSE);
	}	
}

BOOL CMenuControl::OnMouseMsg(UINT msg, UINT nFlags, CPoint pt)
{
	if (m_fsState & MISTATE_HIDDEN)
		return FALSE;

	if (msg == WM_LBUTTONDOWN) {
		//LTRACE(_T("    WM_LBUTTONDOWN\n"));
		m_nTracking = HitTest(pt);
		if (m_nTracking >= 0) {
			CClientDC dc(m_pMenuBar);
			DrawControl(&dc, m_nTracking, TRUE);
			m_bDown = TRUE;
			m_pMenuBar->SetCapture();				  // grab mouse input
			return TRUE;
		}
	}
	else if ((msg == WM_MOUSEMOVE) && m_nTracking >= 0) {
		// mouse moved, and I am tracking: possibly draw button up/down
		BOOL bOldDown = m_bDown;
		m_bDown = m_arrCaption[m_nTracking].PtInRect(pt);
		if (bOldDown != m_bDown) {
			// up/down state changed: need to redraw button
			CClientDC dc(m_pMenuBar);
			DrawControl(&dc, m_nTracking, m_bDown);
		}
		return TRUE; // handled

	}
	else if (msg == WM_LBUTTONUP && m_nTracking >= 0) {
		// user released the mouse and I am tracking: do button command
		ReleaseCapture(); // let go the mouse
		if (m_bDown) {
			// if button was down when released: draw button up, and do system cmd
			CClientDC dc(m_pMenuBar);
			DrawControl(&dc, m_nTracking, FALSE);
			CFrameWnd* pFrame = m_pMenuBar->GetTopLevelFrame()->GetActiveFrame();
			ASSERT_VALID(pFrame);
			static int syscmd[3] =
			{ /*SC_MOUSEMENU,*/ SC_CLOSE, SC_RESTORE, SC_MINIMIZE };
			// SendMessage occur access violation!
			// *****fixed by Koay Kah Hoe. Thanks!*****
			pFrame->PostMessage(WM_SYSCOMMAND, syscmd[m_nTracking]);
		}
		m_nTracking = -1; // stop tracking
		return TRUE;	  // handled (eat)
	}

	return FALSE;
}

int CMenuControl::HitTest(CPoint point)
{
	for (int i = 0; i < 3; ++i) {
		if (m_arrCaption[i].PtInRect(point))
			return i;
	}

	return -1;
}

void CMenuControl::DrawControl(CDC* pDC, int nIndex, BOOL bPressed)
{
	//LTRACE(_T("CMenuControl::DrawControl\n"));
	// draw frame controls
	CRect& rc = m_arrCaption[nIndex];
	//LTRACE(_T("    %d, %d, %d, %d\n"), rc.left, rc.top, rc.right, rc.bottom);
	static UINT dfcs[3] = { DFCS_CAPTIONCLOSE, DFCS_CAPTIONRESTORE, DFCS_CAPTIONMIN };
	UINT uState = dfcs[nIndex];
	if (bPressed)
		uState |= DFCS_PUSHED;
	pDC->DrawFrameControl(rc, DFC_CAPTION, uState);
}

void CMenuControl::ForceDrawControl(CDC * pDC)
{
	if (m_fsState & MISTATE_HIDDEN)
		return;

	for (int i = 0; i < 3; ++i) {
		DrawControl(pDC, i, FALSE);
	}
}

void CMenuControl::OnActivateChildWnd()
{
	//LTRACE(_T("CMenuControl::OnActivateChildWnd\n"));
	ASSERT_VALID(m_pMenuBar);
	
	CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
	ASSERT_VALID(pFrame);
	CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
	HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
	ASSERT(::IsWindow(hWndMDIClient));

	BOOL bMaximized = FALSE;
	HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
		WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);

	if (bMaximized == FALSE) {
		m_fsState |= MISTATE_HIDDEN;
	}
	else {
		m_fsState &= ~MISTATE_HIDDEN;
	}
}

CSize CMenuControl::GetCaptionSize()
{
	NONCLIENTMETRICS info; info.cbSize = sizeof(info);
	::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);

	// due to my own feeling
	return CSize(info.iMenuHeight - info.iBorderWidth*2, info.iMenuHeight - info.iBorderWidth*4);
}

#if _MFC_VER < 0x0600
void CMenuBar::SetBorders(int cxLeft, int cyTop, int cxRight, int cyBottom)
{
	ASSERT(cxLeft >= 0);
	ASSERT(cyTop >= 0);
	ASSERT(cxRight >= 0);
	ASSERT(cyBottom >= 0);

	m_cxLeftBorder = cxLeft;
	m_cyTopBorder = cyTop;
	m_cxRightBorder = cxRight;
	m_cyBottomBorder = cyBottom;
}
#endif

void CMenuBar::_DrawGripper(CDC* pDC, const CRect& rect)
{
	COLORREF clrBtnHilite = ::GetSysColor(COLOR_BTNHILIGHT);
	COLORREF clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);

	BOOL bDrawGripper = !(m_dwStyle & CBRS_FLOATING) && (m_dwExStyle & CBRS_GRIPPER);

	// only draw the gripper if not floating and gripper is specified
	if (bDrawGripper)
	{
		// draw the gripper in the border
		if (m_dwStyle & CBRS_ORIENT_HORZ)
		{
			if (bDrawGripper) {
				pDC->Draw3dRect(rect.left+CX_BORDER_GRIPPER,
					rect.top+m_cyTopBorder,
					CX_GRIPPER, rect.Height()-m_cyTopBorder-m_cyBottomBorder,
					clrBtnHilite, clrBtnShadow);
			}		
		}
		else
		{
			if (bDrawGripper) {
				pDC->Draw3dRect(rect.left+m_cyTopBorder,
					rect.top+CY_BORDER_GRIPPER,
				

⌨️ 快捷键说明

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