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

📄 menubar.cpp

📁 一个IE的辅助菜单插件。附全部的源代码文件。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// MenuBar.cpp : implementation file
//

#include "stdafx.h"
#include "ExplorerFavorateMenu.h"
#include "MenuBar.h"
#include "resource.h"

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

/////////////////////////////////////////////////////////////////////////////
#define MB_POPUPMENU	WM_USER + 100
#define ID_FIRSTMENU	WM_USER + 200
#define TPM_VERPOSANIMATION 0x1000L
#define PriMenuButtonIDIncresement 100
#define FOLDERICONINDEX		-1
#define NOICONFOUND			-2
// CMenuBar

CMenuBar::CMenuBar()
{
	m_bTrack = FALSE;
	m_hMenu = NULL;
	m_nPressed = -1;
	m_nPriMenuItemCount = 0;
}

CMenuBar::~CMenuBar()
{
	FreeMenuResource(m_hMenu);
	DestroyIcon(m_hIeIcon);
	DestroyIcon(m_hFolderIcon);
}

BEGIN_MESSAGE_MAP(CMenuBar, CToolBar)
	//{{AFX_MSG_MAP(CMenuBar)
	ON_WM_LBUTTONDOWN()
	ON_MESSAGE(MB_POPUPMENU, OnPopupMenu)
	ON_WM_DRAWITEM()
	ON_WM_MEASUREITEM()
	ON_MESSAGE(WM_MENUCOMMAND, OnMenuCommand)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMenuBar message handlers
////////////////////////////////////////////////////////////////////////////////
CMenuBar*	pMenuBar	= NULL;
HHOOK		g_hMsgHook	= NULL;

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

	//因为TrackPopupMenuEx调用后线程等待用户输入,此时
	//就不能处理其他消息,所以采用钩子.
	if(!pMenuBar || nCode != MSGF_MENU)//只处理菜单消息
		return CallNextHookEx(g_hMsgHook,nCode,wParam,lParam);

	if(pMenuBar->OnMenuInput(pMsg))
		return TRUE;
	else
		return CallNextHookEx(g_hMsgHook,nCode,wParam,lParam);
}

HWND CMenuBar::Create(HWND ParentWnd) 
{
	CWnd TmpParamWnd;
	TmpParamWnd.Attach (ParentWnd);
	if(!CToolBar::CreateEx (&TmpParamWnd, TBSTYLE_FLAT|TBSTYLE_TRANSPARENT))
	{	
		TmpParamWnd.Detach ();
		return NULL;
	}
	TmpParamWnd.Detach ();
	
	if(!InitMenuBar())
		return NULL;

	m_hIeIcon = (HICON)LoadImage(_Module.m_hInstResource, MAKEINTRESOURCE(IDI_IEICON), IMAGE_ICON, 0, 0, 0); 
	m_hFolderIcon = (HICON)LoadImage(_Module.m_hInstResource, MAKEINTRESOURCE(IDI_FOLDERICON), IMAGE_ICON, 0, 0, 0); 

	return m_hWnd;
}

BOOL CMenuBar::InitMenuBar()
{
	if(!CreateFavorateMenu())
		return FALSE;
	
	//用工具栏模拟菜单
	//主菜单ID从ID_FIRSTMENU起
	CToolBarCtrl& tbc = GetToolBarCtrl();
	tbc.SetBitmapSize (CSize(0,0));//没有图标, 置图标尺寸为0.
	
	m_nPriMenuItemCount = GetMenuItemCount(m_hMenu);
	int nStrIndex;		TCHAR MenuText[64];
	TBBUTTON MenuBtn;   RECT rect;
	TBBUTTONINFO tif;   tif.cbSize = sizeof(tif);

	HDC hOwnerDC = ::GetDC(m_hWnd);//选用标准字体来测定文字所占空间
	HGDIOBJ hOldFnt = SelectObject(hOwnerDC, GetStockObject(DEFAULT_GUI_FONT));
	
	for(int i = 0;i < m_nPriMenuItemCount;i++)
	{
		//设置Toolbar上的按钮,仅文字,故似菜单.
		GetMenuString(m_hMenu, i, MenuText, 64, MF_BYPOSITION);
		nStrIndex = AddString(MenuText);
		MenuBtn.iBitmap = NULL;
		MenuBtn.dwData = 0;
		MenuBtn.fsState = TBSTATE_ENABLED;
		MenuBtn.fsStyle = TBSTYLE_BUTTON;
		MenuBtn.idCommand = ID_FIRSTMENU + i*PriMenuButtonIDIncresement;
		MenuBtn.iString = nStrIndex;
		tbc.InsertButton (-1, &MenuBtn);
		
		tif.dwMask = TBIF_SIZE;
		DrawText(hOwnerDC, MenuText, lstrlen(MenuText), &rect, DT_LEFT|DT_CALCRECT|DT_SINGLELINE);

		tif.cx = rect.right - rect.left + 12;
		tbc.SetButtonInfo (MenuBtn.idCommand, &tif);
	}

	SelectObject(hOwnerDC, hOldFnt);
	::ReleaseDC(m_hWnd, hOwnerDC);

	return TRUE;
}

int CMenuBar::AddString(LPCTSTR lpszString)
{
	//虽然MSDN说必须以两个\0结尾,但仅一个字符串时,可以直接以普通单个\0结尾
	TCHAR TmpStr[66];
	lstrcpy(TmpStr, lpszString);
	TmpStr[lstrlen(lpszString)+1] = '\0';
	return SendMessage(TB_ADDSTRING, (WPARAM)NULL, (LPARAM)TmpStr);
}

void CMenuBar::PressButton(int nIndex, BOOL bPress)
{
	//显示下压状态
	CToolBarCtrl& tbc = GetToolBarCtrl();
	tbc.PressButton (ID_FIRSTMENU + nIndex*100, bPress); 
}

void CMenuBar::OnLButtonDown(UINT nFlags, CPoint point) 
{
	//菜单所有相关操作从这开始
	m_ptMouse.x = point.x;
	m_ptMouse.y = point.y;

	//nTest是所按下主菜单项的Index
	int nTest = SendMessage(TB_HITTEST, 0, (LPARAM)&m_ptMouse);

	if(nTest < 0 || nTest >= m_nPriMenuItemCount)
		return;

	m_nPressed = nTest;//记录所按下菜单项
	TrackPopup();//弹出菜单
}

//////////////////////////////////////////////////////////////////////////
//跟踪弹出子菜单
/////////////////////////////////////////////////////////////////////////
void CMenuBar::TrackPopup()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());//Init MFC
	
	//MFC与API混合编程,Cool! MenuBar包装并抽象了m_hMenu,使之表现为一个Window Bar.
	HMENU hSubMenu = GetSubMenu(m_hMenu, m_nPressed);//得到子菜单句柄
	if(hSubMenu == NULL)
		return;

	m_bTrack = TRUE;//开始跟踪
	PressButton(m_nPressed, TRUE);//压下按钮

	RECT rc;
	GetItemRect(m_nPressed,&rc);
	ClientToScreen(&rc);

	TPMPARAMS tpm;
	tpm.cbSize = sizeof(tpm);
	tpm.rcExclude = rc;
	//设置钩子函数
	pMenuBar = this;
	g_hMsgHook = SetWindowsHookEx(WH_MSGFILTER,	MenuInputFilter, NULL, GetCurrentThreadId());

	//跟踪菜单弹出,线程转入钩子函数的运作.
	TrackPopupMenuEx(hSubMenu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL|TPM_VERPOSANIMATION, rc.left, rc.bottom, m_hWnd, NULL);
	
	PressButton(m_nPressed, FALSE);
	UnhookWindowsHookEx(g_hMsgHook);//解除钩子函数

	g_hMsgHook = NULL;
	pMenuBar = NULL;
}
/////////////////////////////////////////////////////////////////////////////////
BOOL CMenuBar::OnMenuInput(MSG* pMsg)
{
	BOOL bResult = FALSE;
	
	//处理在PopMenu后主线程等待时的其他消息。
	switch(pMsg->message)
	{
	case WM_MOUSEMOVE:
		{
			POINT pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(&pt);
			if(m_ptMouse.x == pt.x && m_ptMouse.y == pt.y)
				return TRUE;
		
			m_ptMouse.x = pt.x;
			m_ptMouse.y = pt.y;

			int nTest = SendMessage(TB_HITTEST, 0, (LPARAM)&pt);

			//鼠标移动到非当前项
			if(nTest >= 0 && nTest< m_nPriMenuItemCount && nTest != m_nPressed)
			{
				PressButton(m_nPressed, FALSE);//回复原下压菜单
				
				//撤销弹出菜单, TrackPopMenuEx后的语句开始执行。
				//注意, 此时两个线程开始同时运行。
				PostMessage(WM_CANCELMODE, 0, 0);
				
				//下压后移项,弹出菜单
				m_nPressed = nTest;
				PostMessage(MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
		}
		break;
	case WM_LBUTTONDOWN:
		{
			POINT pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(&pt);

			int nTest = SendMessage(TB_HITTEST, 0, (LPARAM)&pt);

			if(nTest<0)
				m_bTrack = FALSE;
			else if(nTest == m_nPressed)
			{
				m_bTrack = FALSE;
				PostMessage(WM_CANCELMODE, 0, 0);
				bResult = TRUE;
			}
		}
		break;
	case WM_KEYDOWN:
		{
			TCHAR vkey = pMsg->wParam;
			if(vkey == VK_LEFT)
			{
				PressButton(m_nPressed,FALSE);
				m_nPressed --;
				PostMessage(WM_CANCELMODE,0,0);
				PostMessage(MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
			else if(vkey == VK_RIGHT)
			{
				PressButton(m_nPressed, FALSE);
				m_nPressed++;
				PostMessage(WM_CANCELMODE,0,0);
				PostMessage(MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
			else if (vkey == VK_ESCAPE)
			{
				PostMessage(WM_CANCELMODE, 0, 0);
				m_bTrack = FALSE;
				bResult = TRUE;
			}
		}
		break;

	default:
		break;
	}

	return bResult;
}
////////////////////////////////////////////////////////////////////////////
LRESULT CMenuBar::OnPopupMenu(WPARAM wParam, LPARAM lParam)
{
	//左右轮循
	if(m_nPressed < 0)
		m_nPressed = m_nPriMenuItemCount - 1;

	if(m_nPressed >=  m_nPriMenuItemCount)
		m_nPressed = 0;

	TrackPopup();
	return 0;
}

BOOL CMenuBar::CreateFavorateMenu()
{
	//太复杂了,说不出!
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	
	WIN32_FIND_DATA fd;
	TCHAR FavoritesPath[MAX_PATH];//保持的收藏夹目录
	TCHAR lpszChildFolder[MAX_PATH];

	m_URLStringArray.RemoveAll ();
	m_uMenuIDOrder = ID_FIRSTMENU;

	if(!SHGetSpecialFolderPath(m_hWnd, FavoritesPath, CSIDL_FAVORITES, FALSE))
		return FALSE;
	
	lstrcpy(lpszChildFolder, FavoritesPath);
	lstrcat(lpszChildFolder, "\\*.*");
	
	HANDLE hFindFile = FindFirstFile(lpszChildFolder, &fd);
	
	if(hFindFile == INVALID_HANDLE_VALUE)//没找到任何文件夹,一般不可能发生.
	{
		FindClose(hFindFile);
		return FALSE;

⌨️ 快捷键说明

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