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

📄 mtlctrlw.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 2 页
字号:
	{
		int nMsg = pMsg->message;
		CPoint pt = pMsg->lParam;
		ScreenToClient(&pt);

		switch (nMsg) {
		case WM_MOUSEMOVE:
			if (pt != m_ptMouse && !m_bIgnoreInputMouseMove) {
				m_bIgnoreInputMouseMove = false;
				int nIndex = _HitTest(pt);
				if (_IsValidIndex(nIndex) && nIndex != m_nPopBtn) {
					// defferent button clicked
//					ATLTRACE(_T("defferent button clicked\n"));
					_CloseMenu();
					_UpdateBar();							// clean up
					m_nPopBtn = nIndex;
					m_bLoop = true;							// continue loop
				}
				m_ptMouse = pt;
			}
			break;

		case WM_LBUTTONDOWN:	{
			int nIndex = _HitTest(pt);
			if (nIndex != -1 && nIndex == m_nPopBtn) {
				// same button clicked
				_CloseMenu();
				_UpdateBar(hotByMouse, m_nPopBtn);
				m_bLoop = false;						// out of loop
				return true;							// eat it!
			}
								}
			break;

		case WM_KEYDOWN:	{
			TCHAR vKey = pMsg->wParam;
			if ((vKey == VK_LEFT  && m_bProcessLeftArrow) ||
				(vKey == VK_RIGHT && m_bProcessRightArrow)) {
				// no submenu
				int nNewIndex = _GetNextOrPrevButton(m_nPopBtn, vKey==VK_LEFT);
				_CloseMenu();
				_UpdateBar();
				m_nPopBtn = nNewIndex;
				m_bLoop = true;							// continue loop			
				return true;							// eat it!
			}
							}
			break;

		case WM_SYSKEYDOWN:
	//		LTRACE(_T("    m_bIgnore = true\n"));
			m_bIgnoreAlt = true;					// next SysKeyUp will be ignored
			break;
		}
		

		return false;	// pass along...
	}

	bool _IsAltKeyDown(MSG* pMsg)
	{
		bool bAlt = HIWORD(pMsg->lParam) & KF_ALTDOWN;
		bool bExt = HIWORD(pMsg->lParam) & 0x0100;
		return bAlt && !bExt;
	}

	BOOL PreTranslateMessagePrevVer(MSG* pMsg)
	{
		if (!m_hWnd)
			return FALSE;

		UINT nMsg = pMsg->message;
		if (WM_LBUTTONDOWN <= nMsg && nMsg <= WM_MOUSELAST) {
			if (pMsg->hwnd != m_hWnd && m_nTrackingState > 0) {
				// clicked outside
				_UpdateBar();
			}
		}
		else if (nMsg == WM_SYSKEYDOWN || nMsg == WM_SYSKEYUP || nMsg == WM_KEYDOWN) {
			bool bAlt = _IsAltKeyDown(pMsg);	// Alt key pressed?
			TCHAR vkey = pMsg->wParam;			// + X key
			if (vkey == VK_MENU ||
				(vkey == VK_F10 && !((GetKeyState(VK_SHIFT) & 0x80000000) ||
				                   (GetKeyState(VK_CONTROL) & 0x80000000) || bAlt))) {
				// only alt key pressed
				if (nMsg == WM_SYSKEYUP) {
					switch (m_nTrackingState) {
					case hotByMouse:	// NOTE. the mouse hook send WM_MOUSEMOVE even if mouse not moving...
						m_bIgnoreInputMouseMove = true;
//						break;			// do nothing
					case none:
						if (m_bIgnoreAlt) {
							m_bIgnoreAlt = false;
							break;
						}
						_UpdateBar(hotByAlt, 0);
						break;
					case hotByAlt:
						_UpdateBar();
						break;
					}
				}
				return true;
			}
			else if ((nMsg == WM_SYSKEYDOWN || nMsg == WM_KEYDOWN)) {
				if (m_nTrackingState == hotByAlt) {
					switch (vkey) {
					case VK_LEFT:
					case VK_RIGHT: {
						int nNewIndex  = _GetNextOrPrevButton(m_nPopBtn, vkey == VK_LEFT);
						_UpdateBar(hotByAlt, nNewIndex);
						return true;
								   }
					case VK_SPACE:
					case VK_UP:
					case VK_DOWN:
						_DoTrackPopupMenu(m_nPopBtn);
						return true;		

					case VK_ESCAPE:
						_UpdateBar();
						return true;
					}
				}	

				// Alt + X pressed
				if ((bAlt || m_nTrackingState == hotByAlt) && Mtl_istalnum(vkey)) {
					int nIndex;
					if (_MapAccessKey(vkey, nIndex)) {
						_UpdateBar();
						_DoTrackPopupMenu(nIndex);
						return true;		// eat it!
					}
					else if (m_nTrackingState == hotByAlt && !bAlt) {
	//					MessageBeep(0);		// if you want
						return true;
					}
				}	

				if (m_nTrackingState > 0) {	// unknown key
					if (m_nTrackingState != hotByMouse) {	// if tracked with mouse, don't update bar
						_UpdateBar();
					}
				}
			}
		}

		return FALSE;	// pass along...
	}

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		if (m_hWnd == NULL)
			return FALSE;

		int nVirtKey = pMsg->wParam;
		UINT message = pMsg->message;

		if (message == WM_SYSKEYUP && nVirtKey == VK_MENU) {			// just alt key up
			switch (m_nTrackingState) {
			case hotByMouse:	// NOTE. the mouse hook send WM_MOUSEMOVE even if mouse not moving...
				m_bIgnoreInputMouseMove = true;
				// break;			// do nothing
			case none:
				if (m_bIgnoreAlt) {
					m_bIgnoreAlt = false;
					break;
				}
				_UpdateBar(hotByAlt, 0);
				break;
			case hotByAlt:
				_UpdateBar();
				break;
			}

			return TRUE; // eat it
		}
		else if (message == WM_KEYDOWN && m_nTrackingState == hotByAlt) {// alt key tracking
			switch (nVirtKey) {
			case VK_LEFT:
			case VK_RIGHT: {
				int nNewIndex  = _GetNextOrPrevButton(m_nPopBtn, nVirtKey == VK_LEFT);
				_UpdateBar(hotByAlt, nNewIndex);
				return TRUE;
						   }
			case VK_RETURN:
			case VK_UP:
			case VK_DOWN:
				_DoTrackPopupMenu(m_nPopBtn);
				return TRUE;

			case VK_ESCAPE:
				_UpdateBar();
				return TRUE;
			}
		}	
		else if (pMsg->message == WM_SYSKEYDOWN) {	// access key
			if (nVirtKey == VK_MENU || nVirtKey == VK_SHIFT)
				return FALSE;
	
			// Alt + X pressed
			if (Mtl_istalnum(nVirtKey)) {
				int nIndex;
				if (_MapAccessKey(nVirtKey, nIndex)) {
					_UpdateBar();
					_DoTrackPopupMenu(nIndex);
					return TRUE;		// eat it!
				}
			}

			// unknown access key
			if (m_nTrackingState != hotByMouse) {
				_UpdateBar();
			}
		}

		return FALSE;	// pass along...
	}

// Implementation
	void _DoTrackPopupMenu(int nIndex)
	{
		ATLASSERT(_IsValidIndex(nIndex));

		m_nPopBtn = nIndex;
		m_bLoop = true;

		while (m_bLoop) {
//			UpdateWindow();// force to repaint when button hidden by other window
			_UpdateBar(popup, m_nPopBtn);
	
			// install hook
			ATLASSERT(s_pCurrentBar == NULL);
			s_pCurrentBar = this;
			ATLASSERT(s_hMsgHook == NULL);

			m_bLoop = false;
			s_hMsgHook = ::SetWindowsHookEx(WH_MSGFILTER, MessageHookProc, NULL, ::GetCurrentThreadId());// m_bLoop may become true

			// popup!!
			m_nTrackingState = popup;
			m_wndParent.SendMessage(WM_MENUSELECT, MAKEWPARAM(m_nPopBtn, MF_POPUP), (LPARAM)m_hMenu);// for help message line
			ATLASSERT(_IsValidIndex(m_nPopBtn));
			m_arrBtn[m_nPopBtn].TrackPopup(m_hWnd, m_wndParent, s_bW2K);

			// uninstall hook
			::UnhookWindowsHookEx(s_hMsgHook);
			s_hMsgHook = NULL;
			s_pCurrentBar = NULL;
		}

		_UpdateBar();
	}


	void _UpdateBar(_TrackingState nState = none, int nNewPopBtn = -1)
	{
		if (m_nTrackingState == hotByMouse)	
			m_bIgnoreAlt = false;// if prev state is hotByMouse, always should be false!

		m_nTrackingState = nState;

		// clean up
		if (_IsValidIndex(m_nPopBtn)) {
			m_arrBtn[m_nPopBtn].ModifyState(CBSTATE_HOT | CBSTATE_PRESSED, 0);
			InvalidateRect(m_arrBtn[m_nPopBtn].m_rcBtn);
			UpdateWindow();
		}
		m_nPopBtn = -1;

		if (nState != none) {
			ATLASSERT(_IsValidIndex(nNewPopBtn));
			m_nPopBtn = nNewPopBtn;
			CCmdBarButton& cbbtn = m_arrBtn[nNewPopBtn];

			if (nState == hotByAlt || nState == hotByMouse) {
				cbbtn.ModifyState(CBSTATE_PRESSED, CBSTATE_HOT);
				InvalidateRect(cbbtn.m_rcBtn);
				UpdateWindow();
			}
			else if (nState == popup) {
				cbbtn.ModifyState(CBSTATE_HOT, CBSTATE_PRESSED);
				InvalidateRect(cbbtn.m_rcBtn);
				UpdateWindow();
			}
		}
		else {
			// must be default parameter
			ATLASSERT(nNewPopBtn == -1);
		}

		m_bProcessRightArrow = m_bProcessLeftArrow = true;
	}

	bool _MapAccessKey(TCHAR cAccessKey, int& nIndex)
	{
		for (int i = 0; i < m_arrBtn.GetSize(); ++i) {
			// fixing point
			TCHAR cKey = m_arrBtn[i].m_cAccessKey;
			if (Mtl_tolower(cKey)/*_totupper(cKey)*/ == Mtl_tolower(cAccessKey) &&
				m_arrBtn[i].m_fsState & CBSTATE_ENABLED) {
				nIndex = i;
				return true;
			}
		}
		return false;
	}

	int _HitTest(CPoint point)
	{
		CRect rc;
		GetClientRect(&rc);
		if (!rc.PtInRect(point))
			return -1;

		if (m_nTrackingState == popup) {
			CPoint ptScreen = point;
			ClientToScreen(&ptScreen);
			if (::WindowFromPoint(ptScreen) != m_hWnd) // the puzzle figured out!
				return -1;
		}

		for (int i = 0; i < m_arrBtn.GetSize(); ++i) {
			if (m_arrBtn[i].m_rcBtn.PtInRect(point) &&
				m_arrBtn[i].m_fsState & CBSTATE_ENABLED) {
				return i;
			}
		}

		return -1;
	}

	int _GetNextOrPrevButton(int nIndex, BOOL bPrev)
	{
		int nCount = m_arrBtn.GetSize();
		if (bPrev) {				// <-
			--nIndex;
			if (nIndex < 0)
				nIndex = nCount - 1;
		}
		else {						// ->
			++nIndex;
			if (nIndex >= nCount)
				nIndex = 0;
		}

		if ( (m_arrBtn[nIndex].m_fsState & CBSTATE_HIDDEN) ||
			 !(m_arrBtn[nIndex].m_fsState & CBSTATE_ENABLED)) {
			return _GetNextOrPrevButton(nIndex, bPrev);
		}

		return nIndex;
	}

	bool _IsValidIndex(int nIndex)
	{
		if (0 <= nIndex && nIndex < m_arrBtn.GetSize())
			return true;
		else
			return false;
	}
	
	void _ClearAll()
	{
		m_arrBtn.RemoveAll();
	}

	void _AddButtons(HMENU hMenu)
	{
		ATLASSERT(::IsMenu(hMenu));
		int nItems = ::GetMenuItemCount(hMenu);

		T* pT = static_cast<T*>(this);
		TCHAR szString[pT->_nMaxMenuItemTextLength];
		int cxOffset = 0;
		for(int i = 0; i < nItems; ++i) {
			CMenuItemInfo mii;
			mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
			mii.fType = MFT_STRING;
			mii.dwTypeData = szString;
			mii.cch = pT->_nMaxMenuItemTextLength;
			BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, true, &mii);
			ATLASSERT(bRet);
			// If we have more than the buffer, we assume we have bitmaps bits
			if (::lstrlen(szString) > pT->_nMaxMenuItemTextLength - 1) {
				mii.fType = MFT_BITMAP;
				::SetMenuItemInfo(m_hMenu, i, true, &mii);
				szString[0] = 0;
			}

			// NOTE: Command Bar2 currently supports only drop-down menu items
			ATLASSERT(mii.hSubMenu != NULL);
			BYTE fsState = (BYTE)(((mii.fState & MFS_DISABLED) == 0) ? CBSTATE_ENABLED : 0);
			CCmdBarButton cbbtn(fsState, szString, mii.hSubMenu);
			cbbtn.m_rcBtn = _MeasureButton(szString) + CPoint(cxOffset, 0);
			cxOffset = cxOffset + cbbtn.m_rcBtn.Width();
			m_arrBtn.Add(cbbtn);
//			ATLTRACE(_T("cxOffset : %d\n"), cxOffset);
		}

		MoveWindow(0, 0, cxOffset, m_arrBtn[0].m_rcBtn.Height());
	}

	CRect _MeasureButton(const CString& strText)
	{
		// compute size of text - use DrawText with DT_CALCRECT
		int cx = MtlComputeWidthOfText(strText, m_fontMenu);

		LOGFONT lf;
		m_fontMenu.GetLogFont(lf);
		int cy = lf.lfHeight;
		if(cy < 0)
			cy = -cy;
		cy += 2 * s_kcyTextMargin;

		// height of item is the bigger of these two
		cy = MtlMax(cy, ::GetSystemMetrics(SM_CYMENU) - 1);

		// width is width of text plus a bunch of stuff
		cx += 2 * s_kcxTextMargin;	// L/R margin for readability
		
//		ATLTRACE(_T("(cx, cy) = (%d, %d)\n"), cx, cy);
		return CRect(0, 0, cx, cy);
	}

	CMenuHandle _PrepareChevronMenu()
	{
		CMenuHandle menuCmdBar(m_hMenu);

		// build a menu from hidden items
		CMenuHandle menu;
		BOOL bRet = menu.CreatePopupMenu();
		ATLASSERT(bRet);
		RECT rcClient;
		bRet = GetClientRect(&rcClient);
		ATLASSERT(bRet);

		for (int i = 0; i < m_arrBtn.GetSize(); ++i) {
			CCmdBarButton cbb = m_arrBtn[i];
			bool bEnabled = ((cbb.m_fsState & CBSTATE_ENABLED) != 0);
			if (cbb.m_rcBtn.right > rcClient.right) {
				TCHAR szBuff[100];
				CMenuItemInfo mii;
				mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
				mii.dwTypeData = szBuff;
				mii.cch = sizeof(szBuff) / sizeof(TCHAR);
				bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
				ATLASSERT(bRet);
				// Note: CmdBar currently supports only drop-down items
				ATLASSERT(::IsMenu(mii.hSubMenu));
				bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
				ATLASSERT(bRet);
			}
		}

		if (menu.GetMenuItemCount() == 0) {	// no hidden buttons after all
			menu.DestroyMenu();
			return NULL;
		}

		return menu;
	}

#if (_WIN32_IE >= 0x0500)
	void _DisplayChevronMenu(CMenuHandle menu, LPNMREBARCHEVRON lpnm)
	{
		// convert chevron rect to screen coordinates
		CWindow wndFrom = lpnm->hdr.hwndFrom;
		RECT rc = lpnm->rc;
		wndFrom.ClientToScreen(&rc);
		// set up flags and rect
		UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
		TPMPARAMS TPMParams;
		TPMParams.cbSize = sizeof(TPMPARAMS);
		TPMParams.rcExclude = rc;
		::TrackPopupMenuEx(menu.m_hMenu, uMenuFlags, rc.left, rc.bottom, m_wndParent, &TPMParams);
	}

	void _CleanupChevronMenu(CMenuHandle menu, LPNMREBARCHEVRON lpnm)
	{
		// if menu is from a command bar, detach submenus so they are not destroyed
		for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
			menu.RemoveMenu(i, MF_BYPOSITION);

		// destroy menu
		menu.DestroyMenu();
		// convert chevron rect to screen coordinates
		CWindow wndFrom = lpnm->hdr.hwndFrom;
		RECT rc = lpnm->rc;
		wndFrom.ClientToScreen(&rc);
		// eat next message if click is on the same button
		MtlEatNextLButtonDownOnChevron(m_wndParent, rc);
	}
#endif 

	void GetSystemSettings()
	{
		// refresh our font
		NONCLIENTMETRICS info;
		info.cbSize = sizeof(info);
		::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
		LOGFONT logfont;
		memset(&logfont, 0, sizeof(LOGFONT));
		if(m_fontMenu.m_hFont != NULL)
			m_fontMenu.GetLogFont(logfont);
		if(logfont.lfHeight != info.lfMenuFont.lfHeight ||
		   logfont.lfWidth != info.lfMenuFont.lfWidth ||
		   logfont.lfEscapement != info.lfMenuFont.lfEscapement ||
		   logfont.lfOrientation != info.lfMenuFont.lfOrientation ||
		   logfont.lfWeight != info.lfMenuFont.lfWeight ||
		   logfont.lfItalic != info.lfMenuFont.lfItalic ||
		   logfont.lfUnderline != info.lfMenuFont.lfUnderline ||
		   logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut ||
		   logfont.lfCharSet != info.lfMenuFont.lfCharSet ||
		   logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision ||
		   logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision ||
		   logfont.lfQuality != info.lfMenuFont.lfQuality ||
		   logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily ||
		   lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0)
		{
			HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont);
			ATLASSERT(hFontMenu != NULL);
			if(hFontMenu != NULL)
			{
				if(m_fontMenu.m_hFont != NULL)
					m_fontMenu.DeleteObject();
				m_fontMenu.Attach(hFontMenu);
				SetFont(m_fontMenu);
			}
		}
	}
};

class CCommandBarCtrl2 : public CCommandBarCtrl2Impl<CCommandBarCtrl2>
{
public:
	DECLARE_WND_CLASS_EX(_T("MTL_CommandBar2"), NULL, COLOR_BTNFACE)
};

#ifdef __ATLCTRLW_H__
class CCoolMenuManager
{
public:
	WTL::CCommandBarCtrl m_CmdBar;

	BOOL Install(HWND hWnd)
	{
		return m_CmdBar.AttachToWindow(hWnd);
	}

	BOOL LoadImages(int* __firstID, int* __lastID,
		UINT nImageBmpID, int cx, int cy, COLORREF clrMask, UINT nFlags = ILC_COLOR8)
	{
		return MtlCmdBarLoadImages(m_CmdBar, __firstID, __lastID, nImageBmpID, cx, cy, clrMask, nFlags);
	}

	void Validate(bool bOn)
	{
		m_CmdBar.SetImagesVisible(bOn);
	}
};
#endif

////////////////////////////////////////////////////////////////////////////
} //namespace MTL

#endif // __MTLCTRLW_H__

⌨️ 快捷键说明

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