可以设置刻度的进度条

        现在做的软件上要用图形来显示串口传过来的信号值大小,最简单的办法,莫过于用进度条显示了。但是在使用的过程中发现一个问题,就是没有刻度。如果有美工,问题也好解决,在没有美工的情况下,只好靠自己动手DIY了。

       由于以前没有做过控件,就在网上找了别人做的拿来参考,于是,就发现了颜色渐变进度条的代码。这个代码严格说来并不完全,进度条只能横着不能竖起来。在读懂了颜色渐变进度条后,我做出了带刻度的进度条控件。目前,我做的这个控件有以下功能:

  1、设置前景色

  2、设置背景色

  3、设置有无刻度,刻度位置,刻度数量

  4、设置进度条有无边框

  5、设置文字显示

  头文件如下:

#if !defined(AFX_GRADIENTPROGRESSCTRL_H__91ECB8BC_A7DA_42EB_B2C5_37419D31B753__INCLUDED_)
#define AFX_GRADIENTPROGRESSCTRL_H__91ECB8BC_A7DA_42EB_B2C5_37419D31B753__INCLUDED_
#endif

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

#if !defined(AFX_MEMDC_H__A68B97E6_DDB4_4B4F_8A18_429844C3659C__INCLUDED_)
#define AFX_MEMDC_H__A68B97E6_DDB4_4B4F_8A18_429844C3659C__INCLUDED_
#endif

class CMemDC : public CDC 
{
public:
 CMemDC(CDC* pDC);
 CMemDC* operator->(){return this;}
 operator CMemDC*(){return this;}
 virtual ~CMemDC();
private:
 CBitmap m_bitmap;
 CBitmap* m_pOldBitmap;
 CDC* m_pDC;
 CRect m_rect;
 BOOL m_bMemDC;
};


/
// CScaleProgressCtrl window

class CScaleProgressCtrl : public CProgressCtrl
{
// Construction
public:
 CScaleProgressCtrl();

 //Set_function
 void SetTextColor(COLORREF color) {m_clrText=color;}   //设置文字颜色,默认为
 void SetBkColor(COLORREF color)  {m_clrBkGround=color;}  //设置进度条背景色
 void SetForeColor(COLORREF color) {m_FaceColor=color;}    //设置进度条前景色
 void SetShowFrame(BOOL frame)           {m_Frame=frame;}    //设置是否显示进度条边框
 //void SetEndColor(COLORREF color) {m_clrEnd=color;}
 //Percent TXT showed in the Progress
 void SetShowPercent(BOOL bShowPercent=TRUE) {m_bShowPercent=bShowPercent;}   //是否显示文字
 
 //Get_Function
 COLORREF GetTextColor(void)  {return m_clrText;}   
 COLORREF GetBkColor(void)  {return m_clrBkGround;}
 COLORREF GetFaceColor(void) {return m_FaceColor;}
 


// Attributes
public:
 int m_nLower;   //setrange的最小值
 int m_nUpper;   //setrange的最大值
 int m_nStep;    //步长
 int m_nCurrentPosition;  //setpos的值
 COLORREF m_FaceColor,m_clrBkGround,m_clrText;  //前景色,背景色,文字颜色的变量
 BOOL  m_bShowPercent;       //是否显示文字的变量

 BOOL        m_ScaleLine;    //有无刻度
 int         m_Side;         //刻度的方向,如0表示左边或上边有刻度,1表示右边或下边有刻度,3表示两边都有
 int         m_ScaleNumber;  //刻度的数量
 BOOL        m_Frame;        //有无边框
// Operations
public:

// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CScaleProgressCtrl)
 //}}AFX_VIRTUAL

// Implementation
public:
 int SetPos(int nPos);
 void SetShowScale(BOOL Scaleline,int side,int scalenumber);    //Scaleline是是否有刻度线,false为无刻度,true为有刻度                                                         
                                                            //side代表刻度的位置,当竖着时,0表示左边有刻度,1表示右边有刻度,3表示两边都有
                 //当水平时,0表示上边有刻度,1表示下边有刻度,3表示两边都有
                                                                //scalenumber表示刻度数量,直从3~setrange的最大值

 int  SetStep(int nStep);          //设置步长
 void SetRange(int nLower,int nUpper);
 virtual ~CScaleProgressCtrl();

 // Generated message map functions
protected:
 void DrawGradient(CPaintDC *pDC, RECT& rectClient,const int & nMaxWidth);   //水平时进度条的绘制
 void DrawEndUp(CPaintDC *pDC, RECT& rectClient,const int & maxHigh);        //竖直时进度条的绘制
 //{{AFX_MSG(CScaleProgressCtrl)
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 afx_msg void OnPaint();
 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()

public:
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
public:
 virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
public:
 virtual BOOL CreateEx(DWORD dwExStyle, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
protected:
 virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
 virtual void PreSubclassWindow();
};

  

 

   cpp文件如下:

// ScaleProgressCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ScaleProgressCtrl.h"
#include "assert.h"
//#include "MemDC.h"

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

//
// Construction/Destruction
//

CMemDC::CMemDC(CDC* pDC):CDC()
{

 ASSERT(pDC!=NULL);

 m_pDC=pDC;
 m_pOldBitmap=NULL;
 m_bMemDC=!pDC->IsPrinting();
 //
 if(m_bMemDC)
 {
  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  //为相关的现有设备准备打印
 {
  m_bPrinting=pDC->m_bPrinting;
  m_hDC=pDC->m_hDC;
  m_hAttribDC=pDC->m_hAttribDC;
 }

}

CMemDC::~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;
 }

}


/
// CScaleProgressCtrl

CScaleProgressCtrl::CScaleProgressCtrl()
{
 m_nLower=0;    //setrange最小值
 m_nUpper=100;  //setrange最大值
 m_nCurrentPosition=0;  //setpos的值
 m_nStep=10;            //setstep的值
 m_ScaleLine=false;     //默认无刻度
 m_ScaleNumber=10;      //默认10个刻度线
 m_Side=0;              //默认水平时上边有刻度或竖直时左边有刻度
 m_Frame=true;         //默认无边框

 //Initial Color of show
 m_FaceColor= COLORREF(RGB(0,0,255)); 
 //m_clrEnd= COLORREF(RGB(255,0,0));
 m_clrBkGround=::GetSysColor(COLOR_3DFACE);
 m_clrText=RGB(255,255,255);   //默认文字颜色为白色
 //Not show Word
 m_bShowPercent=FALSE;
}

CScaleProgressCtrl::~CScaleProgressCtrl()
{
}


BEGIN_MESSAGE_MAP(CScaleProgressCtrl, CProgressCtrl)
 //{{AFX_MSG_MAP(CScaleProgressCtrl)
 ON_WM_ERASEBKGND()
 ON_WM_PAINT()
 //}}AFX_MSG_MAP
 ON_WM_CREATE()
END_MESSAGE_MAP()

/
// CScaleProgressCtrl message handlers

void CScaleProgressCtrl::SetRange(int nLower,int nUpper)
{
 //This Function is to Set Range of the progress
 m_nLower=nLower;
 m_nUpper=nUpper;
 m_nCurrentPosition=nLower;
 
 CProgressCtrl::SetRange(nLower,nUpper);
}

int CScaleProgressCtrl::SetStep(int nStep)
{
 m_nStep=nStep;
 return (CProgressCtrl::SetStep(nStep));
}

BOOL CScaleProgressCtrl::OnEraseBkgnd(CDC* pDC)
{
 // TODO: Add your message handler code here and/or call default
 
 return TRUE;//CProgressCtrl::OnEraseBkgnd(pDC);
}
void CScaleProgressCtrl::DrawEndUp(CPaintDC *pDC,  RECT &rectClient, const int &maxHigh)
{
 RECT rectFill;  //显示区域
 float fStep;   //每一步的幅长
 CBrush brush;   //显示的颜色画刷

 CMemDC memDC(pDC);
 CRect a1,b1;
 if(m_ScaleLine==TRUE)
 {
  if(m_Side==0)
   rectClient.left+=5;
  if(m_Side==1)
   rectClient.right-=5;
  if(m_Side==2)
  {
   rectClient.left+=5;
   rectClient.right-=5;
  }  
  a1.top=rectClient.top;
  a1.right=rectClient.left;
  a1.bottom=rectClient.bottom;
  a1.left=rectClient.left-5;
  
  b1.top=rectClient.top;
  b1.right=rectClient.right+5;
  b1.bottom=rectClient.bottom;
  b1.left=rectClient.right;
 } 
 int  nSteps=abs(m_nUpper-m_nLower);   
 fStep=(float)(abs(rectClient.top-rectClient.bottom))/(float)(m_nUpper-m_nLower);
 
 
 //使用背景色填充客户区域
 ::SetRect(&rectFill,
  //以下为填充矩形区域的左上角x,y和右下角x,y
      rectClient.left,        //左上X 
      rectClient.top,
      rectClient.right,  //右下X
      rectClient.bottom);      //右下Y
 VERIFY(brush.CreateSolidBrush(m_clrBkGround));    
 memDC.FillRect(&rectFill,&brush); //填充背景色
 VERIFY(brush.DeleteObject());
 if(m_ScaleLine==TRUE)
 {
  COLORREF colorside;
  colorside=::GetSysColor(COLOR_3DFACE);
  VERIFY(brush.CreateSolidBrush(colorside));
  memDC.FillRect(&a1,&brush);
  memDC.FillRect(&b1,&brush);
  VERIFY(brush.DeleteObject());
 }
 
 //绘制进程条
 //if(rectFill.bottom>=maxHigh)
 //{
  ::SetRect(&rectFill,rectFill.left,rectClient.bottom-m_nCurrentPosition*fStep,rectClient.right,rectClient.bottom);   
  VERIFY(brush.CreateSolidBrush(m_FaceColor));
  memDC.FillRect(&rectFill,&brush);
  VERIFY(brush.DeleteObject());
  if(m_ScaleLine==TRUE)
  {
   COLORREF colorside;
      colorside=::GetSysColor(COLOR_3DFACE);   
   VERIFY(brush.CreateSolidBrush(colorside));
   memDC.FillRect(&a1,&brush);
   memDC.FillRect(&b1,&brush);
   VERIFY(brush.DeleteObject());
  
   int m_step;
   m_step=(rectClient.bottom-rectClient.top-1)/m_ScaleNumber;  //这里不-1可能会有一个刻度绘不上最下边的或最右边的
   
   int temp=abs(rectClient.top-rectClient.bottom);
   for(int y=rectClient.bottom-1;y>=0;y-=m_step)    //绘制刻度线
   { 
    if(m_Side==0)
    {           
     memDC.MoveTo(0,y);
     memDC.LineTo(5,y);     
    }
    if(m_Side==1)
    {
     memDC.MoveTo(rectClient.right,y);
     memDC.LineTo(rectClient.right+5,y);      
    }
    if(m_Side==2)
    {
     memDC.MoveTo(0,y);
     memDC.LineTo(5,y);
     memDC.MoveTo(rectClient.right,y);
     memDC.LineTo(rectClient.right+5,y);
    }
   }    
  //}
  return;
 }
 
}
void CScaleProgressCtrl::DrawGradient(CPaintDC *pDC,  RECT &rectClient, const int &nMaxWidth)
{
 RECT rectFill;  //显示区域
 float fStep;   //每一步的幅长
 CBrush brush;   //显示的颜色画刷
 CMemDC memDC(pDC);
 CRect a1,b1;
 if(m_ScaleLine==TRUE)
 {
  if(m_Side==0)
   rectClient.top+=5;
  if(m_Side==1)
   rectClient.bottom-=5;
  if(m_Side==2)
  {
   rectClient.top+=5;
   rectClient.bottom-=5;
  }  
  a1.top=rectClient.top-5;
  a1.left=rectClient.left;
  a1.bottom=rectClient.top;
  a1.right=rectClient.right;
  
  b1.top=rectClient.bottom;
  b1.right=rectClient.right;
  b1.bottom=rectClient.bottom+5;
  b1.left=rectClient.left;
 } 
 int  nSteps=abs(m_nUpper-m_nLower);   //总步数 
 fStep=(float)(abs(rectClient.right-rectClient.left))/(float)(m_nUpper-m_nLower);  //每步的坐标数
 
 //使用背景色填充客户区域 
 ::SetRect(&rectFill,
  //以下为填充矩形区域的左上角x,y和右下角x,y
      rectClient.left,        //左上X 
      rectClient.top,         //左上Y
      rectClient.right,       //右下X
      rectClient.bottom);     //右下Y
 VERIFY(brush.CreateSolidBrush(m_clrBkGround));    
 memDC.FillRect(&rectFill,&brush); //填充背景色
 VERIFY(brush.DeleteObject());
 if(m_ScaleLine==TRUE)
 {
  COLORREF colorside;
  colorside=::GetSysColor(COLOR_3DFACE);
  VERIFY(brush.CreateSolidBrush(colorside));
  memDC.FillRect(&a1,&brush);
  memDC.FillRect(&b1,&brush);
  VERIFY(brush.DeleteObject());
 }
 
 
 //绘制进程条
 if(rectFill.right>=nMaxWidth)
 {
  ::SetRect(&rectFill,rectFill.left,rectClient.top,rectClient.left+m_nCurrentPosition*fStep,rectClient.bottom);   
  VERIFY(brush.CreateSolidBrush(m_FaceColor));
  memDC.FillRect(&rectFill,&brush);
  VERIFY(brush.DeleteObject());
  if(m_ScaleLine==TRUE)
  {
   COLORREF colorside;
      colorside=::GetSysColor(COLOR_3DFACE);   
   VERIFY(brush.CreateSolidBrush(colorside));
   memDC.FillRect(&a1,&brush);
   memDC.FillRect(&b1,&brush);
   VERIFY(brush.DeleteObject());
  
   int m_step;
   m_step=(rectClient.right-rectClient.left-1)/m_ScaleNumber;  //刻度的步长
   int temp=abs(rectClient.right-rectClient.left);
   for(int x=0;x<=temp;x+=m_step)   //绘制刻度线
   { 
    if(m_Side==0)
    {           
     memDC.MoveTo(x,0);
     memDC.LineTo(x,5);     
    }
    if(m_Side==1)
    {
     memDC.MoveTo(x,rectClient.bottom);
     memDC.LineTo(x,rectClient.bottom+5);     
    }
    if(m_Side==2)
    {
     memDC.MoveTo(x,0);
     memDC.LineTo(x,5);
     memDC.MoveTo(x,rectClient.bottom);
     memDC.LineTo(x,rectClient.bottom+5);     
    }
   }    
  }
  return;
 }
}


void CScaleProgressCtrl::OnPaint()
{
 if(!m_Frame)
 {
  this->ModifyStyleEx(WS_EX_STATICEDGE,0);
  this->Invalidate(false); //这两句是去掉Progress的边框并显示
 }
 DWORD y=this->GetStyle();
 y=y&4;
 CPaintDC dc(this); // device context for painting
 CRect rectClient;
 GetClientRect(rectClient);

 float maxWidth((float)m_nCurrentPosition/(float)m_nUpper*(float)rectClient.right);
 float maxHigh((float)m_nCurrentPosition/(float)m_nUpper*(float)rectClient.bottom);
 //绘制
 
  if(y==4)
  DrawEndUp(&dc,rectClient,(int)maxHigh);
 if(y==0)
  DrawGradient(&dc,rectClient,(int)maxWidth);
 //显示进程条进度文字
 if(m_bShowPercent) 
 {
  CString percent;
  percent.Format("%d%%",(int)(100*(float)m_nCurrentPosition/m_nUpper));  //显示当前值的百分比  
  dc.SetTextColor(m_clrText);
  dc.SetBkMode(TRANSPARENT);
  dc.DrawText(percent,&rectClient,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
 }
 
 // Do not call CProgressCtrl::OnPaint() for painting messages
}

int CScaleProgressCtrl::SetPos(int nPos)
{
 //Set the Position of the Progress
 m_nCurrentPosition=nPos;
 return (CProgressCtrl::SetPos(nPos));
}

int CScaleProgressCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CProgressCtrl::OnCreate(lpCreateStruct) == -1)
  return -1;

 // TODO:  在此添加您专用的创建代码

 return 0;
}

BOOL CScaleProgressCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
 // TODO: 在此添加专用代码和/或调用基类

 return CProgressCtrl::Create(dwStyle, rect, pParentWnd, nID);
}

BOOL CScaleProgressCtrl::CreateEx(DWORD dwExStyle, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
 // TODO: 在此添加专用代码和/或调用基类

 return CProgressCtrl::CreateEx(dwExStyle, dwStyle, rect, pParentWnd, nID);
}

BOOL CScaleProgressCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: 在此添加专用代码和/或调用基类

 return CProgressCtrl::PreCreateWindow(cs);
}

void CScaleProgressCtrl::PreSubclassWindow()
{
 // TODO: 在此添加专用代码和/或调用基类

 CProgressCtrl::PreSubclassWindow();
}
void CScaleProgressCtrl::SetShowScale(BOOL scaleline,int side,int scalenumber)
{
 assert(scaleline==0||scaleline==1);
 m_ScaleLine=scaleline;
 assert(scalenumber>2 && scalenumber<m_nUpper);
 m_ScaleNumber=scalenumber;
 assert(side<3 && side>=0);
 m_Side=side;
 return;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值