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

📄 menubar.cpp

📁 用户管理系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*********************************************************
* Simple IE-like Menu And Toolbar
* Version: 1.3
* Date: Semptember 1, 2003
* Autor: Michal Mecinski
* E-mail: mimec@mimec.w.pl
* WWW: http://www.mimec.w.pl
*
* Copyright (C) 2002-03 by Michal Mecinski
*********************************************************/

#include "stdafx.h"
#include "MenuBar.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// size of menu icons
#define MB_CX_ICON	16
#define MB_CY_ICON	16
#define GRAY_AREA_LENGTH   23


CMenuBar::CMenuBar()
{
	m_bCues = false;
	m_bFlatMenu = true;
	m_bKeepPrefix = false;
	m_bKeyboard = FALSE;
	m_bNextMenu = false;
	m_bPopMenu = FALSE;
	m_bPrefix = TRUE;
	m_hSelMenu = NULL;
	m_bSelPopup = false;
	m_bWndActive = TRUE;
   
	m_hSelMenu = NULL;
	m_nItemCount = 0;
	m_nPressed = -1;

	m_pMenu = NULL;
	m_pPopupMenu = NULL;
	m_pPrevFocus = NULL;
}

CMenuBar::~CMenuBar()
{
	delete m_pMenu;
	delete m_pPopupMenu;
}

BEGIN_MESSAGE_MAP(CMenuBar, CToolBarCtrl)
	ON_WM_LBUTTONDOWN()
	ON_WM_KILLFOCUS()
	ON_WM_INITMENUPOPUP()
	ON_WM_MEASUREITEM()
	ON_WM_DRAWITEM()
	ON_WM_ENTERIDLE()
	ON_WM_MENUSELECT()
	ON_MESSAGE(MBM_POPUPMENU, OnPopupMenu)
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CMenuBar public functions

BOOL CMenuBar::Create(CWnd* pParentWnd, UINT nID)
{
	return CToolBarCtrl::Create(WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NODIVIDER | CCS_NORESIZE,
		CRect(0, 0, 0, 0), pParentWnd, nID);
}


BOOL CMenuBar::LoadMenuBar(UINT nID, int nStyle)
{
	if (m_pMenu)
		m_pMenu->DestroyMenu();
	else
		m_pMenu = new CMenu;

	// load menu resource
	if (!m_pMenu->LoadMenu(nID))
		return FALSE;

	// create image list
	if (!m_ImgList.Create(MB_CX_ICON, MB_CY_ICON, nStyle))
		return FALSE;

	m_CmdArray.RemoveAll();

	// delete previous buttons if any
	while (m_nItemCount--)
		DeleteButton(0);

	m_nItemCount = m_pMenu->GetMenuItemCount();

	SetBitmapSize(CSize(1, 1));

	TBBUTTON tbb; 
	ZeroMemory(&tbb, sizeof(tbb));

	tbb.fsState = TBSTATE_ENABLED;
	tbb.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE;

	// add button for each menu
	for(int i=0; i<m_nItemCount; i++)
	{
		CString strText;
		m_pMenu->GetMenuString(i, strText, MF_BYPOSITION);

		tbb.iString = AddStrings(strText);
		tbb.idCommand = i;

		if (!AddButtons(1, &tbb))
			return FALSE;
	}

	// get system settings and resize toolbar
	UpdateSettings();

	return TRUE;
}

BOOL CMenuBar::AttachMenu(HMENU hMenu)
{
	if (m_pMenu)
		m_pMenu->Detach();
	else
		m_pMenu = new CMenu;

	m_pMenu->Attach(hMenu);

	while (m_nItemCount--)
		DeleteButton(0);

	m_nItemCount = m_pMenu->GetMenuItemCount();

	SetBitmapSize(CSize(1, 1));

	TBBUTTON tbb; 
	ZeroMemory(&tbb, sizeof(tbb));

	tbb.fsState = TBSTATE_ENABLED;
	tbb.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE;

	// add button for each menu
	for(int i=0; i<m_nItemCount; i++)
	{
		CString strText;
		m_pMenu->GetMenuString(i, strText, MF_BYPOSITION);

		tbb.iString = AddStrings(strText);
		tbb.idCommand = i;

		if (!AddButtons(1, &tbb))
			return FALSE;
	}

	UpdateSettings();

	return TRUE;
}

BOOL CMenuBar::LoadToolBar(UINT nID)
{
	HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nID), RT_TOOLBAR);
	HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nID), RT_TOOLBAR);
	if (hRsrc == NULL)
		return FALSE;

	HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
	if (hGlobal == NULL)
		return FALSE;

	struct TBDATA
	{
		WORD wVersion;
		WORD wWidth;
		WORD wHeight;
		WORD wItemCount;
		WORD aItems[1];
	};

	// get the toolbar data
	TBDATA* pData = (TBDATA*)LockResource(hGlobal);
	if (pData == NULL)
		return FALSE;
	ASSERT(pData->wVersion == 1);

	// add command IDs to the array
	for (int i=0; i < pData->wItemCount; i++)
	{
		int nCmd = pData->aItems[i];
		if (nCmd != 0)	// ignore separators
			m_CmdArray.Add(nCmd);
	}

	// load bitmap image
	BOOL bResult = m_ImgList.AddBitmap(nID);

	UnlockResource(hGlobal);
	FreeResource(hGlobal);

	return bResult;
}

HMENU CMenuBar::GetMenuHandle()
{
	return m_pMenu ? m_pMenu->m_hMenu : NULL;
}


BOOL CMenuBar::LoadPopupMenu(UINT nID)
{
	if (m_pPopupMenu)
		m_pPopupMenu->DestroyMenu();
	else
		m_pPopupMenu = new CMenu;

	return m_pPopupMenu->LoadMenu(nID);
}

void CMenuBar::TrackPopup(int nIndex, CPoint ptPos)
{
	// use window menu if popup menu is not loaded
	CMenu* pSubMenu = m_pPopupMenu ? m_pPopupMenu->GetSubMenu(nIndex) : m_pMenu->GetSubMenu(nIndex);

	m_bPopMenu = m_pPopupMenu!=NULL;

	if (pSubMenu)
		pSubMenu->TrackPopupMenu(0, ptPos.x, ptPos.y, this);
}

void CMenuBar::TrackPopup(LPCSTR lpszName, CPoint ptPos)
{
	CMenu* pMenu = m_pPopupMenu ? m_pPopupMenu : m_pMenu;

	for (UINT i=0; i<pMenu->GetMenuItemCount(); i++)
	{
		CString str;
		pMenu->GetMenuString(i, str, MF_BYPOSITION);
		if (str.Compare(lpszName) == 0)
		{
			TrackPopup(i, ptPos);
			return;
		}
	}
}


/////////////////////////////////////////////////////////////////////////////
// CMenuBar input filter

//CMenuBar* CMenuBar::g_pMenuBar	= NULL;
//HHOOK CMenuBar::g_hMsgHook	= NULL;
static CMenuBar* g_pMenuBar = NULL;
static HHOOK g_hMsgHook = NULL;

LRESULT CMenuBar::MenuInputFilter(int nCode, WPARAM wParam, LPARAM lParam)
{
	MSG* pMsg = (MSG*)lParam;

	if (g_pMenuBar && nCode == MSGF_MENU)
	{
		// process menu message
		if (g_pMenuBar->OnMenuInput(pMsg))
			return TRUE;
	}
    if(!g_hMsgHook) return 0;
	return CallNextHookEx(g_hMsgHook, nCode, wParam, lParam);
}

BOOL CMenuBar::OnMenuInput(MSG* pMsg)
{
	BOOL bResult = FALSE;

	switch(pMsg->message)
	{
	case WM_MOUSEMOVE:
		{
			CPoint pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(&pt);

			if (pt == m_ptLast)	// ignore if mouse not moved
				return TRUE;

			m_ptLast = pt;

			int nTest = HitTest(&pt);

			// check if another menu was highlighted
			if (nTest>=0 && nTest<m_nItemCount && nTest != m_nPressed)
			{
				PressButton(m_nPressed, FALSE);
				m_bKeepPrefix = TRUE;
				m_bNextMenu = TRUE;
				SendMessage(WM_CANCELMODE);	// close current menu
				m_nPressed = nTest;
				PostMessage(MBM_POPUPMENU);	// open highlighted menu
				return TRUE;
			}
		}
		break;

	case WM_LBUTTONDOWN:
		{
			POINT pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(&pt);

			int nTest = HitTest(&pt);

			if (nTest == m_nPressed)	// close menu if clicked again
			{
				m_bKeepPrefix = TRUE;
				m_bNextMenu = TRUE;
				SendMessage(WM_CANCELMODE,0,0);
				return TRUE;
			}
		}
		break;

	case WM_KEYDOWN:
		{
			switch (pMsg->wParam)
			{
			case VK_LEFT:
				if (InSubMenu())	// default action - close submenu
					return FALSE;
				PressButton(m_nPressed, FALSE);
				m_bKeepPrefix = TRUE;
				m_bNextMenu = TRUE;
				SendMessage(WM_CANCELMODE);
				m_nPressed--;		// open previous menu
				m_bKeyboard = TRUE;
				PostMessage(MBM_POPUPMENU);
				return TRUE;

			case VK_RIGHT:
				if (m_bSelPopup)	// default action - open submenu
					return FALSE;
				PressButton(m_nPressed,FALSE);
				m_bKeepPrefix = TRUE;
				m_bNextMenu = TRUE;
				SendMessage(WM_CANCELMODE);
				m_nPressed++;		// open next menu
				m_bKeyboard = TRUE;
				PostMessage(MBM_POPUPMENU);
				return TRUE;

			case VK_ESCAPE:
				if (InSubMenu())	// default action - close submenu
					return FALSE;
				m_ptLast = CPoint(-1,-1);
				m_bKeepPrefix = TRUE;
				SendMessage(WM_CANCELMODE);
				Highlight(m_nPressed);	// activate the menu bar
				return TRUE;
			}
		}
		break;

	case WM_MENUSELECT:
		{
			// store info about selected item
			m_hSelMenu = (HMENU)pMsg->lParam;
			m_bSelPopup = (HIWORD(pMsg->wParam) & MF_POPUP) != 0;
			// notify main frame
			if (HIWORD(pMsg->wParam) != 0xFFFF)
				GetParentFrame()->SendMessage(WM_MENUSELECT, pMsg->wParam, pMsg->lParam);
			return TRUE;
		}
		break;
	}

	return FALSE;
}

BOOL CMenuBar::InSubMenu()
{
	for (int i=0; i<m_nItemCount; i++)
	{
		// check if current menu is one of top level menus
		if (m_hSelMenu == m_pMenu->GetSubMenu(i)->m_hMenu)
			return FALSE;
	}

	// otherwise it's a submenu
	return TRUE;
}

void CMenuBar::Highlight(int nItem)
{
	SetHotItem(nItem);	// hihglight item

	if (nItem < 0)
	{
		// restore focus
		if (m_pPrevFocus && IsWindow(m_pPrevFocus->m_hWnd))
			m_pPrevFocus->SetFocus();
		m_pPrevFocus = NULL;
	}
	else
	{
		// steal focus
		m_pPrevFocus = SetFocus();
	}
}

void CMenuBar::UpdateSettings()
{
	m_bCues = TRUE;
	m_bFlatMenu = FALSE;

	SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &m_bCues, 0);
	SystemParametersInfo(SPI_GETFLATMENU, 0, &m_bFlatMenu, 0);
//指定为平面模式
    m_bFlatMenu = TRUE;

	SetPrefix(m_bCues);

	// create menu font
	NONCLIENTMETRICS ncmet;
	ncmet.cbSize = sizeof(ncmet);
	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncmet), &ncmet, 0);

	m_Font.DeleteObject();
	m_Font.CreateFontIndirect(&ncmet.lfMenuFont);

	SetFont(&m_Font);	// use it to draw toolbar buttons too

⌨️ 快捷键说明

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