Click here to Skip to main content
13,398,451 members (34,967 online)
Click here to Skip to main content
Add your own
alternative version


47 bookmarked
Posted 16 May 2004

How to create owner drawn menus - Step by Step

, 16 May 2004
Rate this:
Please Sign up or sign in to vote.
This tutorial explains how to create owner drawn menus step by step

Sample Image


This is just a tutorial on how to create Step-by-Step your own - owner drawn - menu!


Step 1

First of all, you should make your Own class. I called it COwnMenu. The base class should be CMenu. Then create a struct, that could look like this:

struct MenuObject { 
HICON m_hIcon; 
CString m_strCaption; 

Then, you have to declare an instance of COwnMenu to your main class (for example CMainFrame or CTestDlg). It is also recommended that you declare two vectors, that hold the addresses of every item that you've allocated!

COwnMenu menu;
std::vector<DWORD> deleteItem;
std::vector<DWORD> deleteMenu;

Step 2

The next thing you've got to do is to create a function that changes all Items of your menu to MF_OWNERDRAW. I've created a recursive function to step through really every menu item... All addresses of the allocated items are saved in deleteItem, if it's an item :) and in deleteMenu, if it's a menu :)

The function could look like this:

void COwnMenu::MakeItemsOwnDraw(BOOL bFirst)
 int iMaxItems = GetMenuItemCount();
 for(int i = 0; i < iMaxItems; i++)
   MenuObject* pObject = new MenuObject;
   pObject->m_hIcon = NULL;
   GetMenuString(i, pObject->m_strCaption, MF_BYPOSITION);
   ZeroMemory(&mInfo, sizeof(MENUITEMINFO));
   UINT uID = mInfo.wID; 
   /*I dont use GetMenuItemID because 
     it doesn't return 0/-1 when it's a Popup
      (so the MSDN is wrong)*/
              uID, (char*)pObject);
     COwnMenu* pSubMenu = new COwnMenu;


First of all, you step through all menu items. Then, you create a new MenuObject and add its address to deleteItem. If you have an Icon, you could change pObject->m_hIcon to its address. The next thing you do is getting the Caption of the Item and save it to pObject->m_strCaption. Then you change the style of the menu to MF_OWNERDRAW. What you have got to understand is, that the last parameter of ModifyMenu is a pointer to your pObject which we've got to use in DrawItem and MeasureItem later!

The next thing you do is checking whether the item is a popup item, which means that it has subitems. If it is one, you create a new COwnMenu, add its address to deleteMenu, so we can clear the whole memory when we destroy our program. After we've done this, we do the whole function for this item.

So - now you can tell me, what's difficult to understand :)

Step 3

Now, you have to add these two functions:

void COwnMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  CRect rectFull(lpDrawItemStruct->rcItem); 
  CRect rectIcon(rectFull.left,,rectFull.left+20,;
  CRect rectText(rectIcon.right,,rectFull.right,rectFull.bottom);
  COLORREF IconRectLeft = COLORREF(RGB(246,245,244));
  COLORREF IconRectRight = COLORREF(RGB(0,209,201));
  COLORREF TextRect = COLORREF(RGB(249, 248, 247));
  CRect rectBorder = rectFull;
  rectBorder.right -= 1;
  CRect rectFill = rectBorder;
  rectFill.left += 1;
  rectFill.right -= 1; += 1;
  rectFill.bottom -= 1;
    ZeroMemory(&rectIcon, sizeof(CRect));
    rectText = rectFull;
    TextRect = GetSysColor(COLOR_BTNFACE);// COLORREF(RGB(192,192,192));

  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    rectIcon, 246,245,244,213,209,201);

  if ((lpDrawItemStruct->itemState & ODS_SELECTED) &&
   (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
    TextRect = COLORREF(RGB(182, 189, 210));
    pDC->FillSolidRect(&rectBorder, COLORREF(RGB(10, 36, 106)));
    pDC->FillSolidRect(&rectFill, TextRect);

  rectText.left += 5; += 1;
  rectText.bottom += 1;

void COwnMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
 lpMeasureItemStruct->itemHeight = 20;
 lpMeasureItemStruct->itemWidth = 

In MeasureItem, you have to tell the menu how big your item is! I think, that's really easy to understand :).

In DrawItem, you check whether the item is selected. If it is, we draw this cool XP Style Rect. I have made a cool function called FillFluentRect that draws cool special effects to our Iconplace ;). It looks like this:

void COwnMenu::FillFluentRect(HDC hDC, RECT rect, 
  byte r1, byte g1, byte b1, byte r2, byte g2, byte b2)
  int iWidth = rect.right - rect.left;
  int iHeight = rect.bottom -;
  short rDif = r2 - r1;
  short gDif = g2 - g1;
  short bDif = b2 - b1;
  for(int i = 0; i < iWidth; i++)
    byte rCur, gCur, bCur;
    rCur = r1 + (short)(float)(((float)rDif/(float)iWidth)*(float)i);
    gCur = g1 + (short)(float)(((float)gDif/(float)iWidth)*(float)i);
    bCur = b1 + (short)(float)(((float)bDif/(float)iWidth)*(float)i);
    for(int y = 0; y < iHeight; y++)
      SetPixel(hDC, rect.left + i, + y,
    RGB(rCur, gCur, bCur));

I think, I don't have to explain anything here.

When you want to draw an icon or bitmap in DrawItem, you just draw it into the Icon rect with BitBlt...if anybody has a problem with doing this - feel free to ask :) ...but I think it's not that difficult!

Step 4

The next thing is clearing the memory when we end our program, it's not very difficult to look at this:

  for(int i = 0; i < deleteItem.size(); i++)
    delete ((MenuObject*)deleteItem[i]);
    for(int i = 0; i < deleteMenu.size(); i++)
      delete ((COwnMenu*)deleteMenu[i]);

Step 5

The next thing is activating our menu :) It can either be done in CDialog::OnInitDialog() or in CMainFrame::OnCreate(). It could look like this:


Additional Information

If you want your menu to have flat borders, then you’ve got to set a WindowsHook, and in the WindowProc, you have got to identify whether the window is your menu or not…. if you don’t know how this works, have a look at the CMenuXP example.

The End

Now, we've wasn't really hard to understand...was it? I hope I could help some of you.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Kevin Stumpf
Germany Germany
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionStill existing error ,i have fixed it Pin
mftime28-Jul-14 7:16
membermftime28-Jul-14 7:16 
SuggestionError in funtion "MakeItemsOwnDraw" Pin
mftime27-Jul-14 22:04
membermftime27-Jul-14 22:04 
GeneralMy vote of 4 Pin
meirs849-Apr-12 1:40
membermeirs849-Apr-12 1:40 
GeneralAssertion failure Pin
emmmatty126-Aug-09 8:08
memberemmmatty126-Aug-09 8:08 
GeneralBold font... Pin
alfa_aquila31-Mar-08 22:40
memberalfa_aquila31-Mar-08 22:40 
QuestionWhat exactly does this accomplish? Pin
SonicMouser28-Dec-06 15:52
memberSonicMouser28-Dec-06 15:52 
QuestionError 'IDR_MENU' : undeclared identifier Pin
kiranin25-Apr-06 23:10
memberkiranin25-Apr-06 23:10 
AnswerRe: Error 'IDR_MENU' : undeclared identifier Pin
Christian Graus27-Apr-06 17:46
staffChristian Graus27-Apr-06 17:46 
Generalthanks Pin
Max Santos28-Jul-05 11:55
memberMax Santos28-Jul-05 11:55 
GeneralBeginner Question Pin
magsah200021-Jan-05 9:29
membermagsah200021-Jan-05 9:29 
GeneralA Error Pin
Orxorand3-Nov-04 0:17
memberOrxorand3-Nov-04 0:17 
GeneralAn error in the code Pin
MiaoMing2-Aug-04 23:32
memberMiaoMing2-Aug-04 23:32 
GeneralColouring the menu bar Pin
Alex Evans20-Jun-04 16:01
memberAlex Evans20-Jun-04 16:01 
QuestionSeparators and Checked menus??? Pin
I can't remeber my registeration name20-May-04 19:26
memberI can't remeber my registeration name20-May-04 19:26 
AnswerRe: Separators and Checked menus??? Pin
Renato Czar Tome21-Jun-04 19:13
memberRenato Czar Tome21-Jun-04 19:13 
GeneralType safety Pin
Nathan Holt at CCEI19-May-04 6:08
memberNathan Holt at CCEI19-May-04 6:08 
Generalseems like.. Pin
T1TAN18-May-04 1:19
memberT1TAN18-May-04 1:19 
GeneralGood.. Pin
Snyp17-May-04 18:13
memberSnyp17-May-04 18:13 
GeneralRe: Good.. Pin
Kevin Stumpf18-May-04 5:01
memberKevin Stumpf18-May-04 5:01 

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

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

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180216.1 | Last Updated 17 May 2004
Article Copyright 2004 by Kevin Stumpf
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid