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

📄 cmdbar.h

📁 WTL开发的一个写字板程序 ,很有借鉴意义
💻 H
📖 第 1 页 / 共 5 页
字号:
		if(bSelected)
		{
			dc.FillRect(&rcDest, (HBRUSH)LongToPtr((bSelected ? COLOR_MENU : COLOR_3DLIGHT) + 1));
		}
		else
		{
			COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
			COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
			CBrush hbr(CDCHandle::GetHalftoneBrush());
			dc.SetBrushOrg(rcDest.left, rcDest.top);
			dc.FillRect(&rcDest, hbr);
			dc.SetTextColor(crTxt);
			dc.SetBkColor(crBk);
		}
		// draw the check bitmap transparently
		COLORREF crOldBack = dc.SetBkColor(RGB(255, 255, 255));
		COLORREF crOldText = dc.SetTextColor(RGB(0, 0, 0));
		CDC dcTrans;
		// create two memory dcs for the image and the mask
		dcTrans.CreateCompatibleDC(dc);
		// create the mask bitmap	
		CBitmap bitmapTrans;	
		int nWidth = rcDest.right - rcDest.left;
		int nHeight = rcDest.bottom - rcDest.top;	
		bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
		// select the mask bitmap into the appropriate dc
		dcTrans.SelectBitmap(bitmapTrans);
		// build mask based on transparent color	
		dcMem.SetBkColor(m_clrMask);
		dcTrans.SetBkColor(RGB(0, 0, 0));
		dcTrans.SetTextColor(RGB(255, 255, 255));
		dcTrans.BitBlt(0, 0, nWidth, nHeight, dcMem, p.x, p.y, SRCCOPY);
		dc.BitBlt(rcDest.left, rcDest.top, nWidth, nHeight, dcMem, p.x, p.y, SRCINVERT);
		dc.BitBlt(rcDest.left, rcDest.top, nWidth, nHeight, dcTrans, 0, 0, SRCAND);
		dc.BitBlt(rcDest.left, rcDest.top, nWidth, nHeight, dcMem, p.x, p.y, SRCINVERT);
		// restore settings	
		dc.SetBkColor(crOldBack);
		dc.SetTextColor(crOldText);			
		dcMem.SelectBitmap(hBmpOld);		// restore
		// draw pushed-in hilight
		if(rc.right - rc.left > size.cx)
			::InflateRect(&rcDest, 1,1);	// inflate checkmark by one pixel all around
		dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);

		return TRUE;
	}

	void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
	{
		_MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;

		if(pmd->fType & MFT_SEPARATOR)	// separator - use half system height and zero width
		{
			lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU) / 2;
			lpMeasureItemStruct->itemWidth  = 0;
		}
		else
		{
			// == Begin, Ramon Smits 22-04-2000
			if(lpMeasureItemStruct->itemID == SIDEBAR_ID)
			{
				// We only need to return the width of the sidebar to let windows
				// know the width of sidebar. It doesn't need to reserve height
				// because we determine the height ourselfs in the DrawItem method
				lpMeasureItemStruct->itemWidth = SIDEBAR_WIDTH - GetSystemMetrics(SM_CXMENUCHECK);
				lpMeasureItemStruct->itemHeight= 0;
				return;
			}
			// == End

			// compute size of text - use DrawText with DT_CALCRECT
			CWindowDC dc(NULL);
			HFONT hOldFont;
			if(pmd->fState & MFS_DEFAULT)
			{
				// need bold version of font
				LOGFONT lf;
				m_fontMenu.GetLogFont(lf);
				lf.lfWeight += 200;
				CFont fontBold;
				fontBold.CreateFontIndirect(&lf);
				ATLASSERT(fontBold.m_hFont != NULL);
				hOldFont = dc.SelectFont(fontBold);
			}
			else
			{
				hOldFont = dc.SelectFont(m_fontMenu);
			}

			RECT rcText = { 0, 0, 0, 0 };
			dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
			int cx = rcText.right - rcText.left;
			dc.SelectFont(hOldFont);

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

			// height of item is the bigger of these two
			lpMeasureItemStruct->itemHeight = max(cy, m_szButton.cy);

			// width is width of text plus a bunch of stuff
			cx += 2 * s_kcxTextMargin;	// L/R margin for readability
			cx += s_kcxGap;			// space between button and menu text
			cx += 2 * m_szButton.cx;	// button width (L=button; R=empty margin)

			// Windows adds 1 to returned value
			cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1;
			lpMeasureItemStruct->itemWidth = cx;		// done deal
		}
	}

// Implementation - Hook procs
	static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM lParam)
	{
		LRESULT lRet = 0;
		TCHAR szClassName[7];

		if(nCode == HCBT_CREATEWND)
		{
			HWND hWndMenu = (HWND)wParam;
#ifdef _CMDBAR_EXTRA_TRACE
			ATLTRACE2(atlTraceUI, 0, "CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n", hWndMenu);
#endif

			::GetClassName(hWndMenu, szClassName, 7);
			if(!lstrcmp(_T("#32768"), szClassName))
				s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu);
		}
		else if(nCode == HCBT_DESTROYWND)
		{
			HWND hWndMenu = (HWND)wParam;
#ifdef _CMDBAR_EXTRA_TRACE
			ATLTRACE2(atlTraceUI, 0, "CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n", hWndMenu);
#endif

			::GetClassName(hWndMenu, szClassName, 7);
			if(!lstrcmp(_T("#32768"), szClassName))
			{
				ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent());
				s_pCurrentBar->m_stackMenuWnd.Pop();
			}
		}
		else if(nCode < 0)
		{
			lRet = ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam);
		}
		return lRet;
	}

	static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
	{
		LPMSG pMsg = (LPMSG)lParam;

		if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message != GetGetBarMessage() && pMsg->message != WM_FORWARDMSG)
		{
			CCommandBarCtrlBase* pCmdBar = NULL;
			HWND hWnd = pMsg->hwnd;
			DWORD dwPID = 0;
			while(pCmdBar == NULL && hWnd != NULL)
			{
				pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hWnd, GetGetBarMessage(), (WPARAM)&dwPID, 0L);
				hWnd = ::GetParent(hWnd);
			}

			if(pCmdBar != NULL && dwPID == GetCurrentProcessId())
			{
				pCmdBar->m_hWndHook = pMsg->hwnd;
				ATLASSERT(pCmdBar->IsCommandBarBase());

				if(::IsWindow(pCmdBar->m_hWnd))
					pCmdBar->SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
				else
					ATLTRACE2(atlTraceUI, 0, "CmdBar - Hook skipping message, can't find command bar!\n");
			}
		}

		LRESULT lRet = 0;
		ATLASSERT(s_pmapMsgHook != NULL);
		if(s_pmapMsgHook != NULL)
		{
			DWORD dwThreadID = ::GetCurrentThreadId();
			_MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
			if(pData != NULL)
			{
				lRet = ::CallNextHookEx(pData->hMsgHook, nCode, wParam, lParam);
			}
		}
		return lRet;
	}

// Implementation
	void DoPopupMenu(int nIndex, bool bAnimate)
	{
#ifdef _CMDBAR_EXTRA_TRACE
		ATLTRACE2(atlTraceUI, 0, "CmdBar - DoPopupMenu, bAnimate = %s\n", bAnimate ? "true" : "false");
#endif

		// get popup menu and it's position
		RECT rect;
		GetItemRect(nIndex, &rect);
		ClientToScreen(&rect);
		TPMPARAMS TPMParams;
		TPMParams.cbSize = sizeof(TPMPARAMS);
		TPMParams.rcExclude = rect;
		HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex);

		// get button ID
		TBBUTTON tbb;
		GetButton(nIndex, &tbb);
		int nCmdID = tbb.idCommand;

		m_nPopBtn = nIndex;	// remember current button's index

		// press button and display popup menu
		PressButton(nCmdID, TRUE);
		SetHotItem(nCmdID);
		DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN |
			(s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0), rect.left, rect.bottom, &TPMParams);
		PressButton(nCmdID, FALSE);
		if(::GetFocus() != m_hWnd)
			SetHotItem(-1);

		m_nPopBtn = -1;		// restore

		// eat next message if click is on the same button
		MSG msg;
		if(::PeekMessage(&msg, m_hWnd, NULL, NULL, PM_NOREMOVE))
		{
			if(msg.message == WM_LBUTTONDOWN && ::PtInRect(&rect, msg.pt))
				::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
		}

		// check if another popup menu should be displayed
		if(m_nNextPopBtn != -1)
		{
			PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFFF);
			if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem)
				PostMessage(WM_KEYDOWN, VK_DOWN, 0);
			m_nNextPopBtn = -1;
		}
		else
		{
			m_bContextMenu = false;
			// If user didn't hit escape, give focus back
			if(!m_bEscapePressed)
				GiveFocusBack();
			else
			{
				SetHotItem(nCmdID);
				SendMessage(TB_SETANCHORHIGHLIGHT, TRUE, 0);
			}
		}
	}

	BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL)
	{
		CMenuHandle menuPopup = hMenu;

		::EnterCriticalSection(&_Module.m_csWindowCreate);

		ATLASSERT(s_hCreateHook == NULL);

		s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this);

		s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, _Module.GetModuleInstance(), GetCurrentThreadId());
		ATLASSERT(s_hCreateHook != NULL);

		m_bPopupItem = false;
		m_bMenuActive = true;

		BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams);
		m_bMenuActive = false;

		::UnhookWindowsHookEx(s_hCreateHook);

		s_hCreateHook = NULL;
		s_pCurrentBar = NULL;

		::LeaveCriticalSection(&_Module.m_csWindowCreate);

		// cleanup - convert menus back to original state
#ifdef _CMDBAR_EXTRA_TRACE
		ATLTRACE2(atlTraceUI, 0, "CmdBar - TrackPopupMenu - cleanup\n");
#endif

		ATLASSERT(m_stackMenuWnd.GetSize() == 0);

		UpdateWindow();
		CWindow wndTL = GetTopLevelParent();
		wndTL.UpdateWindow();

		// restore the menu items to the previous state for all menus that were converted
		if(m_bImagesVisible)
		{
			HMENU hMenuSav;
			while((hMenuSav = m_stackMenuHandle.Pop()) != NULL)
			{
				menuPopup = hMenuSav;
				BOOL bRet;
				// restore state and delete menu item data
				for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
				{
					CMenuItemInfo mii;
					mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;
					bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
					ATLASSERT(bRet);

					_MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
					if(pMI != NULL && pMI->IsCmdBarMenuItem())
					{
						mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
						mii.fType = pMI->fType;
						mii.fState = pMI->fState;
						mii.dwTypeData = pMI->lpstrText;
						mii.cch = lstrlen(pMI->lpstrText);
						mii.dwItemData = NULL;

						bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
						// this one triggers WM_MEASUREITEM
						menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText);
						ATLASSERT(bRet);

						delete [] pMI->lpstrText;
						delete pMI;
					}
				}
			}
		}
		return bTrackRet;
	}

	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);
				AddStrings(_T("NS\0"));	// for proper item height
				AutoSize();
			}
		}
	}

// Implementation - alternate focus mode support
	void TakeFocus()
	{
		if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == NULL)
			m_hWndFocus = ::GetFocus();
		SetFocus();
	}

	void GiveFocusBack()
	{
		if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWindow(m_hWndFocus))
			::SetFocus(m_hWndFocus);
		else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_wndParent.IsWindow())
			m_wndParent.SetFocus();
		m_hWndFocus = NULL;
		SendMessage(TB_SETANCHORHIGHLIGHT, 0, 0);
	}

// Implementation - internal message helpers
	static UINT GetAutoPopupMessage()
	{
		static UINT uAutoPopupMessage = 0;
		if(uAutoPopupMessage == 0)
		{
			::EnterCriticalSection(&_Module.m_csStaticDataInit);
			if(uAutoPopupMessage == 0)
				uAutoPopupMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalAutoPopupMsg"));
			::LeaveCriticalSection(&_Module.m_csStaticDataInit);
		}
		ATLASSERT(uAutoPopupMessage != 0);
		return uAutoPopupMessage;
	}

	static UINT GetGetBarMessage()
	{
		static UINT uGetBarMessage = 0;
		if(uGetBarMessage == 0)
		{
			::EnterCriticalSection(&_Module.m_csStaticDataInit);
			if(uGetBarMessage == 0)
				uGetBarMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalGetBarMsg"));
			::LeaveCriticalSection(&_Module.m_csStaticDataInit);
		}
		ATLASSERT(uGetBarMessage != 0);
		return uGetBarMessage;
	}
};


class RamonSmit_CCommandBarCtrl : public RamonSmit_CCommandBarCtrlImpl<CCommandBarCtrl>
{
public:
	DECLARE_WND_SUPERCLASS(_T("RamonSmit_CommandBar"), GetWndClassName())
};


#endif //_CmdBar_d1d0a48a_662a_4619_9da7_d547a97e0acc

⌨️ 快捷键说明

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