目前位置: VCer资源中心 >>> VCer开源 >>> 可重用类

[本帖已阅读2033次 分值130 回复0次] 张贴资源 发回信箱 控制面板

一个自适应大小的位图控件

提供者:hamxj 张贴时间:2007-02-28 15:45:50.0 出处:codeguru.com 作者:Chris Maunder

一个自适应大小的位图控件(2007-02-28 15:45:50.0)


热的


 
级别: VCer小兵
头衔: VCer会员

经验: 310
作品: 3
分会: 华北分会
注册: 2007-01-05 09:46:57.0
登录: 2007-05-10 22:27:54.0
工程源码[3,294字节] 下载123
软件下载[21,918字节] 下载88

实现方法

这是一个自适应大小的位图控件演示程序

通过调整对话框字体大小可以观察出CBitmapPicture类和MFC的Picture控件之间的差别

关键代码如下:

...

BitmapPicture.h

...

class CBitmapPicture : public CStatic

{

// Construction

public:

    CBitmapPicture();

   

// Operations

public:

    BOOL SetBitmap(HBITMAP hBitmap);            // Not recommended

    BOOL SetBitmap(UINT nIDResource);

    BOOL SetBitmap(LPCTSTR lpszResourceName);

    BOOL ReloadBitmap();

// Overrides

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CBitmapPicture)

    protected:

    virtual void PreSubclassWindow();

    virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

    //}}AFX_VIRTUAL

// Implementation

public:

    virtual ~CBitmapPicture();

// Attributes

protected:

    HBITMAP  m_hBitmap;

    BITMAP  m_bmInfo;

private:

    int    m_nResourceID;

    CString m_strResourceName;

// Generated message map functions

protected:

    //{{AFX_MSG(CBitmapPicture)

    afx_msg BOOL OnEraseBkgnd(CDC* pDC);

    afx_msg void OnSysColorChange();

    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()

};

...

BitmapPicture.cpp

...

#define UPDATE_ENTIRE_CLIENT_AREA

/////////////////////////////////////////////////////////////////////////////

// CBitmapPicture

CBitmapPicture::CBitmapPicture()

{

    m_hBitmap = NULL;

    m_nResourceID = -1;

    m_strResourceName.Empty();

}

CBitmapPicture::~CBitmapPicture()

{

    if (m_hBitmap) ::DeleteObject(m_hBitmap);

}

BEGIN_MESSAGE_MAP(CBitmapPicture, CStatic)

    //{{AFX_MSG_MAP(CBitmapPicture)

    ON_WM_ERASEBKGND()

    ON_WM_DRAWITEM_REFLECT()

    ON_WM_SYSCOLORCHANGE()

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CBitmapPicture message handlers

BOOL CBitmapPicture::SetBitmap(HBITMAP hBitmap)

{

    ::DeleteObject(m_hBitmap);

    m_hBitmap = hBitmap;

    return ::GetObject(m_hBitmap, sizeof(BITMAP), &m_bmInfo);

}

BOOL CBitmapPicture::SetBitmap(UINT nIDResource)

{

    m_nResourceID = nIDResource;

    m_strResourceName.Empty();

    HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),

                                        MAKEINTRESOURCE(nIDResource),

                                        IMAGE_BITMAP,

                                        0,0,

                                        LR_LOADMAP3DCOLORS);

    if (!hBmp) return FALSE;

    return CBitmapPicture::SetBitmap(hBmp);

}

BOOL CBitmapPicture::SetBitmap(LPCTSTR lpszResourceName)

{

    m_nResourceID = -1;

    m_strResourceName = lpszResourceName;

    HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),

                                        lpszResourceName,

                                        IMAGE_BITMAP,

                                        0,0,

                                        LR_LOADMAP3DCOLORS);

    if (!hBmp) return FALSE;

    return CBitmapPicture::SetBitmap(hBmp);

}

// Suggested by P? K. Used to reload the bitmap on system colour changes.

BOOL CBitmapPicture::ReloadBitmap()

{

    if (m_nResourceID > 0)

        return SetBitmap(m_nResourceID);

    else if (!m_strResourceName.IsEmpty())

        return SetBitmap(m_strResourceName);

    else    // if SetBitmap(HBITMAP hBitmap) was used directly then we can’t reload.

        return FALSE;

}

void CBitmapPicture::PreSubclassWindow()

{

    CStatic::PreSubclassWindow();

    ModifyStyle(0, SS_OWNERDRAW);

}

BOOL CBitmapPicture::OnEraseBkgnd(CDC* pDC)

{

    CRect rect;

    GetClientRect(rect);

    // If no bitmap selected, simply erase the background as per normal and return

    if (!m_hBitmap)

    {

        CBrush backBrush(::GetSysColor(COLOR_3DFACE)); // (this is meant for dialogs)

        CBrush* pOldBrush = pDC->SelectObject(&backBrush);

        pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);

        pDC->SelectObject(pOldBrush);

        return TRUE;

    }

    // We have a bitmap - draw it.

    // Create compatible memory DC using the controls DC

    CDC dcMem;

    VERIFY( dcMem.CreateCompatibleDC(pDC));

   

    // Select bitmap into memory DC.

    HBITMAP* pBmpOld = (HBITMAP*) ::SelectObject(dcMem.m_hDC, m_hBitmap);

    pDC->SetStretchBltMode(COLORONCOLOR);

    // StretchBlt bitmap onto static’s client area

#ifdef UPDATE_ENTIRE_CLIENT_AREA

    pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(),

                    &dcMem, 0, 0, m_bmInfo.bmWidth-1, m_bmInfo.bmHeight-1,

                    SRCCOPY);

#else

    CRect TargetRect;                // Region on screen to be updated

    pDC->GetClipBox(&TargetRect);

    TargetRect.IntersectRect(TargetRect, rect);

    CRect SrcRect;                    // Region from bitmap to be painted

    SrcRect.left    = MulDiv(TargetRect.left,  m_bmInfo.bmWidth,  rect.Width());

    SrcRect.top    = MulDiv(TargetRect.top,    m_bmInfo.bmHeight, rect.Height());

    SrcRect.right  = MulDiv(TargetRect.right,  m_bmInfo.bmWidth,  rect.Width());

    SrcRect.bottom  = MulDiv(TargetRect.bottom, m_bmInfo.bmHeight, rect.Height());   

    pDC->StretchBlt(TargetRect.left, TargetRect.top, TargetRect.Width(), TargetRect.Height(),

                    &dcMem,

                    SrcRect.left, SrcRect.top, SrcRect.Width(), SrcRect.Height(),

                    SRCCOPY);

#endif

    ::SelectObject(dcMem.m_hDC, pBmpOld);

    return TRUE;

}

void CBitmapPicture::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

{

    ASSERT(lpDrawItemStruct != NULL);

   

    CString str;

    GetWindowText(str);

    if (!str.GetLength()) return;

    CDC*  pDC    = CDC::FromHandle(lpDrawItemStruct->hDC);

    CRect rect    = lpDrawItemStruct->rcItem;

    DWORD dwStyle = GetStyle();

    int  nFormat = DT_NOPREFIX | DT_NOCLIP | DT_WORDBREAK | DT_SINGLELINE;

    if (dwStyle & SS_CENTERIMAGE) nFormat |= DT_VCENTER;

    if (dwStyle & SS_CENTER)      nFormat |= DT_CENTER;

    else if (dwStyle & SS_RIGHT)  nFormat |= DT_RIGHT;

    else                          nFormat |= DT_LEFT;

    int nOldMode = pDC->SetBkMode(TRANSPARENT);

    pDC->DrawText(str, rect, nFormat);

    pDC->SetBkMode(nOldMode);

}

// Suggested by P? K. T?der.

void CBitmapPicture::OnSysColorChange()

{

    CStatic::OnSysColorChange();

    ReloadBitmap();

}

注:转载文章需注明来源:VCer.net 文章地址:http://vcer.net/1172648750640.html

  如果你觉得VCer.net不错,而且你愿意为VCer.net捐赠一元钱,那么点击后面的捐赠按钮吧:) vcer.net捐赠

[回复该贴] [加入个人书签]
[投票结果]

A: 评分 10 100% (3 票)
B: 评分 5 0% (0 票)
C: 评分 0 0% (0 票)
D: 评分 -5 0% (0 票)
E: 评分 -10 0% (0 票)