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

📄 mtlctrlw.h

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

#pragma once

#ifndef __MTLMISC_H__
	#error mtlctrlw.h requires mtlmisc.h to be included first
#endif
////////////////////////////////////////////////////////////////////////////
// MTL Version 0.10
// Copyright (C) 2001 MB<mb2@geocities.co.jp>
// All rights unreserved.
//
// This file is a part of Mb Template Library.
// The code and information is *NOT* provided "as-is" without
// warranty of any kind, either expressed or implied.
//
// MtlCtrlw.h: Last updated: March 17, 2001
/////////////////////////////////////////////////////////////////////////////
namespace MTL
{
/////////////////////////////////////////////////////////////////////////////
// Command Bars

// Window Styles:
#define CBR2WS_TOP				CCS_TOP
#define CBR2WS_BOTTOM			CCS_BOTTOM
#define CBR2WS_NORESIZE			CCS_NORESIZE
#define CBR2WS_NOPARENTALIGN	CCS_NOPARENTALIGN
#define CBR2WS_NODIVIDER		CCS_NODIVIDER

// Extended styles
#define CBR2_EX_TRANSPARENT	0x00000001L	// not supported yet
#define CBR2_EX_SHAREMENU	0x00000002L

// standard command bar styles
#define MTL_SIMPLE_CMDBAR2_PANE_STYLE \
	(WS_CHILD | WS_VISIBLE | CBR2WS_NODIVIDER | CBR2WS_NORESIZE | CBR2WS_NOPARENTALIGN)

/////////////////////////////////////////////////////////////////////////////
// Forward declarations

template <class T, class TBase = CCommandBarCtrl2Base, class TWinTraits = CControlWinTraits> class CCommandBarCtrlImpl;
class CCommandBarCtrl2;

/////////////////////////////////////////////////////////////////////////////
// CCmdBarButton

// CCmdBarButton state flags
#define CBSTATE_ENABLED		0x01
#define CBSTATE_PRESSED		0x02
#define CBSTATE_HOT			0x04
#define CBSTATE_INACTIVE	0x08
#define CBSTATE_HIDDEN		0x10

class CCmdBarButton
{
public:
// Data members
	BYTE m_fsState;
	CString m_strBtn;		// string on button
	CMenuHandle m_menuSub;	// handle to sub menu
	TCHAR m_cAccessKey;		// access key (Alt key + X)
	CRect m_rcBtn;
		
// Constructor/destructor
	CCmdBarButton(BYTE fsState, const CString& strBtn, HMENU hSubMenu)
		: m_fsState(fsState), m_strBtn(strBtn), m_menuSub(hSubMenu)
	{
		// init access key
		int nIndex = m_strBtn.Find(_T('&'));
		if (nIndex + 1 == m_strBtn.GetLength()) {
			ATLTRACE(_T("warning : & is bad position, access key is invalid.\n"));
			m_cAccessKey = 0;
		}
		m_cAccessKey = m_strBtn[nIndex + 1];// -1 + 1 = 0; it's ok
	}
	
// Attributes
	bool ModifyState(BYTE fsRemove, BYTE fsAdd)
	{
		bool bOldEnable = m_fsState & CBSTATE_ENABLED;
		m_fsState = (m_fsState & ~fsRemove) | fsAdd;
		bool bNewEnable = m_fsState & CBSTATE_ENABLED;
		return bOldEnable != bNewEnable;
	}	

// Methods
	void Update(CDCHandle dc)
	{
		if (m_fsState & CBSTATE_HIDDEN)
			return;
		
		if (m_fsState & CBSTATE_HOT) {
			DrawHot(dc);
		}
		else if (m_fsState & CBSTATE_PRESSED) {
			DrawPressed(dc);
		}
		else {
			_DrawText(dc);
		}
	}
	
	void TrackPopup(HWND hWnd, HWND hWndMenuOwner, bool bW2K)
	{
// Menu animation flags
#ifndef TPM_VERPOSANIMATION
		const UINT TPM_VERPOSANIMATION = 0x1000L;
#endif
#ifndef TPM_NOANIMATION
		const UINT TPM_NOANIMATION = 0x4000L;
#endif

		// "! menu"
		ATLASSERT(m_menuSub.IsMenu());

		CWindow wnd(hWnd);
		// get popup menu and it's position
		CRect rect = m_rcBtn;
		wnd.ClientToScreen(&rect);
		TPMPARAMS TPMParams;
		TPMParams.cbSize = sizeof(TPMPARAMS);
		TPMParams.rcExclude = rect;

		m_menuSub.TrackPopupMenuEx(TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN |
			(bW2K ? (true ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0),
			rect.left, rect.bottom, hWndMenuOwner, &TPMParams);
	}

// Implementation
	void _DrawText(CDCHandle dc, CPoint ptOffset = CPoint(0, 0))
	{
		COLORREF clr;
		if (m_fsState & CBSTATE_INACTIVE)
			clr = ::GetSysColor(COLOR_GRAYTEXT);
		else if (m_fsState & CBSTATE_ENABLED)
			clr = ::GetSysColor(COLOR_MENUTEXT);
		else
			clr = ::GetSysColor(COLOR_3DSHADOW);
			
		COLORREF clrOld = dc.SetTextColor(clr);

		CRect rcBtn = m_rcBtn + ptOffset;

		if (!(m_fsState & CBSTATE_ENABLED)) {
			// disabled - draw shadow text shifted down and right 1 pixel (unles selected)
			CRect rcDisabled = rcBtn + CPoint(1, 1);
			COLORREF clrOld2 = dc.SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
			dc.DrawText(m_strBtn, -1, rcDisabled, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
			dc.SetTextColor(clrOld2);
		}

		dc.DrawText(m_strBtn, -1, rcBtn, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		dc.SetTextColor(clrOld);
	}
	
	void DrawHot(CDCHandle dc)
	{
		dc.DrawEdge(m_rcBtn, BDR_RAISEDINNER, BF_RECT);
		_DrawText(dc);
	}

	void DrawPressed(CDCHandle dc)
	{
		dc.DrawEdge(m_rcBtn, BDR_SUNKENOUTER, BF_RECT);
		_DrawText(dc, CPoint(1, 1));
	}
};

/////////////////////////////////////////////////////////////////////////////
// CCommandBarCtrl2Base - base class for the Command Bar2 implementation

class CCommandBarCtrl2Base : public CWindow
{
public:
	static bool s_bW2K;  // For animation flag
	static CCommandBarCtrl2Base* s_pCurrentBar;
	static bool s_bStaticInit;
	static HHOOK s_hMsgHook;

	CCommandBarCtrl2Base()
	{
		// init static variables
		if(!s_bStaticInit) {
			CLockStaticDataInit lock;
			if(!s_bStaticInit) {
				// Animation on Win2000 only
				s_bW2K = !AtlIsOldWindows();
				// done
				s_bStaticInit = true;
			}
		}
	}

	virtual bool OnMenuInput(MSG* pMsg) = 0;
};

__declspec(selectany) CCommandBarCtrl2Base* CCommandBarCtrl2Base::s_pCurrentBar = NULL;
__declspec(selectany) bool CCommandBarCtrl2Base::s_bW2K = false;
__declspec(selectany) bool CCommandBarCtrl2Base::s_bStaticInit = false;
__declspec(selectany) HHOOK CCommandBarCtrl2Base::s_hMsgHook = NULL;

/////////////////////////////////////////////////////////////////////////////
// CCommandBarCtrl2 - MTL implementation of Command Bars

template <class T, class TBase = CCommandBarCtrl2Base, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CCommandBarCtrl2Impl :
	public CWindowImpl< T, TBase, TWinTraits >,
	public CTrackMouseLeave<CCommandBarCtrl2Impl>
{
public:
	DECLARE_WND_CLASS_EX(NULL, 0, -1)

// Declarations

// Constants
	enum _CmdBarDrawConstants
	{
		s_kcxTextMargin = 7,
		s_kcyTextMargin = 2
	};

	enum
	{
		_nMaxMenuItemTextLength = 100,
		_chChevronShortcut = _T('/')
	};
	
	enum _TrackingState
	{
		none = 0,
		hotByAlt,
		popup,
		hotByMouse
	};

// Data members
	HMENU m_hMenu;
	CSimpleArray<CCmdBarButton> m_arrBtn;
	_TrackingState m_nTrackingState;

	CPoint m_ptMouse;
	int m_nPopBtn;
	bool m_bLoop;
	bool m_bProcessRightArrow, m_bProcessLeftArrow;
	bool m_bIgnoreAlt;
	bool m_bIgnoreInputMouseMove;

	CContainedWindow m_wndParent;

	CFont m_fontMenu;

	DWORD m_dwExtendedStyle;	// Command Bar2 specific extended styles

// Constructor/destructor
	CCommandBarCtrl2Impl() : 
			m_hMenu(NULL), 
			m_wndParent(this, 1), 
			m_nPopBtn(-1), 
			m_dwExtendedStyle(CBR2_EX_TRANSPARENT | CBR2_EX_SHAREMENU),
			m_bLoop(false),
			m_bProcessRightArrow(false),
			m_bProcessLeftArrow(false),
			m_bIgnoreAlt(false), m_bIgnoreInputMouseMove(false),
			m_nTrackingState(none),
			m_ptMouse(-1, -1)
	{
 	}
 	
	~CCommandBarCtrl2Impl()
	{
		if(m_wndParent.IsWindow())
/*scary!*/			m_wndParent.UnsubclassWindow();

		if(m_hMenu != NULL && (m_dwExtendedStyle & CBR2_EX_SHAREMENU) == 0)
			::DestroyMenu(m_hMenu);
	}
	
// Attributes
	DWORD GetCommandBar2ExtendedStyle() const
	{
		return m_dwExtendedStyle;
	}
	DWORD SetCommandBar2ExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
	{
		DWORD dwPrevStyle = m_dwExtendedStyle;
		if(dwMask == 0)
			m_dwExtendedStyle = dwExtendedStyle;
		else
			m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
		return dwPrevStyle;
	}

	CMenuHandle GetMenu() const
	{
		ATLASSERT(::IsWindow(m_hWnd));
		return m_hMenu;
	}

	int GetButtonCount() const
	{
		return m_arrBtn.GetSize();
	}
	
// Methods
	HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			UINT nID = 0, LPVOID lpCreateParam = NULL)
	{
		return CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
	}

	BOOL LoadMenu(_U_STRINGorID menu)
	{
		ATLASSERT(::IsWindow(m_hWnd));

		if(menu.m_lpstr == NULL)
			return false;

		HMENU hMenu = ::LoadMenu(_Module.GetResourceInstance(), menu.m_lpstr);
		if(hMenu == NULL)
			return false;

		return AttachMenu(hMenu);
	}

	BOOL AttachMenu(HMENU hMenu)
	{
		ATLASSERT(::IsWindow(m_hWnd));
		ATLASSERT(::IsMenu(hMenu));
		if(hMenu != NULL && !::IsMenu(hMenu))
			return false;

		// destroy old menu, if needed, and set new one
		if(m_hMenu != NULL && (m_dwExtendedStyle & CBR2_EX_SHAREMENU) == 0)
			::DestroyMenu(m_hMenu);
		m_hMenu = hMenu;

		// Clear all
		_ClearAll();
		// Add buttons for each menu item
		_AddButtons(m_hMenu);

		Invalidate();
		UpdateWindow();

		return true;
	}

	void EnableButton(int nIndex, bool bEnable = true)
	{
		if (!_IsValidIndex(nIndex))
			return;

		BYTE fsRemove, fsAdd;
		if (bEnable) {
			fsRemove = 0;
			fsAdd = CBSTATE_ENABLED;
		}
		else {
			fsRemove = CBSTATE_ENABLED;
			fsAdd = 0;
		}

		if (m_arrBtn[nIndex].ModifyState(fsRemove, fsAdd)) {
			InvalidateRect(m_arrBtn[nIndex].m_rcBtn);
			UpdateWindow();
		}
	}

	void RefreshBandIdealSize(CReBarCtrl rebar)
	{
		REBARBANDINFO rbBand;
		rbBand.cbSize = sizeof(REBARBANDINFO);
		rbBand.fMask = RBBIM_IDEALSIZE | RBBIM_CHILDSIZE;

		int nIndex = rebar.IdToIndex(GetDlgCtrlID());
		rebar.GetBandInfo(nIndex, &rbBand);

		int nCount = GetButtonCount();
		if (nCount != 0) {
			rbBand.cxIdeal = m_arrBtn[nCount - 1].m_rcBtn.right;
			rbBand.cxMinChild = m_arrBtn[0].m_rcBtn.Width();
		}

		rebar.SetBandInfo(nIndex, &rbBand);
	}

// Message map and handlers
	BEGIN_MSG_MAP(CCommandBarCtrl2Impl)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
		CHAIN_MSG_MAP(CTrackMouseLeave<CCommandBarCtrl2Impl>)
	ALT_MSG_MAP(1)		// Parent window messages
		MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate)
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
#if (_WIN32_IE >= 0x0500)
		NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
#endif
	END_MSG_MAP()

	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		// Let the toolbar initialize itself
		LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
		// get and use system settings
		GetSystemSettings();

		// Parent init
		CWindow wndParent = GetParent();
		CWindow wndTopLevelParent = wndParent.GetTopLevelParent();
		m_wndParent.SubclassWindow(wndTopLevelParent);

		return lRet;
	}

	void _DoPaint(CDCHandle dc, LPCRECT lpRect = NULL)
	{
		CFontHandle fontOld = dc.SelectFont(m_fontMenu.m_hFont);
		int modeOld = dc.SetBkMode(TRANSPARENT);

		for (int i = 0; i < m_arrBtn.GetSize(); ++i) {
			if (lpRect == NULL || MtlIsCrossRect(m_arrBtn[i].m_rcBtn, lpRect)) {
				m_arrBtn[i].Update(dc.m_hDC);
			}
		}

		dc.SelectFont(fontOld);
		dc.SetBkMode(modeOld);
	}

	LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		if (m_dwExtendedStyle & CBR2_EX_TRANSPARENT) {
			bHandled = FALSE;
			return 0;
		}

		RECT rect;
		GetClientRect(&rect);
		::FillRect((HDC)wParam, &rect, (HBRUSH)LongToPtr(COLOR_MENU + 1));

		return 1;	// don't do the default erase
	}

	LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;

		UINT uItem = (UINT) LOWORD(wParam);   // menu item or submenu index 
		UINT fuFlags = (UINT) HIWORD(wParam); // menu flags 
		HMENU hmenu = (HMENU) lParam;          

		if (m_nTrackingState == popup && hmenu != m_hMenu) {// it's not mine
			// if no submenu, ->
			m_bProcessRightArrow = (::GetSubMenu(hmenu, uItem) == NULL || 
				::GetMenuState(hmenu, uItem, MF_BYPOSITION) & (MF_GRAYED | MF_DISABLED));
			// if top leveled menu popping up, <-
			HMENU hSubMenu = ::GetSubMenu(m_hMenu, m_nPopBtn);
			m_bProcessLeftArrow = (hmenu == hSubMenu);
		}

		return 1;
	}

	LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (wParam != NULL)	{
			_DoPaint((HDC)wParam);
		}
		else {
			CPaintDC dc(m_hWnd);
			_DoPaint(dc.m_hDC, &dc.m_ps.rcPaint);
		}

		return 0;
	}

	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
		m_bIgnoreInputMouseMove = false;
		
		int nIndex = _HitTest(pt);
		if (nIndex != -1)
			_DoTrackPopupMenu(nIndex);

		return 0;
	}

// Overrides
	void OnTrackMouseMove(UINT nFlags, CPoint pt)
	{
		int nIndex = _HitTest(pt);
		if (_IsValidIndex(nIndex)) {	
			if (m_nPopBtn == -1 || m_nPopBtn != nIndex) {// if other button
				_UpdateBar(hotByMouse, nIndex);// button made hot with mouse
			}
		}
		else {
			_UpdateBar();
		}
	}

	void OnTrackMouseLeave()
	{
		if (m_nTrackingState != popup) {
			_UpdateBar();
		}
	}

	LRESULT OnParentActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bool bParentActive = (wParam != WA_INACTIVE);

		if (!bParentActive)
			_UpdateBar();
		
		for (int i = 0; i < m_arrBtn.GetSize(); ++i) {
			if (bParentActive)
				m_arrBtn[i].ModifyState(CBSTATE_INACTIVE, 0);
			else
				m_arrBtn[i].ModifyState(0, CBSTATE_INACTIVE);
		}

		Invalidate();
		UpdateWindow();
		bHandled = FALSE;
		return 1;
	}

#if (_WIN32_IE >= 0x0500)
	LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		LPNMREBARCHEVRON lpnm = (LPNMREBARCHEVRON)pnmh;
		if (lpnm->wID != GetDlgCtrlID()) {
			bHandled = FALSE;
			return 1;
		}

		CMenuHandle menu = _PrepareChevronMenu();
		_DisplayChevronMenu(menu, lpnm);
		_CleanupChevronMenu(menu, lpnm);

		return 0;
	}
#endif

// Implementation - Hook proc
	static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
	{
		LPMSG pMsg = (LPMSG)lParam;

		return (nCode == MSGF_MENU && s_pCurrentBar && s_pCurrentBar->OnMenuInput(pMsg))
			? true : ::CallNextHookEx(s_hMsgHook, nCode, wParam, lParam);
	}

	void _CloseMenu()
	{
//		m_wndParent.PostMessage(WM_KEYDOWN, VK_ESCAPE);
		m_wndParent.PostMessage(WM_CANCELMODE);
	}

	virtual bool OnMenuInput(MSG* pMsg)

⌨️ 快捷键说明

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