分享
 
 
 

以曲线或柱状图实时显示数据的控件

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

这是一款可以以曲线或柱状图的形式实时动态显示数据的控件。

主要特点是:支持显示浮点数、负数,显示数据范围大、可以自定义显示范围也可自动选择范围,还可锁定显示范围。

主要技术来源于网上,我只是对其分离改进了一下。有需要的朋友可以看看或联系我

Email: wlzqin@3stonesoft.com

wlzqin@sina.com

QQ :8573980

MSN :wlzqi@hotmail.com

[/url]

[url=http://transparentclock.Zj.com/software/ColorPlot.rar]源码下载

使用方法:

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 ////////////////////////////////////

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有