Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Bitmap Menu

4.96/5 (13 votes)
8 Mar 2013CPOL1 min read 45.6K   2.2K  
A simple way to have a bitmap menu without any bitmap resource or ownerdraw

Image 1

Introduction

This article shows how you can use the CMenu::SetMenuItemBitmaps() method to setup a bitmap to any menu item, and all that without a special resource or handle CMenu::DrawItem, CMenu::MeasureItem. Moreover, you can use icons instead of a bitmap resource or image list.

Background

Recently, I needed to put some icons to menu items so the user can easily recognize the associated toolbar commands... I looked up MSDN Help and saw a small sample here... but these methods can accept only bitmap resources, and these resources must be cut off by 13X13 pixels ... I searched on CodeProject for an owner draw menu and found some good ones, but once they tread the owner draw handler, I have problems on the OS style (counting off that I dumped the project with another control).

But almost any project has icon resources (no matter what dimension), and I was thinking, what if I can put icons on menu items using CMenu::SetMenuItemBitmaps? To complete that, I designed an icon to bitmap conversion method like that:

C++
CBitmap* CMainFrame::ConvertIconToBitmap(HICON hIcon)
{
    CDC dc;
    CBitmap bmp;
    CClientDC ClientDC(this);
    dc.CreateCompatibleDC(&ClientDC);
    bmp.CreateCompatibleBitmap(&ClientDC, 13, 13);
    CBitmap* pOldBmp = (CBitmap*)dc.SelectObject(&bmp);
    ::DrawIconEx(dc.GetSafeHdc(), 0, 0, hIcon, 13, 13, 0, (HBRUSH)RGB(255, 255, 255), DI_NORMAL);
    dc.SelectObject(pOldBmp);
    dc.DeleteDC();
    HBITMAP hBitmap = (HBITMAP)::CopyImage((HANDLE)((HBITMAP)bmp), 
			IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);

    return CBitmap::FromHandle(hBitmap);
}

Using the Code

From the method above, you only need to initialize the menu in the OnInitMenuPopup handler, and use CMainFrame::ConvertIconToBitmap to load icons in the menu:

C++
void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
{
    CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

    // TODO: Add your message handler code here

    HICON hIcon = AfxGetApp()->LoadIcon(IDR_TESTMETYPE);
    pPopupMenu->SetMenuItemBitmaps(ID_FILE_NEW,MF_BYCOMMAND,ConvertIconToBitmap(hIcon),NULL);
    ...
    ...
}

Points of Interest

This solution could be a simple alternative to CMenu derived controls. Enjoy it!

History

  • 21st June, 2012: Initial version
  • 24 April 2015: Updated ConvertIconToBitmap method in order to improve the bitmap quality.

License

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