以曲线或柱状图实时显示数据的控件
这是一款可以以曲线或柱状图的形式实时动态显示数据的控件。
主要特点是:支持显示浮点数、负数,显示数据范围大、可以自定义显示范围也可自动选择范围,还可锁定显示范围。
主要技术来源于网上,我只是对其分离改进了一下。有需要的朋友可以看看或联系我
Email: wlzqin@3stonesoft.com
wlzqin@sina.com
QQ :8573980
MSN :wlzqi@hotmail.com
源码下载
使用方法:
1.首先放一个CButton,并对这个按钮生成一个对象。例如 CButton m_btn ;
2.更改按钮的类名 改为 CMulticolorPlotBtn m_btn
3.初始化: 初始化由自己绝对初始化那些(当然也可省略这步)
4。显示数据。m_btn.SetData( ( float ) rand () ) ;
//////////////////////////////////// MulticolorPlotBtn.h ////////////////////////////////////
/*
模块名称:MulticolorPlotBtn.h
版 本:0.1 Alpha
版 权:Copyright (C) 2005 wlzqin
模块功能:动态图表显示数据
作 者:wlzqi
作者邮箱:mailto:wlzqin@3stonesoft.com
建立时间:22005年6月14日 乙酉 鸡年五月初八
最后修改:by wlzqi
修改历程:
注意事项:
备注:支持 UNICODE 和 ANSI 编码
:测试平台 Windows 2000、IE6、Direcx9、 AMD Xp 2000 + CPU
:不兼容 Windows 98
功能简介:动态实时显示数据,显示方式有BAR和LINE(其它方式以后添加)
,可动态实时改变曲线属性。支持任意范围数据,可设定范围,
也可不设定显示范围(自动寻找最符合的范围),还可任意锁定
(自由)范围。支持浮点数。
*/
#pragma once
#include "afxwin.h"
#include <math.h>
#define BAR 0
#define LINE 1
class CMulticolorPlotBtn :
public CButton
{
public:
CMulticolorPlotBtn(void) ;
virtual ~CMulticolorPlotBtn(void);
private: // 公共属性
int nPlotType ; // 曲线类型 BAR 或 LINE // BAR
bool bfInit ; // 是否初始化 // false
// 网格X方向上的间距
int nGridResolutionX ; // 10
// 网格Y方向上的间距
int nGridResolutionY ; // 10
// 网格滚动的速度和方向(正值为从左向右滚动和从上到下,否则反之。0不动)
int nGridScrollSpeedX ; // -1
int nGridScrollSpeedY ; // 0
// 数据点分辨率大小(即:一个数据点占据的像素数)
int nPlotGranulatrity ; // 2
// 网格线宽度
int nGridLineWidth ; // 1
// 背景色
COLORREF m_clrDarkBack ; // RGB(0,0,75)
// 前景色
COLORREF m_clrDarkLine ; // RGB(32,64,32)
// 控件矩形
RECT m_rect ;
// 控件的尺寸
CSize m_Size ;
// 控件可容纳可见的数据点数
int nPlotData ; // 0
// 实际数据
float * pfData ; // 0
// 数据范围
float fLow , fHigh ; // 0,0
// 数据比例
float fScaleY ; // 1.0
// 数据点处的颜色
COLORREF m_clrCyanData ; // RGB ( 0,255,255 )
// 画笔
CPen m_GridPen ;
// 数据点位图画刷
CBrush m_clrBrush ;
// 网格开始位置
int nGridStarPosX , nGridStarPosY ; // 0,0
// 锁定显示范围
bool bLock ; // true---锁定
// 控件上显示的字体
CFont m_SmallFont ;
// Y轴刻度的颜色
COLORREF m_clrAxisScaleY ; // RGB ( 0,255,255 )
// 是否显示Y轴刻度数字
int nShowFormatDataText ; // 0---不显示
// 控件标题
TCHAR szTitls [MAX_PATH * sizeof ( TCHAR ) + 1] ; // NULL
// 曲线单位
TCHAR szUints [32 * sizeof ( TCHAR ) + 1] ; // NULL
private:
// 关键代码
CRITICAL_SECTION g_cs ;
public: // 公共方法
// 设置画线的类型
void SetPlotType ( int nType )
{
nPlotType = nType ;
bfInit = false ;
}
// 设置网格间距
void SetGridResolutionX ( int nGridReluX ) { nGridResolutionX = nGridReluX ; }
void SetGridResolutionY ( int nGridReluY ) { nGridResolutionY = nGridReluY ; }
// 设置网格滚动速度
// 正值为从左向右滚动,0不动
void SetGridScrollSpeedX ( int nSpeedX ) { nGridScrollSpeedX = nSpeedX ; }
// 正值为从上到下滚动,0不动
void SetGridScrollSpeedY ( int nSpeedY ) { nGridScrollSpeedY = nSpeedY ; }
// 数据点面积大小(即:一个数据点占据的像素数)
bool SetPlotGranulatrity ( int nPlotGrltiy )
{
nPlotGranulatrity = nPlotGrltiy ;
nPlotData = m_Size.cx / nPlotGranulatrity ;
pfData = new float [ nPlotData ] ;
if ( pfData )
{
// 初始化数据为 0
ZeroMemory ( pfData , sizeof ( pfData ) * nPlotData ) ;
return true ;
}
return true ;
}
// 网格线宽度
void SetGridLineWidth ( int nWidth ) { nGridLineWidth = nWidth ; }
// 背景色
void SetGridBackClr ( COLORREF clr ) { m_clrDarkBack = clr ; }
// 前景色
void SetGridLineClr ( COLORREF clr )
{
m_clrDarkLine = clr ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
m_clrDarkLine = clr ;
}
// 数据范围
void SetRang ( float fL , float fH )
{
fLow = fL ;
fHigh = fH ;
}
// 创建画笔
void SetLinePen ( int nWidth , COLORREF clr )
{
nGridLineWidth = nWidth ;
m_clrDarkLine = clr ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
}
// 锁定数据显示范围
void LockRang ( bool bfLock = true ) ;
void LockRang ( float fMin = 0.0 , float fMax = 100.0 ) ;
// Y轴刻度颜色,bfShow==0显示刻度数字,1仅在左上角显示1000(k/sec)/2000样子的数字,2显示最大最小,3显示全部
void SetAxisScaleClrY ( COLORREF clr = RGB ( 0 , 255 , 255 ) )
{
m_clrAxisScaleY = clr ;
}
// 标题
void SetTitle ( PCTSTR pctTitle = NULL )
{
_stprintf ( szTitls , _TEXT ( "%s" ) , pctTitle ) ;
}
// 数据单位例:SetUnit( _TEXT ( "(k/sec)" ) ) ;
void SetUnit ( PCTSTR pctUint = NULL )
{
_stprintf ( szUints , _TEXT ( "%s" ) , pctUint ) ;
}
// 是否显示数据标题、颜色、单位
/*
nShow = 0 ; 不显示任何文本
nShow = 1 ; 仅仅显示标题
nShow = 2 ; 仅仅显示标题和流量总计
nShow = 3 ; 显示标题和最小值
nShow = 4 ; 显示标题、最小值和中值
*/
void ShowTitle ( int nShow = 1 )
{
nShowFormatDataText = nShow ;
}
private: // BAR属性
// BAR颜色
COLORREF m_clrUp ;
COLORREF m_clrDown ;
public: // BAR方法
// BAR 颜色
// clrUp -------- 顶部颜色
// clrDown -------- 底部颜色
// bfRfastness -------- 红色分量是否固定不变 false ---- 渐变
// bfGfastness -------- 红色分量是否固定不变 false ---- 渐变
// bfBfastness -------- 红色分量是否固定不变 false ---- 渐变
void SetBarColor ( COLORREF clrUp , COLORREF clrDown , bool bfRfastness = false , bool bfGfastness = false , bool bfBfastness = false ) ;
// 设置数据
void SetData ( float fData ) ;
private: // LINE属性
// 曲线颜色
COLORREF m_clrLinePen ; // RGB(0,255,0)
// 曲线宽度
int nLineWidth ;
public: // LINE方法
// 曲线颜色
void SetLineColorWidth ( COLORREF clrLine = RGB ( 0 , 255 , 0 ) , int nWidth = 1 )
{
nLineWidth = nWidth ;
m_clrLinePen = clrLine ;
}
void SetLineColor ( COLORREF clrLine = RGB ( 0 , 255 , 0 ) ) { m_clrLinePen = clrLine ; }
void SetLineWidth ( int nWidth = 1 ) { nLineWidth = nWidth ; }
const COLORREF GetLineColor () { return m_clrLinePen ; }
const int GetLineWidth () { return nLineWidth ; }
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnTimer(UINT nIDEvent);
protected:
virtual void PreSubclassWindow();
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};
//////////////////////////////////// end ////////////////////////////////////
//////////////////////////////////// MulticolorPlotBtn.cpp ////////////////////////////////////
#include "StdAfx.h"
#include ".\multicolorplotbtn.h"
#include "MemDC.h"
#define GRID_TIMER 1
//网格刷新速率
#define GRID_UPDATE_SPEED 50
typedef struct
{
float fx ;
float fy ;
} DATA_POINT ;
DATA_POINT * g_DataPoint ;
CMulticolorPlotBtn::CMulticolorPlotBtn()
: nPlotType(BAR)
, bfInit(false)
, nGridResolutionX(10)
, nGridResolutionY(10)
, nGridScrollSpeedX(-1)
, nGridScrollSpeedY(0)
, nPlotGranulatrity(2)
, nGridLineWidth(1)
, m_clrDarkBack(RGB(0,0,75))
, m_clrDarkLine(RGB(32,64,32))
, nPlotData(0)
, pfData(NULL)
, fLow(0.0)
, fHigh(100.0)
, fScaleY(1.0)
, m_clrCyanData(RGB(0,255,255))
, nGridStarPosX(0)
, nGridStarPosY(0)
, bLock(true)
, m_clrAxisScaleY(RGB(0,255,255))
, nShowFormatDataText(0)
, m_clrLinePen(RGB(0,255,0))
, nLineWidth(1)
{
// 关键代码
// 初始化关键代码的 C_S 结构
InitializeCriticalSection ( & g_cs ) ;
// 初始化标题
_stprintf ( szTitls , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
// 初始化单位
_stprintf ( szUints , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
}
CMulticolorPlotBtn::~CMulticolorPlotBtn(void)
{
if ( pfData )
{
delete [] pfData ;
}
// 释放关键代码
DeleteCriticalSection ( & g_cs ) ;
}
BEGIN_MESSAGE_MAP(CMulticolorPlotBtn, CButton)
ON_WM_TIMER()
END_MESSAGE_MAP()
void CMulticolorPlotBtn::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
// 避免把该按钮当成下压式按钮
ModifyStyle( 0 , BS_OWNERDRAW ) ;
GetWindowRect ( & m_rect ) ;
ScreenToClient ( & m_rect ) ;
// 得到该控件的宽和高
m_Size.cx = m_rect.right - m_rect.left ;
m_Size.cy = m_rect.bottom - m_rect.top ;
// 计算控件可容纳可见的数据点数
nPlotData = m_Size.cx / nPlotGranulatrity ;
// 设置控件上显示的文字的字体和大小
m_SmallFont.CreateFont( -11 , 0 , 0 , 0 , FW_THIN , false , false , false , DEFAULT_CHARSET ,
OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY , VARIABLE_PITCH , _TEXT( "Times New Roman" ) ) ;
// 给实际数据分配内存
pfData = new float [ nPlotData ] ;
if ( pfData )
{
// 初始化数据为 0
ZeroMemory ( pfData , sizeof ( pfData ) * nPlotData ) ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
GetWindowRect ( & m_rect ) ;
ScreenToClient ( & m_rect ) ;
CRgn m_Rgn ;
m_Rgn.CreateRoundRectRgn ( 0 , 0 , m_Size.cx , m_Size.cy , 10 , 10 ) ;
SetWindowRgn ( ( HRGN ) m_Rgn , true ) ;
SetTimer ( GRID_TIMER , GRID_UPDATE_SPEED , NULL ) ;
}
CButton::PreSubclassWindow();
}
void CMulticolorPlotBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
ASSERT( lpDrawItemStruct != NULL ) ;
CDC * pDC = CDC::FromHandle( lpDrawItemStruct -> hDC ) ;
// 创建内存 DC
CMemDC * pMemDC = new CMemDC ( pDC ) ;
// 得到控件大小
RECT clipRect ;
pMemDC->GetClipBox ( & clipRect ) ;
if ( bfInit == false )
{
// 如果没有初始化,则初始化画刷
CBitmap m_Bmp ;
// 如果控件大小有效
if ( clipRect.right - clipRect.left > 1 )
{
// 根据数据点分辨率创建内存位图
m_Bmp.CreateCompatibleBitmap( pMemDC ,nPlotGranulatrity , m_Size.cy ) ;
CBitmap * pOldBmp = pMemDC->SelectObject( & m_Bmp ) ;
CSize m_BmpSize = m_Bmp.GetBitmapDimension () ;
// 根据不同的曲线分别绘制
if ( nPlotType == BAR )
{
double factor = 255.0 / ( float ) m_Size.cy ;
BYTE r , g , b ;
for ( int x = 0 ; x < m_Size.cy ; x ++ )
{
g = ( BYTE ) ( 255 - factor * x ) ;
r = ( BYTE ) ( factor * x ) ;
b = ( BYTE ) 64 ;
pMemDC->SetPixelV ( 0 , x , RGB ( r , g , b ) ) ;
pMemDC->SetPixelV ( 1 , x , RGB ( r , g , b ) ) ;
}
}
else if ( nPlotType == LINE )
{
}
else
{
}
pMemDC->SelectObject ( pOldBmp ) ;
// 生成位图画刷
m_clrBrush.CreatePatternBrush ( & m_Bmp ) ;
bfInit = true ;
}
}
if ( bfInit )
{
// 填充背景色
pMemDC->FillSolidRect ( & clipRect , m_clrDarkBack ) ;
CFont * pOldFont ;
//
CPoint orgBrushOrigin = pMemDC->GetBrushOrg () ;
// 画网格
int nGridLinesX = m_Size.cx / nGridResolutionX ;
int nGridLinesY = m_Size.cy / nGridResolutionY ;
// 选择画笔
CPen * pOldPen = pMemDC->SelectObject ( & m_GridPen ) ;
// 创建垂直线
for ( int x = 0 ; x <= nGridLinesX ; x ++ )
{
pMemDC->MoveTo ( x * nGridResolutionX + nGridStarPosX , 0 );
pMemDC->LineTo ( x * nGridResolutionX + nGridStarPosX , m_Size.cy );
}
// 添加水平线
for ( int y = 0 ; y <= nGridLinesY ; y ++ )
{
pMemDC->MoveTo ( 0 , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
pMemDC->LineTo ( m_Size.cx , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
}
// 控制网格正确移动
nGridStarPosX += nGridScrollSpeedX ;
nGridStarPosY += nGridScrollSpeedY ;
if ( nGridStarPosX < 0 ) nGridStarPosX = nGridResolutionX ;
if ( nGridStarPosX > nGridResolutionX ) nGridStarPosX = 0 ;
if ( nGridStarPosY < 0 ) nGridStarPosY = nGridResolutionY ;
if ( nGridStarPosY > nGridResolutionY ) nGridStarPosY = 0 ;
// 还原网格画笔
pMemDC->SelectObject ( pOldPen ) ;
// 用关键代码同步和SetData
EnterCriticalSection ( & g_cs ) ;
// 画数据
float fx , fy ;
if ( nPlotType == BAR )
{
RECT rFill ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
fx = ( float ) ( m_rect.left + nData * nPlotGranulatrity ) ;
fy = fabs ( ( float ) ( m_rect.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
rFill.bottom = ( LONG ) m_rect.bottom ;
rFill.top = ( LONG ) fy ;
rFill.left = ( LONG ) fx ;
rFill.right = ( LONG ) ( fx + nPlotGranulatrity ) ;
pMemDC->SetBrushOrg ( ( int ) fx , m_rect.bottom ) ;
// 用初始化画刷时生成的渐变位图画刷填充矩形
pMemDC->FillRect ( & rFill , & m_clrBrush ) ;
// 画数据点处的颜色
pMemDC->SetPixelV ( ( int ) fx , ( int ) fy , m_clrCyanData ) ;
}
}
else if ( nPlotType == LINE )
{
CPoint * g_DataPoint = new CPoint [nPlotData] ;
// 创建曲线画笔
CPen m_Pen ;
m_Pen.CreatePen ( PS_SOLID , nLineWidth , m_clrLinePen ) ;
CPen * m_pOldPen = pMemDC->SelectObject ( & m_Pen ) ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
g_DataPoint[nData].x = ( LONG ) ( m_rect.left + nData * nPlotGranulatrity ) ;
g_DataPoint[nData].y = ( LONG ) fabs ( ( float ) ( m_rect.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
}
pMemDC->Polyline ( g_DataPoint , nPlotData ) ;
pMemDC->SelectObject ( m_pOldPen ) ;
delete [] g_DataPoint ;
}
else
{
}
// 绘制Y轴刻度
TCHAR szAxisScaleYMax [MAX_PATH * sizeof ( TCHAR ) + 1] ;
TCHAR szAxisScaleYMin [MAX_PATH * sizeof ( TCHAR ) + 1] ;
TCHAR szAxisScaleY [MAX_PATH * sizeof ( TCHAR ) + 1] ;
ZeroMemory ( & szAxisScaleYMax , sizeof ( szAxisScaleYMax ) ) ;
ZeroMemory ( & szAxisScaleYMin , sizeof ( szAxisScaleYMin ) ) ;
ZeroMemory ( & szAxisScaleY , sizeof ( szAxisScaleY ) ) ;
COLORREF clrText = pMemDC->GetTextColor () ;
int nBkMode = pMemDC->GetBkMode () ;
pMemDC->SetTextColor ( m_clrAxisScaleY ) ;
pMemDC->SetBkMode ( TRANSPARENT ) ;
pOldFont = pMemDC->SelectObject ( & m_SmallFont ) ;
// 如果要求现实Y轴刻度数字
switch ( nShowFormatDataText )
{
case 0 : // 不显示
{
} break ;
case 1 : // 仅显示标题
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s" ) , szTitls ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
} break ;
case 2 : // 显示标题和流量比例
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
} break ;
case 3 : // 显示最大最小值
{
// 格式化最大值和标题及单位
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
// 格式化最小值
_stprintf ( szAxisScaleYMin , _TEXT ( "%8.1f" ) , fLow ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pMemDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
} break ;
case 4 : // 显示全部
{
// 格式化最大值和标题及单位
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
// 格式化最小值
_stprintf ( szAxisScaleYMin , _TEXT ( "%8.1f" ) , fLow ) ;
// 格式化中值
_stprintf ( szAxisScaleY , _TEXT ( "%8.1f" ) , ( ( fHigh - fLow ) / 2.0 + fLow ) ) ;
// 绘制Y轴刻度
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pMemDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
pMemDC->TextOut ( 0 , m_Size.cy / 2 , szAxisScaleY ) ;
} break ;
}
pMemDC->SetTextColor ( clrText ) ;
pMemDC->SetBkMode ( nBkMode ) ;
pMemDC->SelectObject ( pOldFont ) ;
// 离开关键代码
LeaveCriticalSection ( & g_cs ) ;
pMemDC->SetBrushOrg ( orgBrushOrigin.x , orgBrushOrigin.y ) ;
}
delete pMemDC ;
ReleaseDC ( pDC ) ;
}
void CMulticolorPlotBtn::OnTimer(UINT nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch ( nIDEvent )
{
case GRID_TIMER :
{
} break ;
}
Invalidate ( false ) ;
CButton::OnTimer(nIDEvent);
}
// BAR 颜色
void CMulticolorPlotBtn::SetBarColor ( COLORREF clrUp , COLORREF clrDown , bool bfRfastness ,
bool bfGfastness , bool bfBfastness )
{
}
// 设置数据
void CMulticolorPlotBtn::SetData ( float fData )
{
// 用关键代码同步
EnterCriticalSection ( & g_cs ) ;
for ( int n = 0 ; n < nPlotData - 1 ; n ++ )
{
pfData [ n ] = pfData [ n + 1 ] ;
}
pfData [ nPlotData - 1 ] = fData ;
if ( bLock ) // 锁定比例范围
{
}
else
{
// 保存最小值
if ( fLow > fData )
{
fLow = fData ;
}
// 保存最大值
if ( fHigh < fData )
{
fHigh = fData ;
}
}
// 离开关键代码
LeaveCriticalSection ( & g_cs ) ;
}
// 锁定数据显示范围
void CMulticolorPlotBtn::LockRang ( bool bfLock )
{
bLock = bfLock ;
}
void CMulticolorPlotBtn::LockRang ( float fMin , float fMax )
{
fLow = fMin ;
fHigh = fMax ;
LockRang ( true ) ;
}
//////////////////////////////////// end ////////////////////////////////////
///////////////////////////// MemDC.h ///////////////////////////////////////////////////
#if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
//////////////////////////////////////////////////
// CMemDC 实现一个内存DC
class CMemDC : public CDC
{
private:
CBitmap m_bitmap; // 实际的bitmap
CBitmap* m_pOldBitmap; // 原先在CMemDC中的位图
CDC* m_pDC; // 保存从构造函数中传来的CDC
CRect m_rect; // 画的矩形区域
BOOL m_bMemDC; // 如果CDC是一个内存DC,则为TRUE
public:
CMemDC(CDC* pDC) : CDC()
{
ASSERT(pDC != NULL);
m_pDC = pDC;
m_pOldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();//判断是否是一个内存DC
if (m_bMemDC) // 创建一个内存DC
{
pDC->GetClipBox(&m_rect);
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
SetWindowOrg(m_rect.left, m_rect.top);
}
else // 这不是一个内存DC,我们只拷贝相关的DC部分以备打印
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
~CMemDC()
{
if (m_bMemDC)
{
// 拷贝实际的位图到屏幕上
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
//装入原始的位图
SelectObject(m_pOldBitmap);
}
else
{
m_hDC = m_hAttribDC = NULL;
}
}
// 允许作为指针
CMemDC* operator->() {return this;}
operator CMemDC*() {return this;}
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
//////////////////////////////////// end ////////////////////////////////////