ボタンにアイコンを表示する

ボタンに下図のようにアイコンを表示する方法です。

こちらは、オーナードローとしてボタンを作成し、自分でせっせとボタン を描画することで実現できます。普通のボタンは、ボタンをクリックしたときに、ボタンが へこんだように見えますが、これはWindows がへこんだように影を描いたりしているからなのです。しかし、オーナードローとしてボタンを作成すると、Windows がボタンを描画するのではなく、アプリケーションが自分でボタンを描画しなければなりません。  面倒くさいですが、自由度は高くなります。

ボタンをオーナードローとして作成するためには、CreateWindowEx するときに BS_OWNERDRAW を含めれば OK です。

オーナードローの描画は、WM_DRAWITEM メッセージのハンドラにて行います。下に単純化したサンプルコードを示します。このコードには無効化した状態が入っていなかったり、足りないので必要に応 じて付け足してみてください。

// WM_CREATE のハンドラ
BOOL OnCreate (HWND hwnd, LPCREATESTRUCT lpCreateStruct) {

    g_hButton = CreateWindowEx (
        0,
        TEXT("button"),
        TEXT(""),
        WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
        0, 0, 0, 0,
        hwnd, (HMENU) ID_BUTTON, NULL, NULL );

    ShowWindow ( g_hButton, SW_SHOW );
    return TRUE;
}

// WM_DRAWITEM のハンドラ
void OnDrawItem (HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem) {

    if ( ID_BUTTON != lpDrawItem->CtlID ) {
        return;
    } 

    HDC hDC = lpDrawItem->hDC;

    // ボタンの状態を取得
    BOOL bIsPressed = (lpDrawItem->itemState & ODS_SELECTED);
    BOOL bIsFocused  = (lpDrawItem->itemState & ODS_FOCUS);
    BOOL bIsDisabled = (lpDrawItem->itemState & ODS_DISABLED);
    RECT rectItem = lpDrawItem->rcItem;
    SetBkMode(hDC, TRANSPARENT);
    if (bIsFocused) {
        HBRUSH hBlackBrush = (HBRUSH) GetStockObject (BLACK_BRUSH);
        FrameRect (hDC, &rectItem, hBlackBrush);
        InflateRect (&rectItem, -1, -1);
    }
 
    // ボタンの表面
    COLORREF clrButtonFace = GetSysColor (COLOR_BTNFACE);
    HBRUSH hButtonFaceBrush = CreateSolidBrush( clrButtonFace );
    FillRect (hDC, &rectItem, hButtonFaceBrush);
    DeleteObject (hButtonFaceBrush);

    // 押下されているボタン
    if (bIsPressed) {
        HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
        FrameRect (hDC, &rectItem, brBtnShadow);
        DeleteObject (brBtnShadow);
    }
    else {
        DrawFrameControl (hDC, &rectItem, DFC_BUTTON, DFCS_BUTTONPUSH);
    }

    // フォーカス
    if ( bIsFocused ) {
        RECT rectFocus = rectItem;
        InflateRect (&rectFocus, -3, -3);
        if ( bIsPressed ) {
            OffsetRect ( &rectFocus, 1, 1);
        }
        DrawFocusRect (hDC, &rectFocus);
    }

    // アイコン
    INT cxIcon = 10 + ( bIsPressed ? 1 : 0 );
    INT cyIcon = 8 + ( bIsPressed ? 1 : 0);
    HICON hIcon = LoadIcon ( NULL, IDI_QUESTION);
    ::DrawIcon (hDC, cxIcon, cyIcon, hIcon);

}

サンプルコードのダウンロード [ODButton.zip, makefile 付]

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説