Re: CMenu + COwnerDraw is it possible?

"Konstantin Mironovich" <[email protected]> Tue, 25 Mar 2014 09:21:48 +0400
Newsgroups gmane.comp.windows.wtl
Organization ixbt.com
Message-ID <23760D6F7851445388C8994C845B806E@KLM64>
Hi Igor,

thanks for the reply.
actually I've seen your article some time ago. as well as many other works 
at codeproject, codeguru, etc..
your approach uses member object m_menuEdit with predefined menu.

I've found a bit  simpler solution for my needs:

LRESULT OnTreeItemRClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
  POINT pt; ::GetCursorPos(&pt);

  CTitleMenu menu;
  menu.CreatePopupMenu();
  menu.AddMenuTitle(_T("Select new action"));
  menu.AppendMenu(MFT_STRING, ID_APP_ABOUT, _T("Action about"));
  menu.AppendMenu(MFT_STRING, ID_FILE_OPEN, _T("Action open"));
  menu.AppendMenu(MFT_STRING, ID_APP_EXIT, _T("Action exit"));
  menu.TrackPopupMenu(TPM_CENTERALIGN, pt.x, pt.y, GetParent());
  return 0;
}
// implementation
class CTitleMenu
  : public ATL::CWindowImpl<CTitleMenu>
  , public COwnerDraw<CTitleMenu>
  , public CMenu
{
protected:
  typedef ATL::CWindowImpl<CTitleMenu> baseClass;
  static const int GAP = 8;

public:
  ~CTitleMenu() { baseClass::UnsubclassWindow(); }

  // overridden to provide proper initialization
  BOOL TrackPopupMenu(UINT nFlags, int x, int y, HWND hWnd, LPCRECT lpRect = 
NULL)
  {
    baseClass::SubclassWindow(hWnd);
    m_font = WTL::AtlCreateBoldFont((HFONT)::SendMessage(hWnd, WM_GETFONT, 
0, 0));
    return CMenu::TrackPopupMenu(nFlags, x, y, hWnd, lpRect);
  }
  void AddMenuTitle(LPCTSTR title)
  {
    m_title = title;
    InsertMenu(0, MF_BYPOSITION | MFT_SEPARATOR);
    InsertMenu(0, MF_BYPOSITION | MFT_OWNERDRAW | MFT_STRING | MF_DISABLED);
  }

  BEGIN_MSG_MAP(CTitleMenu)
    CHAIN_MSG_MAP(COwnerDraw<CTitleMenu>)
    DEFAULT_REFLECTION_HANDLER()
  END_MSG_MAP()

  void DrawItem(LPDRAWITEMSTRUCT pdis)
  {
    if (m_font)
    {
      CDCHandle dc(pdis->hDC);
      dc.FillRect(&pdis->rcItem, COLOR_ACTIVECAPTION);
      // save
      int mode = dc.SetBkMode(TRANSPARENT);
      COLORREF clr = dc.SetTextColor(::GetSysColor(COLOR_MENUTEXT));
      HFONT font = dc.SelectFont(m_font);
      pdis->rcItem.left += ::GetSystemMetrics(SM_CXMENUCHECK) + GAP;;
      // draw the text left aligned and vertically centered
      dc.DrawText(m_title, -1, &pdis->rcItem, DT_SINGLELINE | DT_VCENTER);
      dc.SelectFont(font);
      // restore
      dc.SetBkMode(mode);
      dc.SetTextColor(clr);
    }
  }
  void MeasureItem(LPMEASUREITEMSTRUCT pdis)
  {
    if (m_font && (pdis->CtlType == ODT_MENU))
    {
      CClientDC dc(NULL);
      HFONT font = dc.SelectFont(m_font);
      SIZE size;
      dc.GetTextExtent(m_title, -1, &size);
      dc.SelectFont(font);
      size.cx += ::GetSystemMetrics(SM_CXMENUCHECK) + GAP;;
      pdis->itemWidth = size.cx;
      pdis->itemHeight = ::GetSystemMetrics(SM_CYMENU);
    }
  }

protected:
  CString m_title;
  WTL::CFont m_font; // bold font
};


-km

  ----- Original Message ----- 
  From: Igor Vigdorchik
  To: [email protected]
  Sent: Tuesday, March 25, 2014 4:23 AM
  Subject: Re: [wtl] CMenu + COwnerDraw is it possible?




  Konstantin,


  Please take a look at this article
  http://www.codeproject.com/Articles/13406/Owner-drawn-context-menu-in-WTL


  Regards,
  Igor



------------------------------------------------------------------------------
  From: Konstantin Mironovich <[email protected]>
  To: [email protected]
  Sent: Monday, March 24, 2014 8:33 AM
  Subject: [wtl] CMenu + COwnerDraw is it possible?




  Hi folks,

  I need to create an owner drawn context menu object on stack and do not 
have
  a solid idea how to redirect WM_OWNERDRAW(...) messages from parent window
  to the object.
  maybe to create some kind of proxy window and subclass it?
  this proxy could contain CMenu-based object and do all the work needed..

  any ideas?

  thanks

  -km