📄 atlctrlxp.h
字号:
// Make flat menu overlap with menu button at its bottom frame line
if( lpParams ) {
lpParams->rcExclude.bottom -= 1; // don't exclude bottom frame
y -= 1; // and move up the menu
}
#ifndef TPM_HORPOSANIMATION
const UINT TPM_HORPOSANIMATION = 0x0400;
const UINT TPM_HORNEGANIMATION = 0x0800;
const UINT TPM_VERPOSANIMATION = 0x1000;
const UINT TPM_VERNEGANIMATION = 0x2000;
#endif // TPM_HORPOSANIMATION
#ifndef TPM_NOANIMATION
const UINT TPM_NOANIMATION = 0x4000;
#endif // TPM_NOANIMATION
OSVERSIONINFO ovi;
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
BOOL bRet = ::GetVersionEx(&ovi);
if( bRet &&
ovi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
ovi.dwMajorVersion <= 4 )
{
// There are no menu-animations on Windows NT 4, so we
// don't tinker with the flags. NT4 might fail otherwise.
// Thanks to Andy Karels for this tip.
}
else {
// We need to turn off animations because they mess up the first menu paint.
// Thanks to Ramon Casellas for this tip.
uFlags |= TPM_NOANIMATION;
uFlags &= ~( TPM_HORPOSANIMATION | TPM_HORNEGANIMATION | TPM_VERPOSANIMATION | TPM_VERNEGANIMATION );
}
// Toggle menu fading/animation mode (Windows2K or later)
#ifndef SPI_GETMENUFADE
const UINT SPI_GETMENUFADE = 0x1012;
const UINT SPI_SETMENUFADE = 0x1013;
#endif // SPI_GETMENUFADE
#ifndef SPI_GETMENUANIMATION
const UINT SPI_GETMENUANIMATION = 0x1002;
const UINT SPI_SETMENUANIMATION = 0x1003;
#endif // SPI_GETMENUANIMATION
#ifndef SPI_GETANIMATION
const UINT SPI_GETANIMATION = 0x0048;
const UINT SPI_SETANIMATION = 0x0049;
#endif // SPI_GETANIMATION
BOOL bMenuFading = FALSE;
BOOL bMenuAnim = FALSE;
if( ovi.dwMajorVersion >= 5 )
{
bRet = ::SystemParametersInfo(SPI_GETMENUFADE, 0, &bMenuFading, 0);
bRet = ::SystemParametersInfo(SPI_GETMENUANIMATION, 0, &bMenuAnim, 0);
bRet = ::SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE);
bRet = ::SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) FALSE, SPIF_SENDWININICHANGE);
}
#ifdef _CMDBAR_EXTRA_TRACE
//ATLTRACE2(atlTraceUI, 0, "CmdBar - DoTrackPopupMenu:, bMenuFading = %s, bMenuAnim = %s\n",
// bMenuFading ? "true" : "false", bMenuAnim ? "true" : "false");
#endif
// Figure out the size of the pressed button
if( !m_bContextMenu ) GetItemRect(m_nPopBtn, &m_rcButton);
CMenuHandle menuPopup = hMenu;
::EnterCriticalSection(&_Module.m_csWindowCreate);
ATLASSERT(s_hCreateHook == NULL);
s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this);
s_hCreateHook = ::SetWindowsHookEx(WH_CBT, MyCreateHookProc, _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);
// These updates are also from the original WTL CommandBar control
// but they actually solves some paint problems with submenus in this
// control as well.
UpdateWindow();
CWindow wndTL = GetTopLevelParent();
wndTL.UpdateWindow();
// Restore menu fade/animation mode (Windows2K or later)
if( ovi.dwMajorVersion >= 5 )
{
bRet = ::SystemParametersInfo(SPI_SETMENUFADE, 0, (LPVOID) bMenuFading, SPIF_SENDWININICHANGE);
bRet = ::SystemParametersInfo(SPI_SETMENUANIMATION, 0, (LPVOID) bMenuAnim, SPIF_SENDWININICHANGE);
}
// 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 = FALSE;
// 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;
}
// Implementation - Hook procs
static LRESULT CALLBACK MyCreateHookProc(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) == 0 ) {
s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu);
// Subclass to a flat-looking menu
CFlatMenuWindow* wnd = new CFlatMenuWindow(m_rcButton.right - m_rcButton.left, m_xpstyle.clrFrame, m_xpstyle.clrBackground, m_xpstyle.clrMenu);
wnd->SubclassWindow(hWndMenu);
wnd->SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_DRAWFRAME);
::SetRectEmpty(&m_rcButton);
}
}
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) == 0 )
{
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;
}
// Implementation - ownerdraw overridables and helpers
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Update colors
_GetSystemSettings();
// Allow WTL Command Bar to set its settings...
bHandled = FALSE;
return 0;
}
// Ownerdrawn menu
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
_MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;
if( (pmd->fType & MFT_SEPARATOR) != 0 ) // separator - is really small
{
lpMeasureItemStruct->itemHeight = 5;
lpMeasureItemStruct->itemWidth = 0;
}
else
{
// ** Removed 'static' as suggested by Ilya Kheifets.
CFont fontBold;
// Compute size of text - use DrawText with DT_CALCRECT
CWindowDC dc = m_hWnd;
HFONT hOldFont;
if( (pmd->fState & MFS_DEFAULT) != 0 ) {
// Need bold version of font
LOGFONT lf;
m_fontMenu.GetLogFont(lf);
lf.lfWeight += 200;
fontBold.CreateFontIndirect(&lf);
ATLASSERT(!fontBold.IsNull());
hOldFont = dc.SelectFont(fontBold);
}
else {
hOldFont = dc.SelectFont(m_fontMenu);
}
RECT rcText = { 0 };
dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
dc.SelectFont(hOldFont);
int cx = rcText.right - rcText.left;
LOGFONT lf;
m_fontMenu.GetLogFont(lf);
int cy = lf.lfHeight;
if( cy < 0 ) cy = -cy;
cy += 10;
// Height of item is the bigger of these two
lpMeasureItemStruct->itemHeight = max(cy, (int) m_szButton.cy + 2);
// 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
}
}
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
_MenuItemData* pmd = (_MenuItemData*) lpDrawItemStruct->itemData;
CDCHandle dc = lpDrawItemStruct->hDC;
const RECT& rcItem = lpDrawItemStruct->rcItem;
bool bSelected = (lpDrawItemStruct->itemState & ODS_SELECTED) != 0;
bool bDisabled = (lpDrawItemStruct->itemState & ODS_GRAYED) != 0;
bool bChecked = (lpDrawItemStruct->itemState & ODS_CHECKED) != 0;
if( LOWORD(lpDrawItemStruct->itemID) == (WORD) -1 ) bSelected = false;
RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect
::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically
int cxButn = m_szButton.cx;
RECT rcIcon = rcItem;
RECT rcText = rcItem;
rcText.left += cxButn + s_kcxGap;
rcIcon.right = rcText.left;
// Draw background
if( !bDisabled && bSelected )
{
CBrush brush;
CPen pen;
brush.CreateSolidBrush(m_xpstyle.clrHighlight);
pen.CreatePen(PS_SOLID, 1, m_xpstyle.clrHighlightBorder);
HPEN hOldPen = dc.SelectPen(pen);
HBRUSH hOldBrush = dc.SelectBrush(brush);
dc.Rectangle(&rcItem);
dc.SelectPen(hOldPen);
dc.SelectBrush(hOldBrush);
}
else
{
CBrush brushIcon;
CBrush brushText;
brushIcon.CreateSolidBrush(m_xpstyle.clrMenu);
brushText.CreateSolidBrush(m_xpstyle.clrBackground);
dc.FillRect(&rcIcon, brushIcon);
dc.FillRect(&rcText, brushText);
}
// Draw item
if( (pmd->fType & MFT_SEPARATOR) != 0 )
{
// Draw separator
CPen pen;
pen.CreatePen(PS_SOLID, 1, m_xpstyle.clrMenu);
HPEN hOldPen = dc.SelectPen(pen);
RECT rc = rcText;
rc.top += (rc.bottom - rc.top) / 2; // vertical center
rc.left += s_kcxTextMargin + 4;
dc.MoveTo(rc.left, rc.top);
dc.LineTo(rc.right, rc.top);
dc.SelectPen(hOldPen);
}
else // Not a separator
{
// Draw icon
int iButton = pmd->iButton;
if( iButton >= 0 ) {
// Calc drawing point
SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
sz.cx /= 2;
sz.cy /= 2;
POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
if( bDisabled ) {
DrawShadowIcon(dc, m_hImageList, point, iButton);
}
else {
if( bSelected ) {
// Draw shadow
if( (m_dwExtendedStyle & CBR_EX_NOWIGGLE) == 0 ) {
point.x++;
point.y++;
DrawShadowIcon(dc, m_hImageList, point, iButton);
point.x -= 2;
point.y -= 2;
}
else {
DrawShadowIcon(dc, m_hImageList, point, iButton);
}
}
// Draw the image
ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
}
}
else {
// No image - look for custom checked/unchecked bitmaps
CMenuItemInfo info;
info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
::GetMenuItemInfo( (HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info );
if( bChecked || info.hbmpUnchecked != NULL ) {
bool bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked);
}
}
// Draw text
COLORREF clrText;
if( bDisabled ) clrText = m_xpstyle.clrGreyText;
else if( bSelected ) clrText = m_xpstyle.clrSelMenuText;
else clrText = m_xpstyle.clrMenuText;
rcText.right -= cxButn;
rcText.left += s_kcxTextMargin;
dc.SetBkMode(TRANSPARENT);
DrawMenuText(dc, rcText, pmd->lpstrText, clrText); // finally!
}
}
void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color) const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -