链传动动态图:进度条相关

来源:百度文库 编辑:九乡新闻网 时间:2024/04/20 10:45:12
v\:* {behavior:url(#default#VML);}o\:* {behavior:url(#default#VML);}w\:* {behavior:url(#default#VML);}.shape {behavior:url(#default#VML);}

方法1:
单线程方式。
将你的任务分成多个部分,每运行一部分,就更新一下进度条。
这种方法就是很烦人。

方法2:
双线程方式。
主线程负责完成你想要的工作。副线程负责更新进度条。
更新进度条可以按照计时方法,或者根据主线程完成任务的状态来更新。
因此,你的主线程在完成任务时,还得用一个临界区随时报告任务的完成状态。

方法3:
双线程方式
主线程负责更新进度条,并且创建副线程完成任务的某部分工作。但这和单线程很像。


在VC程序的状态栏中实现进度条

  读者朋友们可能天天使用Visual C++这个强大的工具来开发应用程序,不知道注意到没有,Visual C++每次装载一个项目的时候,为了使项目加载过程不至于太单调,会在状态栏的左半部分会出现一个装载进度条,用来即时显示Visual C++装载项目的进度,当项目装载完毕后,进度条隐藏。那么这个功能是如何实现的呢?为了说明该功能的实现原理,本例提供了一个范例程序prgsbar,它演示了在编辑视图里显示文本文件,在加载文本文件时,在界面的状态条中的进度指示器仿真显示文件的加载过程,当文本装载完毕后,进度条隐藏。由于该程序在装载文件显示的进度条时无法进行拷屏操作,所以这里没有给出状态条中显示进度条的界面效果图,读者可以运行本书所带光盘中的程序代码观看相应的效果。

一、实现方法

虽然Visual C++中的MFC类提供了标准的进度指示器控件(progress control),但是我们不能在状态栏里直接使用这个控件,要解决这个问题,可以创建一个可重用C++类CProgStatusBar,这个类从CStatusBar派生,用来来实现状态条中的进度指示。整个实现过程不是很难,思路是在状态栏创建一个进度指示器控制,把它作为子窗口来对待,然后根据不同的状态来显示或者隐藏进度指示器。

在具体实现CProgStatusBar类的过程中,首先在CProgStatusBar派生类中加了一个CProgressCtrl类型的数据成员--m_wndProgBar,然后重载CstatusBar类的二个重要成员函数:OnCreate()、OnSize(),最后还要在该类中添加一个自定义成员函数OnProgress()。在上述三个函数中, OnCreate()负责在状态栏第一次被创建时接收控制,继而创建进度指示器并将它初始化为一个子窗口,它的实现代码如下:

int CProgStatusBar::OnCreate(LPCREATESTRUCT lpcs)
{
lpcs->style |= WS_CLIPCHILDREN;
VERIFY(CStatusBar::OnCreate(lpcs)==0);
VERIFY(m_wndProgBar.Create(WS_CHILD, CRect(), this, 1));
m_wndProgBar.SetRange(0,100);
return 0;
}

OnCreate()函数在状态栏的式样中加了一个WS_CLIPCHILDREN,它告诉Windows不要绘制子窗口以下的状态栏区域,这样可以减少屏幕闪烁。接着OnCreate()函数创建进度指示器控件并将它的范围设置成[0,100]。注意在这里创建进度指示器控件时没有用WS_VISIBLE,因为我们要实现的目标是仅仅当装载文件时进度条才显现,其余时间内应用程序都隐藏它。

熟悉Windows编程的人都清楚,无论何时,只要在某个窗口里添加子窗口,那么一定要负责管理它的大小尺寸,也就是说,当父窗口大小改变后,子窗口的大小也要跟着作相应的改变。一般来说,这个工作由父窗口的WM_SIZE消息处理函数OnSize()来作,所以我们也要处理该类的OnSize()函数。

void CProgStatusBar::OnSize(...)
{
CStatusBar::OnSize(...);
CRect rc;
GetItemRect(0, &rc);//获取状态条的第一个窗口的尺寸;
m_wndProgBar.MoveWindow(&rc,FALSE);//移动进度条到状态条的第一个窗口;
}  

从上述代码可以看出,CProgStatusBar::OnSize()将进度指示器放在了状态栏的第一个窗格,这个窗格通常用来显示程序的"就绪"信息和命令提示信息。注意这里不论进度指示器是处于可见状态还是隐藏状态,MoveWindow都照样起作用--所以即便是进度指示器处于隐藏状态,其窗口大小同样是可调的。

调整好进度指示器的窗口大小后,下面要作的就是进度指示器的显示,进度指示器当前进度状态的显示在CProgStatusBar::OnProgress中完成。它有一个类型为UINT的入口参数:参数值的范围从0到100,表示进度百分比,0表示进度没开始,100表示全部完成。如果这个参数的值大于0,则OnProgress显示进度控制并设置指示器的位置;如果参数值等于0,则 OnProgress隐藏进度控制。

虽然子窗口控件通常都是放在父窗口能绘制的区域的最上面,但这样做在绘制方面是有一定风险的。在隐藏/显示进度控制时尤其如此,这时候会出现两个问题:第一,因为进度指示器显示在状态栏的第一个窗格位置,所以如果进度条指示器显示时已经显示有状态信息,那么进度指示器和状态信息文本就会有冲突,相互干扰。之所以会这样,是因为进度控制假设其绘制背景是干净的,并且只绘制进度控制的着色部分。解决这个问题最简单的方法是调用CStatusBar::SetWindowText(NULL)函数在显示进度指示器之前打扫一下环境卫生,清除以前的文本。

对于状态栏来说,SetWindowText函数的作用是设置状态栏第一个窗格的文本。反之,当调用OnProgress(0)清除进度控制时也存在类似的问题,CProgStatusBar::OnProgress 隐藏进度控制后,状态栏第一个窗格该显示什么信息呢?一般显示"就绪"或其它的提示信息。当应用程序不做任何事情时,MFC程序总是在这个位置显示资源串AFX_IDS_IDLEMESSAGE表示的文本,其缺省值为"就绪",当然读者朋友们可以在当前项目的RC文件中任意修改这个值,不管怎样,在MFC程序的状态栏中显示"就绪"信息很容易,需要作的就是在CProgStatusBar::OnProgress()函数中调用语句GetParent()->PostMessage(WM_SETMESSAGESTRING,AFX_IDS_IDLEMESSAGE)向父窗口发送一个WM_SETMESSAGESTRING消息就可以了,需要注意的是,使用消息WM_SETMESSAGESTRING时必须包含它的定义文件"afxpriv.h",否则程序会报告编译错误。

上述CprogStatusBar类实现了状态栏中包含进度条控件,该类的使用方法很简单,首先在应用程序的CmainFrame类中用CProgStatusBar代替CStatusBar声明实例,然后在任何想要显示进度控制指示的地方调用CProgStatusBar::OnProgress。本例中定义了一个消息MYWM_PROGRESS,它将进度条当前的进度作为WPARAM参数传递到CProgStatusBar::OnProgress()函数。

经过上述处理,想要使用进度指示的任何对象都可以通过发送一个消息到主框架来调用状态栏进行进度条的显示。例如,在例子程序中,文档的Serialize()函数在加载文本文件时,利用Sleep()函数仿真耗时加载,每隔150毫秒报告一次进度状态。如果你不想从文档发送Windows消息,可以用MFC的视图更新机制来做。你可以发明一个"暗示"代码以及一个小结构来保存进度百分比数据,并通过向框架发送MYWM_PROGRESS消息调用暗示信息。这是从文档到视图/框架传递进度控制信息的最省事的方式。

二、编程步骤

1、 启动Visual C++6.0,生成一个单文档应用程序prgsbar,项目的视图类的基类选择CEdit类;

2、 在程序的Resource.h文件中添加自定义消息的定义:

#define MYWM_PROGRESS (WM_USER+1)

3、 在程序的主框架窗口CMainFrame类的头文件中声明MYWM_PROGRESS的消息响应函数afx_msg LRESULT OnProgress(WPARAM wp, LPARAM lp),在该类的实现中添加消息映射ON_MESSAGE(MYWM_PROGRESS,OnProgress);

4、 将CMainFrame类中的工具条对象改为CProgStatusBar m_wndStatusBar;

5、 重载CPrgsbarDoc::Serialize(CArchive& ar)函数,用来处理读取文件时的进度条仿真;

6、 添加代码,编译运行程序。

三、程序代码

////////////////////////////////////////////CprogStatusBar类的头文件;
// Status bar with progress control.
class CProgStatusBar : public CStatusBar {
public:
CProgStatusBar();
virtual ~CProgStatusBar();
CProgressCtrl& GetProgressCtrl() {
return m_wndProgBar;
}
void OnProgress(UINT pct);
protected:
CProgressCtrl m_wndProgBar; // the progress bar
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
DECLARE_MESSAGE_MAP()
DECLARE_DYNAMIC(CProgStatusBar)
};
///////////////////////////////////////////////////////////////////////////// CprogStatusBar类的实现文件;
#include "StdAfx.h"
#include "ProgBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CProgStatusBar, CStatusBar)
BEGIN_MESSAGE_MAP(CProgStatusBar, CStatusBar)
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////
CProgStatusBar::CProgStatusBar()
{}
CProgStatusBar::~CProgStatusBar()
{}
////////////////////////////////////////创建状态条时也创建进程条
int CProgStatusBar::OnCreate(LPCREATESTRUCT lpcs)
{
lpcs->style |= WS_CLIPCHILDREN;
VERIFY(CStatusBar::OnCreate(lpcs)==0);
VERIFY(m_wndProgBar.Create(WS_CHILD, CRect(), this, 1));
m_wndProgBar.SetRange(0,100); //设置进程条的范围;
return 0;
}
////////////////////////////////////////////////////使进程度条的尺寸与状态条的尺寸同步变化;
void CProgStatusBar::OnSize(UINT nType, int cx, int cy)
{
CStatusBar::OnSize(nType, cx, cy);
CRect rc;
GetItemRect(0, &rc);
m_wndProgBar.MoveWindow(&rc,FALSE);
}
////////////////////////////////////////////////////////////根据pct的当前值对进程条进行设置
void CProgStatusBar::OnProgress(UINT pct)
{
CProgressCtrl& pc = m_wndProgBar;
DWORD dwOldStyle = pc.GetStyle();
DWORD dwNewStyle = dwOldStyle;
if (pct>0) //如果pct>0,将显示进度条
dwNewStyle |= WS_VISIBLE;
else //否则隐藏进度条;
dwNewStyle &= ~WS_VISIBLE;
if (dwNewStyle != dwOldStyle) {
SetWindowText(NULL); //显示进度条前清空状态条;
SetWindowLong(pc.m_hWnd, GWL_STYLE, dwNewStyle);
//设置进度条处于显示状态;
}
// 设置进度条的当前位置;
pc.SetPos(pct);
if (pct==0)
// 如果pct等于0,通知主框架窗口显示空闲信息;
GetParent()->PostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);
}
/////////////////////////////////////////////////////////////////////////文档装载处理函数;
void CPrgsbarDoc::Serialize(CArchive& ar)
{
CWnd* pFrame = AfxGetMainWnd();
if (!ar.IsStoring()) {
for (int pct=10; pct<=100; pct+=10) {//对文档装载进行仿真处理;
Sleep(150);
if (pFrame)
pFrame->SendMessage(MYWM_PROGRESS, pct);
}
}
if (pFrame)
pFrame->SendMessage(MYWM_PROGRESS, 0);
((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);//显示文本文件的内容;
}


四、小结

本例虽然是介绍的如何在状态条中包含进度条,但是读者朋友们可以从中受到启发,开拓思路,将该思想应用到类似的应用当中去,例如在状态条中实现显示图像等。


位图进度条

图一 例子效果

玩过破天的朋友知道,游戏更新时进度是用位图表示的,我觉的挺漂亮的,于是自己动手做了一个类来实现那种效果。

这个类的名字叫CBmpProgCtrl,继承于CStatic,使用方法如下。

1、首先要将BmpProgCtrl.h和BmpProgCtrl.cpp添加到工程中。

2、导入两幅位图,作为前景和背景。资源标识分别为IDB_FORE和IDB_BACK.

3、在对话框上,放置一个"Static Text"控件,修改其ID,只要不是默认的IDC_STATIC就可以了。

4、让这个控件和一个Control类型的变量关联,如变量名可以叫m_bmpprog。

5、找到该变量定义的地方,应该是CStatic m_bmpprog,修改CStatic为CBmpProgCtrl。并将头文件BmpProgCtrl.h包含进来。

6、调用该类的方法。

类成员方法介绍

void GetRange(int &lower,int &upper)返回进度条范围。
int GetPos()获得当前位置
int StepIt( )以当前步长使进度条增长
int SetStep( int nStep )设置步长
int SetPos( int nPos )设置位置
void SetRange( int nLower, int nUpper )设置进度条范围。

具体的可以看源代码。你可以修改它以符合自己的需要。你可能觉的这些方法很熟悉,是的,我参考了CProgressCtrl的方法名。

结束语

这个东西,比较简单,你可以很容易就使用。


一条语句改变进度条颜色及去掉进度条边框  

      改变进度条颜色 

在VC里想改变进度条颜色,在网上找了很多方法,都很麻烦,觉得很郁闷。后来想起在用VB做时,增经用API实现过,很简单。后来再一查,原来是SendMessage这个函数,几经试验,终于成功,高兴,与大家分享!!!!

      代码如下:    

      m_Progress1.SendMessage(PBM_SETBKCOLOR, 0, #0000ff);//背景色为蓝色

m_Progress1.SendMessage(PBM_SETBARCOLOR, 0, #ff0000);//前景色为红色

 

       至于别的控件能不能按这种办法来改变颜色,我还没试过,大家可以试一试,如果可以,请留言告诉我,先谢谢了 。

以下摘自《新编win32API大全》:

函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。

    函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);

    参数:

    hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。

    Msg:指定被发送的消息。

    wParam:指定附加的消息指定信息。

    IParam:指定附加的消息指定信息。

    返回值:返回值指定消息处理的结果,依赖于所发送的消息。

    备注:需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。

    如果指定的窗口是由调用线程创建的,则窗口程序立即作为子程序调用。如果指定的窗口是由不同线程创建的,则系统切换到该线程并调用恰当的窗口程序。线程间的消息只有在线程执行消息检索代码时才被处理。发送线程被阻塞直到接收线程处理完消息为止。

    Windows CE:Windows CE不支持Windows桌面平台支持的所有消息。使用SendMesssge之前,要检查发送的消息是否被支持。

    速查:Windows NT:3.1及以上版本:Windows:95及以上版本;Windows CE:1.0及以上版本;头文件:winuser.h;输入库:user32.lib;Unicode:在Windows NT环境下以Unicode和ANSI方式实现。

以下摘自MSDN:

RGB(red, green, blue)

Arguments

red

Required. Number in the range 0-255 representing the red component of the color.

green

Required. Number in the range 0-255 representing the green component of the color.

blue

Required. Number in the range 0-255 representing the blue component of the color.

 

二、         去掉进度条边框

m_Progress1.ModifyStyleEx(WS_EX_STATICEDGE,0);

m_Progress.Invalidate(false);

 



转可以设置刻度的进度条

现在做的软件上要用图形来显示串口传过来的信号值大小,最简单的办法,莫过于用进度条显示了。但是在使用的过程中发现一个问题,就是没有刻度。如果有美工,问题也好解决,在没有美工的情况下,只好靠自己动手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(#0000ff); 
 //m_clrEnd= COLORREF(#ff0000);
 m_clrBkGround=::GetSysColor(COLOR_3DFACE);
 m_clrText=#ffffff;   //默认文字颜色为白色
 //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_ScaleNumber=scalenumber;
 assert(side<3 && side>=0);
 m_Side=side;
 return;
}




Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1254501