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

 对话框编辑器中的控件工具条中的图片控制主要是在一个对话框中快速地显示一个图象,它是很有用的。但是它只能显示图片的原始尺寸。如果你想显示一幅位图,它有可能和其他控制一起重新排列,问题就出来了。如果你改变了对话框的字体,则每个控制的尺寸将发生变化,但是显示位图的图片控制却没有。同样,当系统字体发生变化是也会出现类似问题。

为了解决此问题,我写了一个CStatic的派生类,按照CStatic控制的大小显示位图。当字体尺寸改变时,CStatic的窗口尺寸亦随之发生变化,位图将自动伸缩来适应新的大小。这样就允许显示的图象比原始尺寸小或大了。使用此类很容易,将CBitmapPicture类加入到你的项目,然后为你的对话框建立一个CStatic对象,并且将该成员的类型与CBitmapPicture关联起来,接着在你的OnInitDialog函数里调用CBitmapPicture::SetBitmap()设置将要用到的位图即可。  

BOOL SetBitmap(UINT nIDResource);           // Loads bitmap from resource ID
BOOL SetBitmap(LPCTSTR lpszResourceName);   // Loads bitmap from resource name
BOOL SetBitmap(HBITMAP hBitmap);            // Not recommended, as reloads can't be done


源程序:


#if !defined(AFX_BITMAPPICTURE_H__A4BE2021_689E_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_BITMAPPICTURE_H__A4BE2021_689E_11D1_ABBA_00A0243D1382__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

// BitmapPicture.h : header file
//
// Copyright (c) Chris Maunder (Chris.Maunder@cbr.clw.csiro.au)
// Written 1 December, 1997


/
// CBitmapPicture window

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()
};

/

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_BITMAPPICTURE_H__A4BE2021_689E_11D1_ABBA_00A0243D1382__INCLUDED_)


// BitmapPicture.cpp : implementation file
//
// Copyright (c) 1997 Chris Maunder (Chris.Maunder@cbr.clw.csiro.au)
// Written 1 December, 1997

#include "stdafx.h"
#include "BitmapPicture.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// if UPDATE_ENTIRE_CLIENT_AREA is not defined then only the update region of
// the bitmap is updated. Otherwise, on each update, the whole client area of
// the bitmap is drawn. UPDATE_ENTIRE_CLIENT_AREA is slower, but distortion
// of the picture may occur if it is not defined.

#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?l 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);

 // 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?l K. T?nder.
void CBitmapPicture::OnSysColorChange()
{
 CStatic::OnSysColorChange();
 ReloadBitmap();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值