Click here to Skip to main content
11,709,581 members (45,352 online)
Click here to Skip to main content

CMenuXP - The OfficeXP menu (WTL version)

, 19 Mar 2002 CPOL 160.2K 2.7K 40
Rate this:
Please Sign up or sign in to vote.
Ownerdrawn menu with the OfficeXP look (WTL version)
<!-- Download Links --> <!-- Article image -->

Sample Image - MenuXP (WTL).gif

<!-- Add the rest of your HTML here -->

Introduction

This is the WTL version of the Ownerdrawn menu with the Office XP look.
With this version, the menubar is a MS ReBar so I have customized its drawing too.

Implementation

All the interested code is in the CCommandBarCtrlImplXP class :
template <class T, class TBase = CCommandBarCtrlBase, 
          class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CCommandBarCtrlImplXP 
          : public CCommandBarCtrlImpl< T, TBase, TWinTraits >
{
public:
    DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())

// Message map and handlers
    typedef CCommandBarCtrlImplXP< T, TBase, TWinTraits > thisClass;
    typedef CCommandBarCtrlImpl< T, TBase, TWinTraits >   baseClass;
    BEGIN_MSG_MAP(CCommandBarCtrlXP)
        CHAIN_MSG_MAP(baseClass)
    ALT_MSG_MAP(1)      // Parent window messages
        NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
        CHAIN_MSG_MAP_ALT(baseClass,1)
    ALT_MSG_MAP(2)        // MDI client window messages
        CHAIN_MSG_MAP_ALT(baseClass,2)
    ALT_MSG_MAP(3)        // Message hook messages
        CHAIN_MSG_MAP_ALT(baseClass,3)

    END_MSG_MAP()

    LRESULT OnCustomDraw (int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
    {
        TCHAR sClass[128];

        GetClassName (pnmh->hwndFrom, sClass, 128);

        if ( _tcscmp (sClass, _T("WTL_CommandBarXP")) )
        {
            return CDRF_DODEFAULT;
        }
        NMCUSTOMDRAW* pCustomDraw = (NMCUSTOMDRAW*)pnmh;

        if ( pCustomDraw->dwDrawStage == CDDS_PREPAINT )
        {
            // Request prepaint notifications for each item
            return CDRF_NOTIFYITEMDRAW;
        }
        if ( pCustomDraw->dwDrawStage == CDDS_ITEMPREPAINT )
        {
            CDCHandle cDC (pCustomDraw->hdc);
            CRect rc = pCustomDraw->rc;
            TCHAR sBtnText[128];

            ::SendMessage (pnmh->hwndFrom, TB_GETBUTTONTEXT, 
                               pCustomDraw->dwItemSpec, (LPARAM)sBtnText);

            if ( pCustomDraw->uItemState & CDIS_HOT )
            {
                COLORREF crHighLight = ::GetSysColor (COLOR_HIGHLIGHT);
                CPenDC pen (cDC, crHighLight);
                CBrushDC brush (cDC, (pCustomDraw->uItemState & CDIS_SELECTED)? 
                                        HLS_TRANSFORM (crHighLight, +50, -50) : 
                                        HLS_TRANSFORM (crHighLight, +70, -57));

                cDC.Rectangle (rc);
                cDC.SetTextColor ((pCustomDraw->uItemState & CDIS_SELECTED)? 
                                       ::GetSysColor (COLOR_HIGHLIGHTTEXT) : 
                                       RGB(0,0,0));
            }
            else
            {
                cDC.FillSolidRect (rc, HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), 
                                   +20, 0));
                cDC.SetTextColor (::GetSysColor (m_bParentActive ? COLOR_BTNTEXT :
                                                 COLOR_3DSHADOW));
            }
            cDC.SetBkMode (TRANSPARENT);
            cDC.SelectFont ((HFONT)GetStockObject (DEFAULT_GUI_FONT));
            cDC.DrawText (sBtnText, _tcslen (sBtnText), rc, 
                          DT_CENTER|DT_VCENTER|DT_SINGLELINE);

            return CDRF_SKIPDEFAULT;
        }
        bHandled = FALSE;

        return CDRF_DODEFAULT;
    }

#define IMGPADDING 6
#define TEXTPADDING 8

// From <winuser.h>
#define OBM_CHECK 32760

    void DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
        _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
        CDCHandle dc = lpDrawItemStruct->hDC;
        const RECT& rcItem = lpDrawItemStruct->rcItem;
        LPCRECT pRect = &rcItem;
        BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
        BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
        BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
        COLORREF crBackImg = CLR_NONE;
        CDCHandle* pDC = &dc; 

        if ( bSelected )
        {
            COLORREF crHighLight = ::GetSysColor (COLOR_HIGHLIGHT);
            CPenDC pen (*pDC, crHighLight);
            CBrushDC brush (*pDC, crBackImg = bDisabled ? 
                            HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +73, 0) : 
                            HLS_TRANSFORM (crHighLight, +70, -57));

            pDC->Rectangle (pRect);
        }
        else
        {
            CRect rc (pRect);

            rc.right = m_szBitmap.cx+IMGPADDING;
            pDC->FillSolidRect (rc, 
                   crBackImg = HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +20, 0));
            rc.left = rc.right;
            rc.right = pRect->right;
            pDC->FillSolidRect (rc, 
                              HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +75, 0));
        }
        if ( pmd->fType & MFT_SEPARATOR )
        {
            CPenDC pen (*pDC, HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), -18, 0));

            pDC->MoveTo (pRect->left+m_szBitmap.cx+IMGPADDING+TEXTPADDING,  
                         (pRect->top+pRect->bottom)/2);
            pDC->LineTo (pRect->right-1, (pRect->top+pRect->bottom)/2);
        }
        else
        {
            CRect rc (pRect);
            CString sCaption = pmd->lpstrText;
            int nTab = sCaption.Find ('\t');

            if ( nTab >= 0 )
            {
                sCaption = sCaption.Left (nTab);
            }
            pDC->SetTextColor (bDisabled ? HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), 
                                           -18, 0) : ::GetSysColor (COLOR_MENUTEXT));
            pDC->SetBkMode (TRANSPARENT);

            CBoldDC bold (*pDC, (lpDrawItemStruct->itemState & ODS_DEFAULT) != 0);

            rc.left = m_szBitmap.cx+IMGPADDING+TEXTPADDING;
            pDC->DrawText (sCaption, sCaption.GetLength(), rc, 
                           DT_SINGLELINE|DT_VCENTER|DT_LEFT);

            if ( nTab >= 0 )
            {    
                rc.right -= TEXTPADDING+4;
                pDC->DrawText (pmd->lpstrText+nTab+1, _tcslen (pmd->lpstrText+nTab+1), 
                               rc, DT_SINGLELINE|DT_VCENTER|DT_RIGHT);
            }
            if ( bChecked  )
            {
                COLORREF crHighLight = ::GetSysColor (COLOR_HIGHLIGHT);
                CPenDC pen (*pDC, crHighLight);
                CBrushDC brush (*pDC, crBackImg = bDisabled ? 
                              HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), +73, 0) :
                                (bSelected ? HLS_TRANSFORM (crHighLight, +50, -50) : 
                                   HLS_TRANSFORM (crHighLight, +70, -57)));

                pDC->Rectangle (CRect (pRect->left+1, pRect->top+1, 
                                pRect->left+m_szButton.cx-2, pRect->bottom-1));
            }
            if ( m_hImageList != NULL && pmd->iButton >= 0 )
            {
                bool bOver = !bDisabled && bSelected;

                if ( bDisabled || (bSelected && !bChecked) )
                {
                    HICON hIcon = ImageList_ExtractIcon (NULL, m_hImageList, 
                                                         pmd->iButton);
                    CBrush brush;

                    brush.CreateSolidBrush (bOver ? 
                         HLS_TRANSFORM (::GetSysColor (COLOR_HIGHLIGHT), +50, -66) : 
                         HLS_TRANSFORM (::GetSysColor (COLOR_3DFACE), -27, 0));
                    pDC->DrawState (CPoint (pRect->left + ( bOver ? 4 : 3 ), 
                                    rc.top + ( bOver ? 5 : 4 )),
                                    CSize (m_szBitmap.cx, m_szBitmap.cx), hIcon, 
                                    DSS_MONO, brush);
                    DestroyIcon (hIcon);
                }
                if ( !bDisabled )
                {
                    ::ImageList_Draw (m_hImageList, pmd->iButton, pDC->m_hDC,
                                      pRect->left+( (bSelected && !bChecked) ?
                                      2 : 3 ), rc.top+( (bSelected && !bChecked) ? 
                                      3 : 4 ), ILD_TRANSPARENT);
                }
            }
            else if ( bChecked )
            {
                // Draw the check mark
                rc.left  = pRect->left+5;
                rc.right = rc.left + m_szBitmap.cx+IMGPADDING;
                pDC->SetBkColor (crBackImg);
                HBITMAP hBmp = LoadBitmap (NULL, MAKEINTRESOURCE(OBM_CHECK));
                pDC->DrawState (CPoint (rc.left,rc.top+3), CSize(rc.Size()), 
                                hBmp, DSS_NORMAL, (HBRUSH)NULL);
                DeleteObject (hBmp);
            }
    }
    }
};


For the MFC version, have a look here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jean-Michel LE FOL
Web Developer CSC
France France
Jean-Michel LE FOL is a GraphTalk product architect.
GraphTalk is a set of products which cover the whole scope of the development process. GraphTalk is used by the main insurance compagnies over the world.
The development team is currently based in France near Paris.

You may also be interested in...

Comments and Discussions

 
GeneralDemo doesn't work in WTL80 Pin
testano20-Jul-07 6:43
membertestano20-Jul-07 6:43 
NewsTrue color bmp popup menu example [modified] Pin
VC Spark9-Apr-07 22:15
memberVC Spark9-Apr-07 22:15 
Generalwork in Release Mode, but not Debug Mode Pin
gankh8-Jan-06 3:41
membergankh8-Jan-06 3:41 
QuestionHow can this be used in a context menu? Pin
Anna-Jayne Metcalfe31-Aug-04 3:23
memberAnna-Jayne Metcalfe31-Aug-04 3:23 
AnswerRe: How can this be used in a context menu? Pin
Igor Vigdorchik13-Mar-06 7:24
memberIgor Vigdorchik13-Mar-06 7:24 
GeneralRe: How can this be used in a context menu? Pin
Anna-Jayne Metcalfe13-Mar-06 7:59
memberAnna-Jayne Metcalfe13-Mar-06 7:59 
GeneralRe: How can this be used in a context menu? Pin
Igor Vigdorchik13-Mar-06 8:31
memberIgor Vigdorchik13-Mar-06 8:31 
GeneralRe: How can this be used in a context menu? Pin
Anna-Jayne Metcalfe13-Mar-06 8:43
memberAnna-Jayne Metcalfe13-Mar-06 8:43 
GeneralRe: How can this be used in a context menu? Pin
Igor Vigdorchik13-Mar-06 8:54
memberIgor Vigdorchik13-Mar-06 8:54 
Generalthere is a little bug~ Pin
kimdoyoung5-Apr-04 19:46
memberkimdoyoung5-Apr-04 19:46 
GeneralRelease Mode Failure Pin
Ken Hester12-Dec-03 13:29
sussKen Hester12-Dec-03 13:29 
GeneralMenu Appears transparent first time Pin
Bilal Ahmed17-Aug-03 14:07
memberBilal Ahmed17-Aug-03 14:07 
GeneralWTL XP Look in ATL COM Composite Control Pin
Schauhan12-May-03 21:15
memberSchauhan12-May-03 21:15 
QuestionHow to change ccommmandbarctrl's backcolor? Pin
marco.song29-Dec-02 4:59
membermarco.song29-Dec-02 4:59 
GeneralProblem on WTL7 Pin
Petr Pavlik10-May-02 2:03
memberPetr Pavlik10-May-02 2:03 
GeneralRe: Problem on WTL7 Pin
BozoLeClown22-Nov-02 7:28
memberBozoLeClown22-Nov-02 7:28 
GeneralRe: Problem on WTL7 Pin
ErikLindemann31-May-05 0:58
memberErikLindemann31-May-05 0:58 
GeneralDoes not work! Pin
Yazan Diranieh28-Mar-02 1:22
memberYazan Diranieh28-Mar-02 1:22 
GeneralRe: Does not work! Pin
Jean-Michel LE FOL28-Mar-02 3:34
memberJean-Michel LE FOL28-Mar-02 3:34 
GeneralRe: Does not work! Pin
Ramon Casellas28-Mar-02 6:50
memberRamon Casellas28-Mar-02 6:50 
GeneralSample code does not compile Pin
Yazan Diranieh27-Mar-02 0:47
memberYazan Diranieh27-Mar-02 0:47 
GeneralRe: Sample code does not compile Pin
Ramon Casellas27-Mar-02 1:19
memberRamon Casellas27-Mar-02 1:19 
GeneralA Menu is a Window,we can make it flat! Pin
tomer dror20-Mar-02 9:57
membertomer dror20-Mar-02 9:57 
GeneralRe: A Menu is a Window,we can make it flat! Pin
Ramon Casellas20-Mar-02 11:28
memberRamon Casellas20-Mar-02 11:28 
GeneralRe: A Menu is a Window,we can make it flat! Pin
CosmoS2k28-Mar-02 16:27
memberCosmoS2k28-Mar-02 16:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150819.1 | Last Updated 20 Mar 2002
Article Copyright 2002 by Jean-Michel LE FOL
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid