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

📄 menucontrol.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
字号:

#pragma once

class CMenuControl : public CWindowImpl<CMenuControl>
{
public:
// Data members
	CMDIWindow m_wndMDIClient;
	CWindow m_wndCmdSent;

	CRect m_arrCaption[3];
	BOOL m_bPushed;
	int m_nTracking;
	bool m_bVisible;
	bool m_bOnlyCloseButton;

	bool m_bSpecialRestore;
	int m_nCmdIDRestore;

// Constants
	enum _MDIMenuControlConstants
	{
		s_kcxGap = 2
	};

// Constructor
	CMenuControl() :
		m_bPushed(false),
		m_nTracking(-1),
		m_bVisible(false),
		m_bOnlyCloseButton(false),
		m_bSpecialRestore(false), m_nCmdIDRestore(0)
	{
	}

	~CMenuControl()
	{
	}

	void InstallAsMDICmdBar(HWND hWndCmdBar, HWND hWndMDIClient, bool bOnlyCloseButton)
	{
		ATLASSERT(::IsWindow(hWndMDIClient));

		// calc init layout
		CRect rc;
		::GetClientRect(hWndCmdBar, &rc);
		_UpdateLayout(rc.Size());

		MTLVERIFY(SubclassWindow(hWndCmdBar));

		m_wndMDIClient.m_hWnd = hWndMDIClient;
		m_wndMDIClient.m_hWndMDIClient = hWndMDIClient;

		m_bOnlyCloseButton = bOnlyCloseButton;
	}

	void InstallAsStandard(HWND hWndDrawn,
		HWND hWndCmdSent, bool bSpecialRestore = false, int nID = 0, bool bOnlyCloseButton = false)
	{
		// calc init layout
		CRect rc;
		::GetClientRect(hWndDrawn, &rc);
		_UpdateLayout(rc.Size());

		MTLVERIFY(SubclassWindow(hWndDrawn));

		m_wndCmdSent = hWndCmdSent;
		m_bSpecialRestore = bSpecialRestore;
		m_nCmdIDRestore = nID;

		m_bOnlyCloseButton = bOnlyCloseButton;
	}

	void Uninstall()
	{
		if (IsWindow())
			UnsubclassWindow();
	}

	void UpdateMDIMenuControl()
	{
		bool bPrev = m_bVisible;
		m_bVisible = _IsChildWindowMaximized();
		if (bPrev != m_bVisible)
			_InvalidateControls();
	}

	void ShowMDIMenuControl(bool bOn)
	{
		m_bVisible = bOn;
		_InvalidateControls();
	}

// Message map and handlers
	BEGIN_MSG_MAP(CMenuControl)
	// for drawn window
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
		MSG_WM_LBUTTONDOWN(OnLButtonDown)
		MSG_WM_MOUSEMOVE(OnMouseMove)
		MSG_WM_LBUTTONUP(OnLButtonUp)
	END_MSG_MAP()

	void OnLButtonDown(UINT nFlags, CPoint pt)
	{
		SetMsgHandled(_OnMouseMsg(WM_LBUTTONDOWN, nFlags, pt));
	}

	void OnMouseMove(UINT nFlags, CPoint pt)
	{
		SetMsgHandled(_OnMouseMsg(WM_MOUSEMOVE, nFlags, pt));
	}

	void OnLButtonUp(UINT nFlags, CPoint pt)
	{
		SetMsgHandled(_OnMouseMsg(WM_LBUTTONUP, nFlags, pt));
	}

	LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
//		ATLTRACE2(atlTraceUser, 4, _T("CMDIMenuControl::OnPaint\n"));
		if (!m_bVisible) {
			bHandled = FALSE;
			return 0;
		}

		CRect rc;
		GetUpdateRect(&rc, FALSE);

		LRESULT lRet = DefWindowProc();

		if (_HitTest(rc) != -1) {
			CClientDC dc(m_hWnd);
			_DoPaint(dc.m_hDC);
		}

		return lRet; 
	}

	void OnWindowPosChanged(LPWINDOWPOS lpwndpos)
	{
		ATLTRACE2(atlTraceUser, 4, _T("CMDIMenuControl::OnWindowPosChanged (%d, %d)\n"), lpwndpos->cx, lpwndpos->cy);
		SetMsgHandled(FALSE);

		if (!m_bVisible) {
			CSize size(lpwndpos->cx, lpwndpos->cy);
			_UpdateLayout(size);			
			return;
		}

		// erase controls on previous position
		_InvalidateControls();

		CSize size(lpwndpos->cx, lpwndpos->cy);
		_UpdateLayout(size);

		CClientDC dc(m_hWnd);
		_DoPaint(dc.m_hDC);
	}

// Implementation
	BOOL _OnMouseMsg(UINT msg, UINT nFlags, CPoint pt)
	{
		if (!m_bVisible)
			return FALSE;

		if (msg == WM_LBUTTONDOWN) {
			//LTRACE(_T("    WM_LBUTTONDOWN\n"));
			m_nTracking = _HitTest(pt);
			if (m_nTracking >= 0) {
				CClientDC dc(m_hWnd);
				_DrawFrameControl(dc.m_hDC, m_nTracking, TRUE);
				m_bPushed = TRUE;
				SetCapture();				  // grab mouse input
				return TRUE;
			}
		}
		else if ((msg == WM_MOUSEMOVE) && m_nTracking >= 0) {
			// mouse moved, and I am tracking: possibly draw button up/down
			BOOL bOldDown = m_bPushed;
			m_bPushed = m_arrCaption[m_nTracking].PtInRect(pt);
			if (bOldDown != m_bPushed) {
				// up/down state changed: need to redraw button
				CClientDC dc(m_hWnd);
				_DrawFrameControl(dc.m_hDC, m_nTracking, m_bPushed);
			}
			return TRUE; // handled
		}
		else if (msg == WM_LBUTTONUP && m_nTracking >= 0) {
			// user released the mouse and I am tracking: do button command
			::ReleaseCapture(); // let go the mouse
			if (m_bPushed) {
				// if button was down when released: draw button up, and do system cmd
				CClientDC dc(m_hWnd);
				_DrawFrameControl(dc.m_hDC, m_nTracking, FALSE);
				SendCommand(m_nTracking);
			}
			m_nTracking = -1; // stop tracking
			return TRUE;	  // handled (eat)
		}

		return FALSE;
	}

	void SendCommand(int nTracking)
	{
		if (m_wndMDIClient.m_hWnd) {// MDI mode
			CWindow wnd = m_wndMDIClient.MDIGetActive();
			if (wnd.m_hWnd) {
				static int syscmd[3] = { /*SC_MOUSEMENU,*/ SC_CLOSE, SC_RESTORE, SC_MINIMIZE };
				// SendMessage occur access violation!
				wnd.PostMessage(WM_SYSCOMMAND, syscmd[m_nTracking]);
			}
		}
		else {
			if (m_wndCmdSent.m_hWnd) {
				static int syscmd[3] = { /*SC_MOUSEMENU,*/ SC_CLOSE, SC_RESTORE, SC_MINIMIZE };
				// SendMessage occur access violation!
				if (m_bSpecialRestore && nTracking == 1)
					m_wndCmdSent.PostMessage(WM_COMMAND, m_nCmdIDRestore);
				else 
					m_wndCmdSent.PostMessage(WM_SYSCOMMAND, syscmd[nTracking]);
			}
		}
	}

	void _DoPaint(CDCHandle hDC)
	{
		if (!m_bVisible)
			return;

		for (int i = 0; i < 3; ++i) {
			_DrawFrameControl(hDC, i, FALSE);
		}	
	}

	void _UpdateLayout(const CSize& sizeWnd)
	{
//		ATLTRACE2(atlTraceUser, 4, _T("CMDIMenuControl::_UpdateLayout : size(%d, %d)\n"), size.cx, size.cy);		

		CSize size = sizeWnd;
		CSize sizeCaption = _GetCaptionSize();

		int cxCaption = sizeCaption.cx;
		int cyCaption = sizeCaption.cy;

		if (cyCaption > size.cy) {//over
			cyCaption = size.cy;
			size.cy += s_kcxGap;// fix
		}

		CRect rcCaption;
		rcCaption.right = size.cx;
		rcCaption.bottom = size.cy - s_kcxGap;
		rcCaption.left = rcCaption.right - cxCaption;
		rcCaption.top = rcCaption.bottom - cyCaption;

		m_arrCaption[0] = rcCaption;

		rcCaption -= CPoint(cxCaption + s_kcxGap, 0);
		m_arrCaption[1] = rcCaption;

		rcCaption -= CPoint(cxCaption, 0);
		m_arrCaption[2] = rcCaption;
	}

	void _InvalidateControls()
	{
		if (m_bOnlyCloseButton) {// invalidate only close button
			InvalidateRect(m_arrCaption[0]);
			return;
		}

		for (int i = 0; i < 3; ++i) {
			InvalidateRect(m_arrCaption[i]);
		}
	}

	void _DrawFrameControl(CDCHandle hDC, int nIndex, BOOL bPushed)
	{
		if (m_bOnlyCloseButton) {// do only 0(close button)
			if (nIndex == 1 || nIndex == 2)
				return;
		}

		// draw frame controls
		CRect& rc = m_arrCaption[nIndex];
		const UINT dfcs[3] = { DFCS_CAPTIONCLOSE, DFCS_CAPTIONRESTORE, DFCS_CAPTIONMIN };
		UINT uState = dfcs[nIndex];
		if (bPushed)
			uState |= DFCS_PUSHED;
		hDC.DrawFrameControl(rc, DFC_CAPTION, uState);
	}

	int _HitTest(CPoint point)
	{
		if (m_bOnlyCloseButton) {// only check 0
			if (m_arrCaption[0].PtInRect(point))
				return 0;
			else
				return -1;
		}

		for (int i = 0; i < 3; ++i) {
			if (m_arrCaption[i].PtInRect(point))
				return i;
		}

		return -1;
	}

	int _HitTest(const CRect& rect)
	{
		if (m_bOnlyCloseButton) {// only check 0
			CRect rcCross = m_arrCaption[0] & rect;
			if (!rcCross.IsRectEmpty())
				return 0;
			else
				return -1;
		}

		for (int i = 0; i < 3; ++i) {
			CRect rcCross = m_arrCaption[i] & rect;
			if (!rcCross.IsRectEmpty())
				return i;
		}

		return -1;
	}

	CSize _GetCaptionSize()
	{
		int cxCaption = ::GetSystemMetrics(SM_CXSIZE) - s_kcxGap;
		int cyCaption = ::GetSystemMetrics(SM_CYSIZE) - s_kcxGap*2;

//		int cyMenu = ::GetSystemMetrics(SM_CYMENU) - s_kcxGap*2;
//		int cyButton = 16;

//		int cyMax = min(cyMenu, cyButton);

//		if (cyCaption > cyMax) {
//			cyCaption = cyMax;
//			cxCaption = cyCaption;
//		}

		return CSize(cxCaption, cyCaption);
	}

/*
	void OnPaintMDIClient(HDC hDC)
	{
//		ATLTRACE2(atlTraceUser, 4, _T("CMDIMenuControl::OnPaintMDIClient\n"));
		SetMsgHandled(FALSE);

		UpdateMDIMenuControl();
	}
*/

	bool _IsChildWindowMaximized()
	{
		BOOL bMaximized = FALSE;
		m_wndMDIClient.MDIGetActive(&bMaximized);
		return (bMaximized == TRUE);
	}
};

⌨️ 快捷键说明

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