/***********************************
    オーナードローサンプル
    2002.Jun.25
    K_Yaguchi
************************************/

#include <windows.h>

#define ClassName       "OwnerDrawSample"
#define ICONW           16
#define ICONH           16
#define ICONCOUNT       5

#define IDM_MENU        102


LPCTSTR str[] = {
                    "マイコンピュータ",
                    "ドライブ",
                    "Internet Explorer",
                    "フォルダ",
                    "エクスプローラ"
                };

HINSTANCE   hInst;




/***********************

    選択アイコン描画

************************/
BOOL Draw3DIcon(HDC hdc, RECT rc) {
    HBRUSH hBrush;

//  左辺と上辺
    rc.right = ICONW + 4;
    hBrush = CreateSolidBrush(0xFFFFFF);
    FillRect(hdc, &rc, hBrush);
    DeleteObject(hBrush);

//  右辺と下辺
    rc.left += 1;
    rc.top += 1;
    hBrush = CreateSolidBrush(0x424142);
    FillRect(hdc, &rc, hBrush);
    DeleteObject(hBrush);

//  真ん中は塗りつぶし
    rc.right -= 1;
    rc.bottom -= 1;
    hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
    FillRect(hdc, &rc, hBrush);
    DeleteObject(hBrush);

    return TRUE;
}


/*****************************

    メニューアイコン描画

*****************************/
BOOL DrawMenuIcon(LPDRAWITEMSTRUCT dis) {
    HDC hdc;
    HBITMAP hOldBmp;
    BOOL ret;

    hdc     = CreateCompatibleDC(0);
    hOldBmp = (HBITMAP)SelectObject(hdc, LoadBitmap(hInst, "IDB_BITMAP"));

//  切り抜き
    ret = BitBlt(
            dis->hDC,
            dis->rcItem.left + 2, dis->rcItem.top + 2,
            ICONW, ICONH,
            hdc,
            ICONW * dis->itemData, 0,
            SRCCOPY
        );

    DeleteObject(SelectObject(hdc, hOldBmp));
    DeleteDC(hdc);
    return ret;
}



/**************************************

    オーナードロー用メニュー作成

**************************************/
HMENU CreateOwnerDrawMenu(void) {
    HMENU hMenu;
    int i;

    hMenu = CreatePopupMenu();
    for(i = 0; i < ICONCOUNT; i++)
        AppendMenu(hMenu, MF_OWNERDRAW, IDM_MENU + i, (LPCTSTR)i);

    return hMenu;
}



/*********************************

    メニューアイテム初期処理

**********************************/
BOOL MeasureItem(LPMEASUREITEMSTRUCT mis) {
    HDC hdc;
    SIZE sz;
    HFONT hFont, hOldFont;

    hdc = GetDC(0);

//  メニューのフォント
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);

//  メニューの大きさを計算
    hOldFont = (HFONT)SelectObject(hdc, hFont);
    GetTextExtentPoint32(hdc, str[mis->itemData], lstrlen(str[mis->itemData]), &sz);
    mis->itemHeight = sz.cy + 8;
    mis->itemWidth  = sz.cx + ICONW + 10;

    SelectObject(hdc, hOldFont);
    ReleaseDC(0, hdc);
    return TRUE;
}



/********************************

    メニューアイテムの描画

*********************************/
BOOL DrawItem(LPDRAWITEMSTRUCT dis) {
    HFONT hFont, hOldFont;
    HBRUSH hBrush;
    RECT rc;

//  メニューのフォント
    hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);

    hOldFont = (HFONT)SelectObject(dis->hDC, hFont);
    rc = dis->rcItem;
    if(dis->itemState & ODS_SELECTED) {
//      選択状態
        hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
        SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
        Draw3DIcon(dis->hDC, dis->rcItem);
        rc.left = ICONW + 6;
        FillRect(dis->hDC, &rc, hBrush);    // アイコンを除いた領域を塗りつぶす
    }
    else {
//      非選択状態
        hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
        SetTextColor(dis->hDC, GetSysColor(COLOR_MENUTEXT));
        FillRect(dis->hDC, &rc, hBrush);
    }
    DrawMenuIcon(dis);                     // アイコン描画
    SetBkMode(dis->hDC, TRANSPARENT);   // SetBkColorでもいいけどね
    TextOut(
        dis->hDC,
        dis->rcItem.left + ICONW + 10,
        dis->rcItem.top + 4,
        str[dis->itemData], lstrlen(str[dis->itemData])
    );
    
    DeleteObject(hBrush);
    SelectObject(dis->hDC, hOldFont);
    return TRUE;
}



/******************************

    ウィンドウプロージャ

*******************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    HDC hdc;
    PAINTSTRUCT ps;
    POINT po;
    static HMENU hMenu1;
    static HMENU hMenu2;
    const char txt[] = "右クリックでメニューが出ます";


    switch (msg) {
        case WM_DESTROY:
            DestroyMenu(hMenu1);
            DestroyMenu(hMenu2);
            PostQuitMessage(0);
            break;

        case WM_CREATE:
            hMenu1 = CreateMenu();          // メニュー作成
            hMenu2 = CreateOwnerDrawMenu(); // ポップアップメニュー作成

            AppendMenu(hMenu1, MF_ENABLED | MF_POPUP | MF_STRING, (UINT)hMenu2, "メニュー");    // メニューバーの項目
            SetMenu(hWnd, hMenu1);
            DrawMenuBar(hWnd);
            break;

        case WM_RBUTTONUP:
            po.x = LOWORD(lp);
            po.y = HIWORD(lp);
            ClientToScreen(hWnd, &po);
            TrackPopupMenu(
                hMenu2, TPM_LEFTALIGN | TPM_TOPALIGN,
                po.x, po.y, 0, hWnd, NULL
            );
            break;

        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            SetBkMode(hdc, TRANSPARENT);
            TextOut(hdc, 50, 90, txt, lstrlen(txt));
            EndPaint(hWnd, &ps);
            break;

        case WM_MEASUREITEM:
            MeasureItem((LPMEASUREITEMSTRUCT)lp);   // 初期処理
            return TRUE;

        case WM_DRAWITEM:
            DrawItem((LPDRAWITEMSTRUCT)lp); // 描画
            return TRUE;

        default:
            return DefWindowProc(hWnd, msg, wp, lp);
    }

    return 0;
}


/***************

    メイン

****************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, PSTR lpCmdLine, int nCmdShow) {
    HWND hWnd;
    MSG msg;
    WNDCLASS wc;

    hInst = hInstance;

//  ウィンドウクラス登録
    wc.style            = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc      = WndProc;
    wc.cbClsExtra       = wc.cbWndExtra = 0;
    wc.hInstance        = hInstance;
    wc.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground    = (HBRUSH)COLOR_WINDOW;
    wc.lpszMenuName     = NULL;
    wc.lpszClassName    = ClassName;

    if (!RegisterClass(&wc)) return 0;

//  オーナーウィンドウ
    hWnd = CreateWindowEx(
                WS_EX_CONTROLPARENT,
                ClassName, "オーナードロー",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                CW_USEDEFAULT, CW_USEDEFAULT ,
                320, 260,
                NULL, NULL ,
                hInstance, NULL
            );
    if (hWnd == NULL) return NULL;

//  メッセージループ
    while(GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

//  ウィンドウクラス解除
    UnregisterClass(ClassName, hInstance);
    return msg.wParam;
}

リソースを使う場合のリソースファイルの内容

//////////////////////////////////
//
// Bitmap
//

IDB_BITMAP  BITMAP      "menu.bmp"