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

📄 menubar.cpp

📁 一个很好的LFP规约调试器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				m_pMenuIcon->Validate(FALSE);
			}

			RefreshBar();			
		}
	}	
}

void CMenuBar::OnInitMenuPopup()
{
	CMenu menu;
	menu.Attach((HMENU)m_hWindowMenu);

	// scan for first window command
	int n = menu.GetMenuItemCount();
	BOOL bAddSeperator = TRUE;
	for (int iPos=0; iPos<n; iPos++) {
		if (menu.GetMenuItemID(iPos) >= AFX_IDM_FIRST_MDICHILD) {
			bAddSeperator = FALSE;
			break;
		}
	}

	// iPos is either first window item, or end if none found.

	// delete everything after.
	while (iPos < (int)menu.GetMenuItemCount())
		menu.RemoveMenu(iPos, MF_BYPOSITION);

	// get active window so I can check its menu item
	ASSERT(m_hWndMDIClient);
	HWND hwndActive = (HWND)::SendMessage(m_hWndMDIClient,
		WM_MDIGETACTIVE, 0, NULL);

	// append window names in the form "# title"
	int iWin=1;
	for (HWND hwnd=::GetWindow(m_hWndMDIClient, GW_CHILD);
		  hwnd;
		  hwnd = ::GetWindow(hwnd, GW_HWNDNEXT)) {

		if (bAddSeperator) {
			menu.InsertMenu(iPos++, MF_BYPOSITION|MF_SEPARATOR);
			bAddSeperator = FALSE;
		}

		// build item name and add it to the menu
		CString sWinName, sMenuItem;
		CWnd::FromHandle(hwnd)->GetWindowText(sWinName);
		sMenuItem.Format(_T("&%d  %s"), iWin++, (LPCTSTR)sWinName);
		menu.InsertMenu(iPos, MF_BYPOSITION,
			::GetDlgCtrlID(hwnd), sMenuItem);
		if (hwnd==hwndActive)
			menu.CheckMenuItem(iPos, MF_BYPOSITION|MF_CHECKED);
		iPos++;
	}
	menu.Detach();
}

void CMenuBar::OnSetMenu(HMENU hNewMenu, HMENU hWindowMenu)
{
	// We can get active MDI child window on this message!
	BOOL bMax;
	HWND hWndChild = GetActiveChildWnd(bMax);

	if (!m_hWndActiveChild || m_hWndActiveChild != hWndChild) {
		// active child window changed
		LTRACE("    active child window changed\n");
		m_hWndActiveChild = hWndChild;
		// tell MenuIcon child window has been changed
		m_pMenuIcon->OnActivateChildWnd(hWndChild);
	}

	LTRACE("CMenuBar::OnSetMenu\n");

	if (!m_hMenu || m_hMenu != hNewMenu) {	// menu changed
		LTRACE("    menu changed\n");
		LoadMenu(hNewMenu, hWindowMenu);	// set toolbar menu
		GetOwner()->SetMenu(NULL);			// clear frame menu
	}
}

HWND CMenuBar::GetActiveChildWnd(BOOL& bMaximized)
{
	if (!m_hWndMDIClient)
		return NULL;

	BOOL bMax = FALSE;
	HWND hWnd = (HWND)::SendMessage(m_hWndMDIClient,
		WM_MDIGETACTIVE, 0, (LPARAM)&bMax);
	bMaximized = bMax;

	return hWnd;
}


CMenuItem::CMenuItem()
{
	m_itemState = none;
	m_rcItem	= CRect(0, 0, 0, 0);
	m_sizeHorz	= CSize(0, 0);
	m_bHorz		= TRUE;
	m_bWrapped	= FALSE;
}

CMenuItem::~CMenuItem()
{

}

CPoint CMenuItem::ComputeMenuTrackPoint(CWnd* pWnd, HMENU hSubMenu, TPMPARAMS& tpm, CFont* pFont)
{
	ASSERT_VALID(pWnd);
	ASSERT_VALID(pFont);
	ASSERT(::IsMenu(hSubMenu));

	tpm.cbSize = sizeof(tpm);
	CRect& rcExclude = (CRect&)tpm.rcExclude;
	CWnd::GetDesktopWindow()->GetWindowRect(&rcExclude);

	CPoint pt;
	CRect  rcItem = m_rcItem;
	pWnd->ClientToScreen(&rcItem);

//	if (hSubMenu == NULL)		// it's possible no sub menu
//		return CPoint();

	if (m_bHorz) {			// horizontal
		int nCount = ::GetMenuItemCount(hSubMenu);
		ASSERT(nCount != -1);
		int cyPopup = nCount * rcItem.Height();	// I want it be not owner drawn but ordinary menu..

		if (rcItem.bottom + cyPopup > rcExclude.bottom) {
			pt = CPoint(rcItem.left, rcItem.top);	// over Screen
			rcExclude.top = rcItem.top;
		}
		else {
			pt = CPoint(rcItem.left, rcItem.bottom);
		}

		pt += CPoint(-1, 1);						// precisely same as DevStudio
	}
	else {										// vertical
		// we never get the width of popup up menu, but I will try
		int nCount = ::GetMenuItemCount(hSubMenu);
		ASSERT(nCount != -1);
	
		int cxPopup = 0;
		CWindowDC dc(NULL);

		CFont* pOldFont = dc.SelectObject(pFont);
		for (int i = 0; i < nCount; ++i) {
			char szName[256];		
			MENUITEMINFO info;
			::ZeroMemory(&info, sizeof(MENUITEMINFO));
			info.cbSize		= sizeof(MENUITEMINFO);
			info.fMask		= MIIM_ID | MIIM_TYPE;
			info.dwTypeData = szName;
			info.cch		= sizeof(szName);
			::GetMenuItemInfo(hSubMenu, i, TRUE, &info);
			
			CString strItem(szName);

			CRect rcText(0, 0, 0, 0);
			dc.DrawText(strItem, &rcText,
				DT_SINGLELINE | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX);
			int cxOffset = ::GetSystemMetrics(SM_CXMENUCHECK) * 2;
			cxPopup = max(rcText.Width() + 4*2 + CXGAP*2 + cxOffset, cxPopup);
		}
		dc.SelectObject(pOldFont);

		if (rcItem.right + cxPopup > rcExclude.right) {	// over right-side
			pt = CPoint(rcItem.left, rcItem.top);
			rcExclude.left = rcItem.left;
		}
		else {
			pt = CPoint(rcItem.right, rcItem.top);
			rcExclude.right = rcItem.right;
		}

		pt += CPoint(1, -1);							// precisely same as DevStudio
	}

	return pt;
}

CMenuIcon::CMenuIcon(CWnd* pWnd)
{
	m_hDocIcon = NULL;//hIcon;
	m_sizeHorz = CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
	m_bValid = FALSE;
	m_hSysMenu = NULL;//::GetSystemMenu(pWnd->GetSafeHwnd(), FALSE);
}

CMenuIcon::~CMenuIcon()
{

}

void CMenuIcon::Update(CDC* pDC)
{
	ASSERT(m_hDocIcon);
	ASSERT(m_bValid);

	::DrawIconEx(pDC->m_hDC, m_rcItem.left, m_rcItem.top, m_hDocIcon,
		m_sizeHorz.cx, m_sizeHorz.cy, 0, NULL, DI_NORMAL);
}

void CMenuIcon::TrackPopup(CWnd* pWnd)
{
	ASSERT(m_hDocIcon);
	ASSERT(m_bValid);
	ASSERT(::IsMenu(m_hSysMenu));

	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);
	::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
	CFont fontSys;
	if (!fontSys.CreateFontIndirect(&info.lfMenuFont))
		return;

	TPMPARAMS tpm;
	CPoint pt = ComputeMenuTrackPoint(pWnd, m_hSysMenu, tpm, &fontSys);

	::TrackPopupMenuEx(m_hSysMenu,
		TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
		pt.x, pt.y, pWnd->GetOwner()->GetSafeHwnd(), &tpm);
}

void CMenuIcon::Layout(CPoint point, BOOL bHorz)
{
	ASSERT(m_bValid);

	m_bHorz = bHorz;
	m_rcItem = CRect(point, m_sizeHorz);
}

void CMenuIcon::OnActivateChildWnd(HWND hWndChild)
{
	TRACE0("CMenuIcon::OnActivateChildWnd\n");
	ASSERT(::IsWindow(hWndChild));
	m_hSysMenu = ::GetSystemMenu(hWndChild, FALSE);
	ASSERT(::IsMenu(m_hSysMenu));
	m_hDocIcon = (HICON)GetClassLong(hWndChild, GCL_HICONSM);	
}


BOOL CMenuControl::OnMouseMsg(UINT msg, UINT nFlags, CPoint pt)
{
	if (!IsValid())
		return FALSE;

	if (msg == WM_LBUTTONDOWN) {
		m_nTracking = HitTest(pt);
		if (m_nTracking >= 0) {
			CClientDC dc(m_pBar);
			DrawControl(&dc, m_nTracking, TRUE);
			m_bDown = TRUE;
			m_pBar->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_pBar);
			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_pBar);
			DrawControl(&dc, m_nTracking, FALSE);
			CFrameWnd* pFrame = m_pBar->GetTopLevelFrame()->GetActiveFrame();
			ASSERT_VALID(pFrame);
			static syscmd[3] =
			{ /*SC_MOUSEMENU,*/ SC_CLOSE, SC_RESTORE, SC_MINIMIZE };
			//pFrame->SendMessage(WM_SYSCOMMAND, syscmd[m_nTracking]);
			pFrame->PostMessage(WM_SYSCOMMAND, syscmd[m_nTracking]);//libin	.because 
			//after executing sendMessage,The CMenuControl object is destroyed.However, 
			//the following line still accesses the member of destroyed object:m_nTracking = -1;array overflow !

		}
		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)
{
	// draw frame controls
	CRect& rc = m_arrCaption[nIndex];
	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 (!IsValid())
		return;

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


namespace {

	const int CXTEXTMARGIN	  = 5;
	int CYTEXTMARGIN		  = 0;
	const int CYTEXTMARGINMIN = 2;
	
	CFont fontHorz, fontVert;

//	const int CXGAP = 3;

}// anonymouse namespace

CMenuButton::CMenuButton(HMENU hMenu, int nIndex)
{
	ASSERT(hMenu);
	InitButtonStringAndSubMenuHandle(hMenu, nIndex);
	InitHorizontalButtonSize();
	InitAccessKeyAndVerticalLinePoint();
}

CMenuButton::~CMenuButton()
{

}

BOOL CMenuButton::InitCommonResource()
{
	// clean up
	fontHorz.DeleteObject();
	fontVert.DeleteObject();

	// create fonts
	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);
	::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
	if (!fontHorz.CreateFontIndirect(&info.lfMenuFont))
		return FALSE;

	info.lfMenuFont.lfEscapement = -900;
	info.lfMenuFont.lfOrientation = -900;
	strcpy (info.lfMenuFont.lfFaceName, _T("Arial")); //Libin
	if (!fontVert.CreateFontIndirect(&info.lfMenuFont))
		return FALSE;


	// get font height
	LOGFONT logfont;
	fontHorz.GetLogFont(&logfont);
	int cyFont = abs(logfont.lfHeight);

	// calc Y text margin
	int cyText = cyFont + CYTEXTMARGINMIN*2;
	int cyMenu = ::GetSystemMetrics(SM_CYMENU);
	if (cyMenu > cyText) {
		CYTEXTMARGIN = (cyMenu - cyFont)/2;
	}
	else {
		CYTEXTMARGIN = CYTEXTMARGINMIN;
	}

	return TRUE;
}

void CMenuButton::InitButtonStringAndSubMenuHandle(HMENU hMenu, int nIndex)
{
	// get menu button Text
	char szText[256];		
	MENUITEMINFO info; ::ZeroMemory(&info, 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);
}

void CMenuButton::InitHorizontalButtonSize()
{
	// get menu button Text size
	ASSERT(m_strBtn.IsEmpty() == FALSE);

	CWindowDC dc(NULL);
	CRect rcText(0, 0, 0, 0);
	CFont* pOldFont = dc.SelectObject(&fontHorz);
	dc.DrawText(m_strBtn, &rcText, DT_SINGLELINE | DT_CALCRECT);
	dc.SelectObject(pOldFont);
	m_sizeHorz.cx = rcText.Width() + CXTEXTMARGIN*2;

	LOGFONT logfont;
	fontHorz.GetLogFont(&logfont);
	int cyFont = abs(logfont.lfHeight);
	m_sizeHorz.cy = cyFont + CYTEXTMARGIN*2;
}

void CMenuButton::InitAccessKeyAndVerticalLinePoint()
{
	int nIndex = m_strBtn.Find('&');
	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) {
		CRect rcTo;
		CWindowDC dc(NULL);
		CFont* pOldFont = dc.SelectObject(&fontHorz);
		dc.DrawText(m_strBtn.Left(nIndex+2), &rcTo, DT_SINGLELINE | DT_CALCRECT);
		dc.SelectObject(pOldFont);

		m_ptLineFrom = CPoint(CYTEXTMARGIN, CXTEXTMARGIN);
		m_ptLineTo	 = CPoint(CYTEXTMARGIN, CXTEXTMARGIN + rcTo.Width());
	}
	else {
		CRect rcFrom, rcTo;
		CWindowDC dc(NULL);
		CFont* pOldFont = dc.SelectObject(&fontHorz);
		dc.DrawText(m_strBtn.Left(nIndex), &rcFrom, DT_SINGLELINE | DT_CALCRECT);
		dc.DrawText(m_strBtn.Left(nIndex+2), &rcTo, DT_SINGLELINE | DT_CALCRECT);
		dc.SelectObject(pOldFont);

		m_ptLineFrom = CPoint(CYTEXTMARGIN, CXTEXTMARGIN + rcFrom.Width());
		m_ptLineTo = CPoint(CYTEXTMARGIN, CXTEXTMARGIN + rcTo.Width());
	}
}

void CMenuButton::Layout(CPoint point, BOOL bHorz)
{
	if (bHorz == TRUE) {
		m_rcItem = CRect(point, m_sizeHorz);
	}
	else {
		m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx));
	}

	m_bHorz = bHorz;
}

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

	switch (m_itemState) {
	case hot:
		DrawHot(pDC);
		break;
	case select:
		DrawSelect(pDC);
		break;
	case none:
		DrawNone(pDC);
		break;
	default:
		ASSERT(TRUE);
	}
}

void CMenuButton::TrackPopup(CWnd* pWnd)
{
	TPMPARAMS tpm;
	CPoint pt = ComputeMenuTrackPoint(pWnd, m_hSubMenu, tpm, &fontHorz);

	::TrackPopupMenuEx(m_hSubMenu,
		TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
		pt.x, pt.y, pWnd->GetOwner()->GetSafeHwnd(), &tpm);
}

void CMenuButton::DrawHorzText(CDC* pDC, CPoint ptOffset)
{
	CRect rcBtn = m_rcItem;
	pDC->SetBkMode(TRANSPARENT);
	CFont* pOldFont = pDC->SelectObject(&fontHorz);
	// I know precise text size
	//rcBtn.DeflateRect(CXTEXTMARGIN, CYTEXTMARGIN);
	rcBtn.DeflateRect(CXTEXTMARGIN, CYTEXTMARGIN-1); //libin.
	pDC->DrawText(m_strBtn, rcBtn + ptOffset,
		DT_SINGLELINE);// | DT_CENTER | DT_VCENTER);	no need
	
	pDC->SelectObject(pOldFont);
}

void CMenuButton::DrawVertText(CDC* pDC, CPoint ptOffset)
{
	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));

	pDC->SetBkMode(TRANSPARENT);
	CFont* pOldFont = pDC->SelectObject(&fontVert);
	// I must 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);

	// DrawText is poor, so we have to draw vertical line by ourselves
	pDC->MoveTo(rcBtn.TopLeft() + m_ptLineFrom + ptOffset);
	pDC->LineTo(rcBtn.TopLeft() + m_ptLineTo + ptOffset);
}

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

void CMenuButton::DrawSelect(CDC* pDC)
{
	if (m_bHorz) {
		// draw pressed button
		pDC->DrawEdge(m_rcItem, BDR_SUNKENOUTER, BF_RECT);
		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_bHorz) {
		DrawHorzText(pDC);
	}
	else {
		DrawVertText(pDC);
	}
}

int CMenuBar::OnActivateFrame(int nCmdShow)
{
	CFrameWnd* pFrame = GetParentFrame();
	ASSERT_VALID(pFrame);
	if (pFrame->GetMenu() != NULL) {
		LTRACE(" has menu\n");
		pFrame->SetMenu(NULL);
	}
	m_nCmdShow = nCmdShow;
	return SW_HIDE;
}

BOOL CMenuBar::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	GetClientRect(&rect);
	return CControlBar::OnEraseBkgnd(pDC);
}

⌨️ 快捷键说明

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