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

📄 menubar.cpp

📁 用VC写的浏览器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////
// Copyright 1998 Paul DiLascia
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
// CMenuBar implements menu bar for MFC. See MenuBar.h for how
// to use, and also the MBTest sample application.
//
#include "StdAfx.h"
#include "MenuBar.h"
#include "ToolMenu.h"
#include "GreenBrowser.h"
#include "function.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//##############################################################
#define countof(x)	(sizeof(x)/sizeof(x[0]))

//##############################################################
BOOL	g_bNoHook = FALSE;
//give WM_NCHITTEST a chance to handle before WM_MOUSEMOVE
int		g_nDelay = 10;

//##############################################################
extern	BOOL g_bRTab;

//##############################################################

IMPLEMENT_DYNAMIC(CMenuBar, CToolBar)

BEGIN_MESSAGE_MAP(CMenuBar, CToolBar)
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_UPDATE_COMMAND_UI_RANGE(0, 256, OnUpdateMenuButton)
	ON_WM_NCHITTEST()
END_MESSAGE_MAP()

CMenuBar::CMenuBar()
{
	m_iTrackingState = TRACK_NONE;		 // initial state: not tracking 
	m_iPopupTracking = m_iNewPopup = -1; // invalid
	m_hmenu = NULL;
	m_nMenuItems = 0;
	//
	g_bNoHook = FALSE;
	g_nDelay = 10;
}

CMenuBar::~CMenuBar()
{
	DestroyMenuData(m_hmenu,0);
}

//////////////////
// Menu bar was created: install hook into owner window
//
int CMenuBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CToolBar::OnCreate(lpCreateStruct)==-1)
		return -1;
	UpdateFont();
	return 0; // OK
}

//////////////////
// Load a different menu. The HMENU must not belong to any CMenu,
// and you must free it when you're done. Returns old menu.
//
HMENU CMenuBar::LoadMenu(HMENU hmenu)
{
	UINT iPrevID=(UINT)-1;
	ASSERT(::IsMenu(hmenu));
	ASSERT_VALID(this);

	HMENU hOldMenu = m_hmenu;
	m_hmenu = hmenu;

	// delete existing buttons
	int nCount = GetToolBarCtrl().GetButtonCount();
	while (nCount--) {
		VERIFY(GetToolBarCtrl().DeleteButton(0));
	}

	GetToolBarCtrl().SetImageList(NULL);

	DWORD dwStyle = GetStyle();
	BOOL bModifyStyle = ModifyStyle(0, TBSTYLE_FLAT|TBSTYLE_TRANSPARENT);

	// add text buttons
	UINT nMenuItems = hmenu ? ::GetMenuItemCount(hmenu) : 0;
	for (UINT i=0; i < nMenuItems; i++)
	{
		TCHAR name[64];
		memset(name, 0, sizeof(name)); // guarantees double-0 at end
		if (theApp.m_bUseLngFile)
		{
			char num[10];
			sprintf(num,"X%d",i);
			if (_GetPrivateProfileString("MenuMain", num, NULL, name, countof(name)-1, theApp.m_strLngFile)==FALSE)
				::GetMenuString(hmenu, i, name, countof(name)-1, MF_BYPOSITION);
		}
		else
			::GetMenuString(hmenu, i, name, countof(name)-1, MF_BYPOSITION);
		//
		TBBUTTON tbb;
		memset(&tbb, 0, sizeof(tbb));
		tbb.idCommand = ::GetMenuItemID(hmenu, i);

		// Because the toolbar is too brain-damaged to know if it already has
		// a string, and is also too brain-dead to even let you delete strings,
		// I have to determine if each string has been added already. Otherwise
		// in a MDI app, as the menus are repeatedly switched between doc and
		// no-doc menus, I will keep adding strings until somebody runs out of
		// memory. Sheesh!
		// 
		int iString = -1;
		for (int j=0; j<m_arStrings.GetSize(); j++) {
			if (m_arStrings[j] == name) {
				iString = j; // found it
				break;
			}
		}
		if (iString <0) {
			// string not found: add it
			iString = GetToolBarCtrl().AddStrings(name);
			m_arStrings.SetAtGrow(iString, name);
		}

		tbb.iString = iString;
		tbb.fsState = TBSTATE_ENABLED;
		tbb.fsStyle = TBSTYLE_AUTOSIZE;
		tbb.iBitmap = -1;
		tbb.idCommand = i;
		VERIFY(GetToolBarCtrl().AddButtons(1, &tbb));
	}

	if (bModifyStyle)
		SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
	
	if (hmenu) {
		GetToolBarCtrl().AutoSize();// size buttons
		m_nMenuItems = GetToolBarCtrl().GetButtonCount();
	}
	return hOldMenu;
}

//////////////////
// Load menu from resource
//
HMENU CMenuBar::LoadMenu(LPCSTR lpszMenuName)
{
	return LoadMenu(::LoadMenu(AfxGetResourceHandle(), lpszMenuName));
}

//////////////////
// Set menu bar font from current system menu font
//
void CMenuBar::UpdateFont()
{
	static CFont font;
	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);
	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
	if ((HFONT)font)
		font.DeleteObject();
	VERIFY(font.CreateFontIndirect(&info.lfMenuFont));
	SetFont(&font);
}

//////////////////
// The reason for having this is so MFC won't automatically disable
// the menu buttons. Assumes < 256 top-level menu items. The ID of
// the ith menu button is i. IOW, the index and ID are the same.
//
void CMenuBar::OnUpdateMenuButton(CCmdUI* pCmdUI)
{
	ASSERT_VALID(this);
	if (IsValidButton(pCmdUI->m_nID))
		pCmdUI->Enable(TRUE);
}

//////////////////
// Set tracking state: none, button, or popup
//
void CMenuBar::SetTrackingState(TRACKINGSTATE iState, int iButton)
{
	ASSERT_VALID(this);
	if (iState != m_iTrackingState)
	{
		if (iState == TRACK_NONE)
			iButton = -1;
		GetToolBarCtrl().SetHotItem(iButton);// could be none (-1)
		if (iState==TRACK_POPUP)
		{
			// set related state stuff
			m_bEscapeWasPressed = FALSE;	 // assume Esc key not pressed
			m_bProcessRightArrow =			 // assume left/right arrow..
				m_bProcessLeftArrow = TRUE; // ..will move to prev/next popup
			m_iPopupTracking = iButton;	 // which popup I'm tracking
		}
		m_iTrackingState = iState;
	}
}

//////////////////
// Toggle state from home state to button-tracking and back
//
void CMenuBar::ToggleTrackButtonMode()
{
	ASSERT_VALID(this);
	if (m_iTrackingState == TRACK_NONE || m_iTrackingState == TRACK_BUTTON)
	{
		SetTrackingState(m_iTrackingState == TRACK_NONE ?
			TRACK_BUTTON : TRACK_NONE, 0);
	}
}

//////////////////
// Get button index before/after a given button
//
int CMenuBar::GetNextOrPrevButton(int iButton, BOOL bPrev)
{
	ASSERT_VALID(this);
	if (bPrev)
	{
		iButton--;
		if (iButton <0)
			iButton = m_nMenuItems - 1;//GetToolBarCtrl().GetButtonCount()
	}
	else
	{
		iButton++;
		if (iButton >= m_nMenuItems)//GetToolBarCtrl().GetButtonCount()
			iButton = 0;
	}
	return iButton;
}

/////////////////
// This is to correct a bug in the system toolbar control: TB_HITTEST only
// looks at the buttons, not the size of the window. So it returns a button
// hit even if that button is totally outside the size of the window!
//
int CMenuBar::HitTest(CPoint p) const
{
	int iHit = GetToolBarCtrl().HitTest(&p);
	if (iHit>0)
	{
		CRect rc;
		GetClientRect(&rc);
		if (!rc.PtInRect(p)) // if point is outside window
			iHit = -1;			// can't be a hit!
	}
	return iHit;
}

//////////////////
// Handle mouse click: if clicked on button, press it
// and go into main menu loop.
//
void CMenuBar::OnLButtonDown(UINT nFlags, CPoint pt)
{
	try{
	ASSERT_VALID(this);
	int iButton = HitTest(pt);
	if (iButton >= 0 && iButton<m_nMenuItems) //GetToolBarCtrl().GetButtonCount() if mouse is over a button:
		TrackPopup(iButton);								 //   track it
	else														 // otherwise:
		CToolBar::OnLButtonDown(nFlags, pt);	 //   pass it on...
	}catch(...){}
}

//////////////////
// Handle mouse movement
//
void CMenuBar::OnMouseMove(UINT nFlags, CPoint pt)
{
	ASSERT_VALID(this);

	if (m_iTrackingState==TRACK_BUTTON)
	{
		// In button-tracking state, ignore mouse-over to non-button area.
		// Normally, the toolbar would de-select the hot item in this case.
		// 
		// Only change the hot item if the mouse has actually moved.
		// This is necessary to avoid a bug where the user moves to a different
		// button from the one the mouse is over, and presses arrow-down to get
		// the menu, then Esc to cancel it. Without this code, the button will
		// jump to wherever the mouse is--not right.

		int iHot = HitTest(pt);
		if (IsValidButton(iHot) && pt != m_ptMouse)
			GetToolBarCtrl().SetHotItem(iHot);
		return;// don't let toolbar get it
	}
	m_ptMouse = pt; // remember point
	CToolBar::OnMouseMove(nFlags, pt);
}

/////////////////
// When user selects a new menu item, note whether it has a submenu
// and/or parent menu, so I know whether right/left arrow should
// move to the next popup.
//
void CMenuBar::OnMenuSelect(HMENU hmenu, UINT iItem)
{
	if (m_iTrackingState > 0)
	{
		// process right-arrow iff item is NOT a submenu
		m_bProcessRightArrow = (::GetSubMenu(hmenu, iItem) == NULL);
		// process left-arrow iff curent menu is one I'm tracking
		//m_bProcessLeftArrow = hmenu==m_hMenuTracking;

⌨️ 快捷键说明

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