Last Updated 2011/04/06
Programming Tips Visual C++ MFC CButton  索 引 
ボタンにビットマップ表示
2003/04/08

ボタンにビットマップを表示する.

ビットマップのリソース ID  IDC_BITMAP_1
                           IDC_BITMAP_2

class CMyButton : public CButton
{
public:
    CMyButton();
    virtual void DrawItem(LPDRAWITEMSTRUCT pDrawItemStruct);

private:
    CBitmap m_bitmap1;
    CBitmap m_bitmap2;

    static const bool DrawBitmap(CDC& dc, CBitmap& bitmap, const CRect& rectPosition, DWORD dwRop = SRCCOPY);
};


CMyButton::CMyButton()
{
    VERIFY(m_bitmap1.LoadBitmap(IDC_BITMAP_1));
    VERIFY(m_bitmap2.LoadBitmap(IDC_BITMAP_2));
}

void CMyButton::DrawItem(LPDRAWITEMSTRUCT pDrawItemStruct)
{
    ASSERT_POINTER(pDrawItemStruct, DRAWITEMSTRUCT);
    ASSERT(pDrawItemStruct->CtlType == ODT_BUTTON);

    CDC dc;
    if( dc.Attach(pDrawItemStruct->hDC) ) {
        CRect rect(pDrawItemStruct->rcItem);
        int nState = DFCS_BUTTONPUSH;
        if( (pDrawItemStruct->itemState & ODS_SELECTED) != 0 ) nState |= DFCS_PUSHED;
        if( (pDrawItemStruct->itemState & ODS_DISABLED) != 0 ) nState |= DFCS_INACTIVE;
        dc.DrawFrameControl(&rect, DFC_BUTTON, nState);

        // (pDrawItemStruct->itemState & ODS_SELECTED) や
        // (pDrawItemStruct->itemState & ODS_DISABLED) や
        // (pDrawItemStruct->itemState & ODS_FOCUS) の状況に応じ
        // たビットマップを選択する例 (ここでは ODS_SELECTED のみ)
        CBitmap& bitmap = ((pDrawItemStruct->itemState & ODS_SELECTED) != 0) ? m_bitmap1 : m_bitmap2;

        // dc に対して (CreateCompatibleDC,BitBlt 又は
        // StretchBlt等を使って) pDrawItemStruct->rcItem の真ん
        // 中に其のビットマップを描画する例
        DrawBitmap(dc, bitmap, rect);
        // ついでに...
        if( (pDrawItemStruct->itemState & ODS_FOCUS) != 0 ) {
            rect.InflateRect(-5, -5);
            dc.DrawFocusRect(&rect);
        }
        dc.Detach();
    }
}


const bool CMyButton::DrawBitmap(CDC& dc, CBitmap& bitmap, const CRect& rectPosition, DWORD dwRop)
{
    ASSERT(dc.GetSafeHdc() != HDC(0));
    ASSERT(bitmap.GetSafeHandle() != HBITMAP(0));

    const CPoint    ptPosition(rectPosition.CenterPoint());
    bool            bRtn = false;
    CDC             dcMemory;
    if( dcMemory.CreateCompatibleDC(&dc) ) {
        CBitmap* const  pBitmap = dcMemory.SelectObject(&bitmap);
        BITMAP          bm;
        // rectPosition の真ん中に食み出さないように...
        if( bitmap.GetObject(sizeof(BITMAP), &bm) != 0 ) {
            CSize       size(bm.bmWidth, bm.bmHeight);
            // 座標系について考慮しない場合
            CPoint      ptOrg1(0, 0);
            const int   nWidth  = rectPosition.Width();
            if( size.cx > nWidth ) {
                ptOrg1.x += ((size.cx - nWidth ) >> 1);
                size.cx  = nWidth ;
            }
            const int       nHeight = rectPosition.Height();
            if( size.cy > nHeight ) {
                ptOrg1.y += ((size.cy - nHeight) >> 1);
                size.cy  = nHeight;
            }
            const CPoint    ptOrg2(ptPosition.x - (size.cx >> 1), ptPosition.y - (size.cy >> 1));
            bRtn = !!dc.BitBlt(ptOrg2.x, ptOrg2.y,
                               size.cx, size.cy,
                               &dcMemory, ptOrg1.x, ptOrg1.y,
                               dwRop);
        }
        if( pBitmap != NULL ) dcMemory.SelectObject(pBitmap);
        VERIFY(dcMemory.DeleteDC());
    }
    return bRtn;
}


参照
ボタンの色
ボタンのフォント
ボタンのフォント(オーナー描画)
前後のTips
ボタンにビットマップ表示

DSS ProgrammingTipsCGI Ver2.02