Здесь представлен класс CTMenu, наследованный от CMenu, который позволяет сделать видимость заголовка в сплывающем меню путём изменения шрифта верхнего пункта.
Чтобы использовать CTMenu, достаточно просто добавить в проект файлы TMENU.H и TMENU.CPP, заменить в исходнике CMenu на CTMenu, и вызвать AddMenuTitle с нужным текстом заголовка. В обычном обработчике OnContextMenu возможно потребуется использовать Attach/Detach. Например, если у Вас есть загруженный ресурс меню в CMenu* pContextMenu; то необходимо проделать следующее: CTMenu titlemenu; titlemenu.Attach(*pContextMenu); titlemenu.AddMenuTitle("SomeTitle"); //работаем с меню... titlemenu.Detach(); И наконец два главных файла: ----------------------------------- начало TMENU.H #if !defined(AFX_TMENU_H__3C1D1728_241C_11D3_9CE5_0060973674E2__INCLUDED_) #define AFX_TMENU_H__3C1D1728_241C_11D3_9CE5_0060973674E2__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // TMenu.h : header file // ///////////////////////////////////////////////////////////////////////////// // CTMenu window class CTMenu : public CMenu { // Construction public: CTMenu(); // Attributes protected: CFont m_Font; CString m_strTitle; // Operations public: void AddMenuTitle(LPCTSTR lpszTitle); protected: HFONT CreatePopupMenuTitleFont(); // Implementation public: virtual ~CTMenu(); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMIS); virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS); }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional // declarations immediately before the previous line. #endif // !defined(AFX_TMENU_H__3C1D1728_241C_11D3_9CE5_0060973674E2__INCLUDED_) ------------------------------------------- конец TMENU.H ------------------------------------------- начало TMENU.CPP // TMenu.cpp : implementation file // #include "stdafx.h" #include "TMenu.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CTMenu CTMenu::CTMenu() { HFONT hfont = CreatePopupMenuTitleFont(); ASSERT(hfont); m_Font.Attach(hfont); } CTMenu::~CTMenu() { m_Font.DeleteObject(); } ///////////////////////////////////////////////////////////////////////////// // CTMenu message handlers HFONT CTMenu::CreatePopupMenuTitleFont() { // start by getting the stock menu font HFONT hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); if (hfont) { LOGFONT lf; //get the complete LOGFONT describing this font if (GetObject(hfont, sizeof(LOGFONT), &lf)) { lf.lfWeight = FW_BOLD; // set the weight to bold // recreate this font with just the weight changed return ::CreateFontIndirect(&lf); } } return NULL; } // // Эта функция добавляет заголовок в меню // void CTMenu::AddMenuTitle(LPCTSTR lpszTitle) { // вставляем пустой пункт в начало меню, который будет являться заголовком // обратите внимание, что этот пункт нельзя выбрать, однако он не серый m_strTitle=CString(lpszTitle); InsertMenu(0, MF_BYPOSITION | MF_OWNERDRAW | MF_STRING | MF_DISABLED, 0); } void CTMenu::MeasureItem(LPMEASUREITEMSTRUCT mi) { // получаем dc экрана чтобы использовать его для получения размеров CDC dc; dc.Attach(::GetDC(NULL)); // выбираем шрифт заголовка HFONT hfontOld = (HFONT)SelectObject(dc.m_hDC, (HFONT)m_Font); // вычисляем размер заголовка CSize size = dc.GetTextExtent(m_strTitle); // возвращаем шрифт обратно ::SelectObject(dc.m_hDC, hfontOld); // добавляем левый отступ для пункта меню size.cx += GetSystemMetrics(SM_CXMENUCHECK)+8; //Возвращаем ширину и высоту //+ включая пробел для рамки const int nBorderSize = 2; mi->itemWidth = size.cx + nBorderSize; mi->itemHeight = size.cy + nBorderSize; } void CTMenu::DrawItem(LPDRAWITEMSTRUCT di) { //Рисуем фон и утопленный прямоугольник... COLORREF crOldBk = ::SetBkColor(di->hDC, ::GetSysColor(COLOR_INACTIVECAPTION)); ::ExtTextOut(di->hDC, 0, 0, ETO_OPAQUE, &di->rcItem, NULL, 0, NULL); ::DrawEdge(di->hDC, &di->rcItem, BDR_SUNKENINNER, BF_RECT); int modeOld = ::SetBkMode(di->hDC, TRANSPARENT); COLORREF crOld = ::SetTextColor(di->hDC, GetSysColor(COLOR_CAPTIONTEXT)); // выбираем шрифт в dc HFONT hfontOld = (HFONT)SelectObject(di->hDC, (HFONT)m_Font); // добавляем к меню отступы di->rcItem.left += GetSystemMetrics(SM_CXMENUCHECK)+8; // рисуем текст с левым выравниванием и отцентрированный по вертикали ::DrawText(di->hDC, m_strTitle, -1, &di->rcItem, DT_SINGLELINE|DT_VCENTER|DT_LEFT); //Восстанавливаем шрифт и цвета... ::SelectObject(di->hDC, hfontOld); ::SetBkMode(di->hDC, modeOld); ::SetBkColor(di->hDC, crOldBk); ::SetTextColor(di->hDC, crOld); } ------------------------------------------- конец TMENU.CPP
|