偶然的一次机会看到了这个小小的控件,想必大家都知道该如何利用它了吧。o(∩_∩)o...

/**////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __MFC_EXT_DIGITCLOCK_H__
#define __MFC_EXT_DIGITCLOCK_H__
// EDClock.h : header file
//
#define IntegerCount 3
#define DecimalCount 5//4

/**//////////////////////////////////////////////////////////////////////////////
// CDigitDisplayer window

class CDigitDisplayer : public CStatic

...{
// Construction
public:
CDigitDisplayer();
virtual ~CDigitDisplayer();

// Attributes
public:
static COLORREF origin;

// Operations
public:

COLORREF GetColor() const ...{ return m_color;}
COLORREF SetColor(COLORREF color);
double m_number;
void DisplayDigit(double number);
void GetDigit(double number);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDigitDisplayer)
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL

// Implementation
public:

// Generated message map functions
protected:
//{{AFX_MSG(CDigitDisplayer)
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
//}}AFX_MSG
private:

COLORREF m_color;
UINT m_w;
UINT m_h;
BITMAP m_bm;
HBITMAP m_hBitmap[13];
UINT m_nTimer;
int m_digit[10];
void Output(UINT digit, UINT pos);

DECLARE_MESSAGE_MAP()
};


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

#endif // __MFC_EXT_DIGITCLOCK_H__
//
// Author: Xie Jingwei, Chinese Spell: 谢敬伟
// Email to me, jw_xie@usa.net
// A digital clock control, :-)
//
// Usage: See the header, just simple
// Please Note: Make sure ADD the 12 bitmaps to your project, and
// sort the ID to correct order. I used IDB_BITMAP1 to IDB_BITMAP12
// side by side. See following:
//
// Digit: ID VALUE
// 0 IDB_BITMAP1 100
// 1 IDB_BITMAP2 101
// 2 IDB_BITMAP3 102
// 3 IDB_BITMAP4 103
// 4 IDB_BITMAP5 104
// 5 IDB_BITMAP6 105
// 6 IDB_BITMAP7 106
// 7 IDB_BITMAP8 107
// 8 IDB_BITMAP9 108
// 9 IDB_BITMAP10 109
// : IDB_BITMAP11 110
// IDB_BITMAP12 111
//

// There are three properties.
// face color <-----> SetColor();
// style <-----> SetStyle();
// alarm mode <----> SetAlarm();


/**///////////////////////////////////////////////////////////////////////////////
// EDClock.cpp : implementation file
//数码管显示

#include "stdafx.h"

#include "resource.h"
#include "DigitDisplayer.h"
#include "math.h"

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

// The resource bitmap face color
//static COLORREF origin;
COLORREF CDigitDisplayer::origin = RGB(255, 0, 0);


/**//////////////////////////////////////////////////////////////////////////////
// CDigitDisplayer

CDigitDisplayer::CDigitDisplayer()

...{
m_color = origin;

for(int i = 0; i< 13; i++) ...{//创建数码显示的位图
HBITMAP temp = (HBITMAP)::CreateMappedBitmap(AfxGetApp()->m_hInstance, i+IDB_BITMAP1, 0, NULL, 0);//创建合适的位图
m_hBitmap[i] = (HBITMAP)::CopyImage( temp, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG | LR_COPYDELETEORG);//将位图存入缓存以备显示
}
for(i=0;i<8;i++) m_digit[i]=0;
m_number=0;
}

CDigitDisplayer::~CDigitDisplayer()

...{

for(int i = 0; i< 12; i++) ...{
if(m_hBitmap[i])
::DeleteObject(m_hBitmap[i]);//清空缓存
}
}

BEGIN_MESSAGE_MAP(CDigitDisplayer, CStatic)
//{{AFX_MSG_MAP(CDigitDisplayer)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/**//////////////////////////////////////////////////////////////////////////////
// CDigitDisplayer message handlers

void CDigitDisplayer::PreSubclassWindow()

...{
::GetObject(m_hBitmap[0], sizeof BITMAP, &m_bm);
CStatic::PreSubclassWindow();
}

void CDigitDisplayer::OnPaint() //设置数码宽度和高度

...{
CPaintDC dc(this); // device context for painting
CRect rectClient;
GetClientRect(&rectClient);
m_h = rectClient.Height();
m_w = rectClient.Width()/(IntegerCount+DecimalCount+2);
DisplayDigit(m_number);
}

BOOL CDigitDisplayer::OnEraseBkgnd(CDC* pDC) //给数码显示准备无效区域

...{
// TODO: Add your message handler code here and/or call default
CBrush brush;
brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT) );
CBrush* pOldBrush = pDC->SelectObject(&brush);

CRect rectClient;
GetClientRect(&rectClient);
pDC->PatBlt(0, 0, rectClient.Width(), rectClient.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
return CStatic::OnEraseBkgnd(pDC);
}

void CDigitDisplayer::Output(UINT digit, UINT pos)//数字输出

...{
// draw the bitmap
CClientDC dc(this);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap* pBitmap = CBitmap::FromHandle( m_hBitmap[digit] );
CBitmap* pOldBitmap = dcMem.SelectObject(pBitmap);
dc.StretchBlt(m_w*pos, 0, m_w, m_h,
&dcMem, 0, 0, m_bm.bmWidth, m_bm.bmHeight, SRCCOPY);
dcMem.SelectObject(pOldBitmap);
dcMem.DeleteDC();
}



COLORREF CDigitDisplayer::SetColor(COLORREF color)//显示数字的颜色设置,若是红色,则改为显示时的绿色。

...{
if(m_color == color)
return color;
COLORREF temp = m_color;
m_color = color;

for(int i = 0; i< 13; i++) ...{
if(m_hBitmap[i])
::DeleteObject(m_hBitmap[i]);
COLORMAP mapColor;
mapColor.from = origin;
mapColor.to = color;
HBITMAP temp = (HBITMAP)::CreateMappedBitmap(AfxGetApp()->m_hInstance, i+IDB_BITMAP1, 0, &mapColor, 1);
m_hBitmap[i] = (HBITMAP)::CopyImage( temp, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG | LR_COPYDELETEORG);
}
return temp;
}

void CDigitDisplayer::GetDigit(double number)//获取每一位数字

...{
//最多显示4位整数,4位小数,1个小数点,1个符号
m_digit[0]=number/1000; //第一位整数
m_digit[1]=(number-m_digit[0]*1000)/100; //第二位整数
m_digit[2]=(number-m_digit[0]*1000-m_digit[1]*100)/10; //第三位整数
m_digit[3]=number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10; //第四位整数
m_digit[4]=(number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10-m_digit[3])*10; //第一位小数
m_digit[5]=(number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10-m_digit[3])*100-m_digit[4]*10; //第二位小数
m_digit[6]=(number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10-m_digit[3])*1000-m_digit[4]*100-m_digit[5]*10; //第三位小数
m_digit[7]=(number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10-m_digit[3])*10000-m_digit[4]*1000-m_digit[5]*100-m_digit[6]*10; //第四位小数
m_digit[8]=(number-m_digit[0]*1000-m_digit[1]*100-m_digit[2]*10-m_digit[3])*100000-m_digit[4]*10000-m_digit[5]*1000-m_digit[6]*100-m_digit[7]*10; //第五位小数
}

void CDigitDisplayer::DisplayDigit(double number)

...{

/**//*CRect rectClient;
GetClientRect(&rectClient);
m_h = rectClient.Height();
m_w = rectClient.Width()/(IntegerCount+DecimalCount+2);
*/
//得到各个数码位
GetDigit(fabs(number));

//显示符号
if(number>0) Output(12, 0); //空位图
else Output(11,0); //负号

//显示小数点前的各数码位
int firstpositive;
firstpositive=3;
for(int i=4-IntegerCount;i<4;i++)

...{
if(m_digit[i]>0)

...{
firstpositive=i;
break;
}
}
for(i=4-IntegerCount;i<4;i++)

...{
if(i>=firstpositive)
Output(m_digit[i],i-3+IntegerCount);
else
Output(12, i-3+IntegerCount);
}

//显示小数点
Output(10,IntegerCount+1);
//显示小数点后的各数码位
for(i=IntegerCount+1;i<IntegerCount+1+DecimalCount;i++)

...{
Output(m_digit[i],i+1);
}
}

void CDigitDisplayer::OnSize(UINT nType, int cx, int cy) //保存当前窗口宽和高,以便后面能用GetWindowHeight和GetWindowWidth得到

...{
CStatic::OnSize(nType, cx, cy);
CRect rectClient;
GetClientRect(&rectClient);
m_h = rectClient.Height();
m_w = rectClient.Width()/(IntegerCount+DecimalCount+2);
}
在BITMAP中加入数码管资源即可实现
