📄 cmdbar.h
字号:
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 + -