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

📄 explorermenu.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 2 页
字号:

#pragma once

#include <vector>
#include <algorithm>

// for debug
#ifdef _DEBUG
	const bool _Mtl_ExplorerMenu_traceOn = false;
	#define epmTRACE if (_Mtl_ExplorerMenu_traceOn) ATLTRACE
#else
	#define epmTRACE
#endif

// be care, if no element, &array[0] is invalid.
template <class _Key, class _Val>
class CCrasyMap : public CSimpleArray< std::pair<_Key, _Val> >
{
public:
	bool FindKey(const _Key& __key)
	{
		if (GetSize() == 0)
			return false;

		return end() != std::find_if(begin(), end(), _Finder(__key));
	}

	void Add(const _Key& __key, const _Val& __val)
	{
		if (GetSize() == 0) {
			CSimpleArray< std::pair<_Key, _Val> >::Add(std::make_pair(__key, __val));
			return;
		}

		std::pair<_Key, _Val>* p = std::find_if(begin(), end(), _Finder(__key));
		if (p == end())
			CSimpleArray< std::pair<_Key, _Val> >::Add(std::make_pair(__key, __val));
		else
			(*p).second = __val;
	}

	_Val Lookup(const _Key& __key)
	{
		if (GetSize() == 0)
			return _Val();

		std::pair<_Key, _Val>* p = std::find_if(begin(), end(), _Finder(__key));
		if (p != end())
			return p->second;
		else
			return _Val();
	}

	void Sort()
	{
		if (GetSize() == 0)
			return;

		std::sort(begin(), end(), _Compare());		
	}

	std::pair<_Key, _Val>* begin()
	{
		return &(*this)[0];
	}

	std::pair<_Key, _Val>* end()
	{
		return &(*this)[0] + GetSize();
	}

//	template <class _Key, class _Val>
	struct _Finder
	{
		_Key __aKey;
		_Finder(_Key __key) : __aKey(__key) { }
		bool operator()(const std::pair<_Key, _Val>& src)
		{
			return (__aKey == src.first);
		}
	};

//	template <class _Key, class _Val>
	struct _Compare
	{
		bool operator()(const std::pair<_Key, _Val>& x, const std::pair<_Key, _Val>& y)
		{
			return x.second < y.second;
		}
	};
};

// Extended styles
#define EMS_ADDITIONALMENUITEM		0x00000001L
#define EMS_ADDITIONALMENUITEMNOSEP 0x00000002L
#define EMS_USER					0x00010000L

#define PASS_MSG_MAP_MENUOWNER_TO_EXPMENU(x) CHAIN_MSG_MAP_MEMBER(x)
/*
class ATL_NO_VTABLE CExplorerMenuImplBase
{
public:
	static int s_nMaxMenuItemTextLength;
	static int s_nMaxMenuBreakCount;

	static void SetMaxMenuItemTextLength(int n)
	{
		s_nMaxMenuItemTextLength = n;
	}

	static int GetMaxMenuItemTextLength()
	{
		return s_nMaxMenuItemTextLength;
	}

	static void SetMaxMenuBreakCount(int n)
	{
		s_nMaxMenuBreakCount = n;
	}

	static int GetMaxMenuBreakCount()
	{
		return s_nMaxMenuBreakCount;
	}
};

__declspec(selectany) int CExplorerMenuImplBase::s_nMaxMenuItemTextLength = 50;
__declspec(selectany) int CExplorerMenuImplBase::s_nMaxMenuBreakCount = 5000;
*/

template <class T>
class ATL_NO_VTABLE CExplorerMenuImpl// : public CExplorerMenuImplBase
{
public:
// Declarations

// Constants

// Data members
	DWORD m_dwStyle;

	CMenuHandle m_menu;
//	CMenu m_menuOriginal;
	int m_nOriginalMenuItemCountExceptInsertPointMenuItem;
	int m_nOriginalInsertPoint;
	int m_nMaxMenuBreakCount;
	int m_nMaxMenuItemTextLength;

	CString m_strRootDirectoryPath;
	CString m_strNoEntries;
	CString m_strAdditional;

	CSimpleArray<HMENU> m_arrMenuHandle;
	int m_nCurrentMenuID;
	CCrasyMap<int, CString> m_mapID;			// id and file path
	CCrasyMap<HMENU, CString> m_mapSubMenu;		// menu handle and file path

	int m_nInsertPointMenuItemID;
	int m_nMinID, m_nMaxID;

	CSimpleArray<CString> m_arrIgnoredPath;

// Constructor
	CExplorerMenuImpl(int nInsertPointMenuItemID, const CString& strNoEntries = _T("(empty)"),
		int nMinID = 0x7000, int nMaxID = 0x7FFF,
		const CString& strAdditional = _T("Open This Directory"), int nMaxMenuItemTextLength = 55)
		: m_strNoEntries(strNoEntries), m_strAdditional(strAdditional),
		  m_nInsertPointMenuItemID(nInsertPointMenuItemID),
		  m_nMinID(nMinID), m_nMaxID(nMaxID),
		  m_dwStyle(0), m_nMaxMenuBreakCount(5000), m_nMaxMenuItemTextLength(55)
	{
		m_nCurrentMenuID = m_nMinID;
	}

	BOOL InstallExplorerMenu(HMENU hMenu)
	{
		SetMenuHandle(hMenu);
		return TRUE;
	}

	~CExplorerMenuImpl()
	{
	}

// Overridables
	void OnMenuItemInitialUpdate(const CString& strDirPath, CSimpleArray<CMenuItemInfo>& infos)
	{
		std::sort(_begin(infos), _end(infos), _DefaultMenuItemCompare(*this));
	}

	void OnExecute(const CString& strFilePath)
	{
	}

	CString OnGetMenuItemText(const CString& strPath)
	{
		CString str = MtlGetDisplayTextFromPath(strPath);
		str = MtlCompactString(str, m_nMaxMenuItemTextLength);
		str.Replace(_T("&"), _T("&&"));

		return str;
	}

// Attributes
	void SetMenuHandle(HMENU hMenu)
	{
		ATLASSERT(::IsMenu(hMenu));
	
		// save original menu infos
		ATLASSERT(_FindInsertPoint(hMenu) != -1);// need InsertPointMenuItem
		m_nOriginalMenuItemCountExceptInsertPointMenuItem = ::GetMenuItemCount(hMenu) - 1;
		m_nOriginalInsertPoint = _FindInsertPoint(hMenu);

		m_menu = hMenu;
	}

	CString GetRootDirectoryPath() const
	{
		return m_strRootDirectoryPath;
	}

	void SetRootDirectoryPath(const CString& strDirectoryPath)
	{
//		ATLASSERT(strDirectoryPath.IsEmpty() == FALSE);
		m_strRootDirectoryPath = strDirectoryPath;
	}

	BOOL LoadAdditionalMenu(_U_STRINGorID menu)
	{
		return m_menuAdditional.LoadMenu(menu);
	}

	void SetStyle(DWORD dwStyle)
	{
		m_dwStyle = dwStyle;
	}

	DWORD GetStyle() const
	{
		return m_dwStyle;
	}

	void AddIgnoredPath(CString& strPath)
	{
		m_arrIgnoredPath.Add(strPath);
	}

	void ResetIgnoredPath()
	{
		m_arrIgnoredPath.RemoveAll();
	}

// Methods
/*
	template <class _Profile>
	void GetProfileExpMenu(_Profile& __profile)
	{
		DWORD dwStyle, dwLength, dwCount;
		LONG lRet = __profile.QueryValue(dwStyle, _T("Style"));
		if (lRet != ERROR_SUCCESS)
			dwStyle = 0;

		lRet = __profile.QueryValue(dwLength,  _T("Max_Text_Length"));
		if (lRet != ERROR_SUCCESS)
			dwLength = 55;

		lRet = __profile.QueryValue(dwCount,  _T("Max_Break_Count"));
		if (lRet != ERROR_SUCCESS)
			dwCount = 5000;

		SetStyle(dwStyle);
		SetMaxMenuItemTextLength(dwLength);
		SetMaxMenuBreakCount(dwCount);
	}

	template <class _Profile>
	void WriteProfileExpMenu(_Profile& __profile)
	{
		__profile.SetValue(GetStyle(), _T("Style"));
		__profile.SetValue(GetMaxMenuItemTextLength(), _T("Max_Text_Length"));
		__profile.SetValue(GetMaxMenuBreakCount(), _T("Max_Break_Count"));
	}
*/


// Message map and handlers
	BEGIN_MSG_MAP(CExplorerMenu)
		MSG_WM_INITMENUPOPUP(OnInitMenuPopup)
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
		COMMAND_RANGE_HANDLER_EX(m_nMinID, m_nMaxID, OnCommandRange)
	END_MSG_MAP()

	void OnInitMenuPopup(HMENU hmenuPopup, UINT uPos, BOOL fSystemMenu)
	{
		SetMsgHandled(FALSE);
		if (m_strRootDirectoryPath.IsEmpty())
			return;

		epmTRACE(_T("CExplorerMenu::OnInitMenuPopup : %d\n"), m_nCurrentMenuID);

//		Somehow, fSystemMenu is sometimes wrong value, why?
//		if (fSystemMenu) {// window menu, do nothing
//			epmTRACE(_T(" It's system menu, return");
//			return;
//		}

		if (m_menu.m_hMenu == hmenuPopup) {// root menu
			epmTRACE(_T(" It's root menu\n"));
			// delayed clean up if menu not clicked
			m_mapID.RemoveAll();
			// at first, add it to the list
			m_arrMenuHandle.Add(hmenuPopup);

			// restore original menu (it's need cuz WM_MENUSELECT is not sent if not toplevel menu. for example. chevron menu)
			_RestoreOriginalMenu();

			// delete insert point menu item
			_DeleteInsertPointMenuItem();

			int nInsertPoint = m_nOriginalInsertPoint;
			_Explore(m_menu, nInsertPoint, m_strRootDirectoryPath);
		}
		else if (m_arrMenuHandle.Find(hmenuPopup) != -1){// it's my menu
//			epmTRACE(_T(" It's %s menu\n"), m_strTestText);
			// first, clean up all the menu items
			_DeleteAllMenuItems(hmenuPopup);
			_Explore(hmenuPopup, 0, _LoadDirectoryPath(hmenuPopup));
			SetMsgHandled(TRUE);// eat it!!
		}
	}

	void OnCommandRange(UINT, int nID, HWND hWndCtrl)
	{
		if (hWndCtrl) {
			SetMsgHandled(FALSE);
			return;
		}

		epmTRACE(_T("CExplorerMenu::OnCommandRange : %d\n"), nID);
		T* pT = static_cast<T*>(this);
		if (CString() != m_mapID.Lookup(nID))
			pT->OnExecute(m_mapID.Lookup(nID));
		m_mapID.RemoveAll();// delayed clean up.
	}

	LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		epmTRACE(_T("CExplorerMenu::OnMenuSelect\n"));
		UINT uItem = LOWORD(wParam);
		UINT fuFlags = HIWORD(wParam);
		HMENU hmenu = (HMENU)lParam;

		SetMsgHandled(FALSE);
		bHandled = FALSE;// must be, oh my god!!!!!!

		// Check if a menu is closing, do a cleanup
		if (fuFlags == 0xFFFF && hmenu == NULL) {// menu closing
			// NOTE: this message sent only if top level menu!!!
			epmTRACE(_T(" Cleanup\n"));
			_CleanUpExceptIDMap();
		}
//		else if (m_arrMenuHandle.Find(hmenu) != -1){// it's my menu
//		}

		return 0;
	}

	void _CleanUpExceptIDMap()
	{
		epmTRACE(_T("CExplorereMenu::_CleanUpExceptIDMap\n"));
		
		// restore original menu
		_RestoreOriginalMenu();

		m_arrMenuHandle.RemoveAll();
		m_mapSubMenu.RemoveAll();
		m_nCurrentMenuID = m_nMinID;
	}	

	void _AddNoneMenuItem(CMenuHandle menu, int& nInsertPoint)
	{
		CMenuItemInfo mii;
		mii.fMask = MIIM_STATE | MIIM_TYPE;
		mii.fType = MFT_STRING;
		mii.fState = MFS_GRAYED;
		mii.dwTypeData = (LPTSTR)(LPCTSTR)m_strNoEntries;

⌨️ 快捷键说明

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