Creating Owner Drawn Menu Example

#define WINVER 0x0501
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#define IDM_MENUITEM1 1
#define IDM_MENUITEM2 2
#define IDM_FILE_QUIT 3

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PWSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT("Menu Demonstration");
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClass(&wc);
CreateWindow(wc.lpszClassName, TEXT("Owner drawn menu"),WS_OVERLAPPEDWINDOW | WS_VISIBLE,100, 100, 350, 180, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
//The LPMEASUREITEMSTRUCT structure stores the the dimensions of an owner-drawn control.
LPMEASUREITEMSTRUCT lpmis;
//The LPDRAWITEMSTRUCT structure stores information required to paint an owner-drawn control
LPDRAWITEMSTRUCT lpdis;
HBRUSH bkBrush, oldBrush;
int fileMenuID=0;

switch (uMsg)
{
case WM_CREATE:
{
//Create menu
HMENU Bar = CreateMenu();
HMENU File = CreateMenu();
HMENU Edit = CreateMenu();
HMENU Help = CreateMenu();
AppendMenu(Bar,MF_POPUP | ODS_FOCUS, (UINT_PTR)File, TEXT("File"));
AppendMenu(Bar,MF_POPUP, (UINT_PTR)Edit, TEXT("Edit"));
//create menutitems with ownerdraw attibute
AppendMenu(File,MF_OWNERDRAW|MF_STRING | ODS_FOCUS, IDM_MENUITEM2, TEXT("Item 1"));
AppendMenu(File,MF_OWNERDRAW|MF_STRING,IDM_MENUITEM1, TEXT("Item 2"));
AppendMenu(Edit,MF_STRING, IDM_FILE_QUIT, TEXT("Quit"));
SetMenu(hwnd, Bar);
}
break;
//The WM_MEASUREITEM message is sent to the owner window of an owner-drawn control when the control is created
case WM_MEASUREITEM:
{

lpmis = (PMEASUREITEMSTRUCT) lParam;

//set width and height of fist and second drop down menu item
if (lpmis->itemID==IDM_MENUITEM1)
{
lpmis->itemWidth = 120;
lpmis->itemHeight = 70;
}
if (lpmis->itemID==IDM_MENUITEM2)
{
lpmis->itemWidth = 120;
lpmis->itemHeight = 50;
}
}
return TRUE;

break;
//The WM_DRAWITEM message is sent to the owner window of an owner-drawn control when a visual aspect of that contol has changed.
case WM_DRAWITEM:
{
lpdis=(LPDRAWITEMSTRUCT)lParam;
//detects if the selection status of the menu item has changed. If so draw bounding box and change text colour
if (lpdis->itemState & ODS_SELECTED) {
SetTextColor(lpdis->hDC, RGB(255, 55, 55));
bkBrush=CreateSolidBrush(RGB(0,0,0));
FillRect(lpdis->hDC, &lpdis->rcItem, bkBrush);
}
else {
SetTextColor(lpdis->hDC, RGB(0, 0, 0));
bkBrush=CreateSolidBrush(RGB(255,255,255));
FillRect(lpdis->hDC, &lpdis->rcItem, bkBrush);
}

//set menu item text and appearance
RECT rect;
bkBrush=CreateSolidBrush(RGB(255,255,0));
oldBrush=(HBRUSH)SelectObject(lpdis->hDC,bkBrush);
SetBkColor(lpdis->hDC,RGB(255,255,0));
rect=lpdis->rcItem;
rect.left=rect.left+5;
rect.top=rect.top+3;
Rectangle(lpdis->hDC,lpdis->rcItem.left+2,lpdis->rcItem.top+2,lpdis->rcItem.right-2,lpdis->rcItem.bottom-2);
DrawText(lpdis->hDC, (LPCTSTR)lpdis->itemData, -1, &rect, DT_SINGLELINE|DT_INTERNAL);
SelectObject(lpdis->hDC,oldBrush);

if (lpdis->itemID==IDM_MENUITEM1)
{
//used to set specific draw attributes for menu item 1
}
if (lpdis->itemID==IDM_MENUITEM2)
{
//used to set specific draw attributes for menu item 2
}

DeleteObject(bkBrush);
DeleteObject(oldBrush);
}
return TRUE;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}