vc 进度条控件.docx
- 文档编号:9891208
- 上传时间:2023-02-07
- 格式:DOCX
- 页数:40
- 大小:55.42KB
vc 进度条控件.docx
《vc 进度条控件.docx》由会员分享,可在线阅读,更多相关《vc 进度条控件.docx(40页珍藏版)》请在冰豆网上搜索。
vc进度条控件
vc进度条控件
(一)
2011-05-2717:
49:
12| 分类:
MFC| 标签:
|字号大中小 订阅
方法1:
单线程方式。
将你的任务分成多个部分,每运行一部分,就更新一下进度条。
这种方法就是很烦人。
方法2:
双线程方式。
主线程负责完成你想要的工作。
副线程负责更新进度条。
更新进度条可以按照计时方法,或者根据主线程完成任务的状态来更新。
因此,你的主线程在完成任务时,还得用一个临界区随时报告任务的完成状态。
方法3:
双线程方式
主线程负责更新进度条,并且创建副线程完成任务的某部分工作。
但这和单线程很像。
在VC程序的状态栏中实现进度条
读者朋友们可能天天使用VisualC++这个强大的工具来开发应用程序,不知道注意到没有,VisualC++每次装载一个项目的时候,为了使项目加载过程不至于太单调,会在状态栏的左半部分会出现一个装载进度条,用来即时显示VisualC++装载项目的进度,当项目装载完毕后,进度条隐藏。
那么这个功能是如何实现的呢?
为了说明该功能的实现原理,本例提供了一个范例程序prgsbar,它演示了在编辑视图里显示文本文件,在加载文本文件时,在界面的状态条中的进度指示器仿真显示文件的加载过程,当文本装载完毕后,进度条隐藏。
由于该程序在装载文件显示的进度条时无法进行拷屏操作,所以这里没有给出状态条中显示进度条的界面效果图,读者可以运行本书所带光盘中的程序代码观看相应的效果。
一、实现方法
虽然VisualC++中的MFC类提供了标准的进度指示器控件(progresscontrol),但是我们不能在状态栏里直接使用这个控件,要解决这个问题,可以创建一个可重用C++类CProgStatusBar,这个类从CStatusBar派生,用来来实现状态条中的进度指示。
整个实现过程不是很难,思路是在状态栏创建一个进度指示器控制,把它作为子窗口来对待,然后根据不同的状态来显示或者隐藏进度指示器。
在具体实现CProgStatusBar类的过程中,首先在CProgStatusBar派生类中加了一个CProgressCtrl类型的数据成员--m_wndProgBar,然后重载CstatusBar类的二个重要成员函数:
OnCreate()、OnSize(),最后还要在该类中添加一个自定义成员函数OnProgress()。
在上述三个函数中,OnCreate()负责在状态栏第一次被创建时接收控制,继而创建进度指示器并将它初始化为一个子窗口,它的实现代码如下:
intCProgStatusBar:
:
OnCreate(LPCREATESTRUCTlpcs)
{
lpcs->style|=WS_CLIPCHILDREN;
VERIFY(CStatusBar:
:
OnCreate(lpcs)==0);
VERIFY(m_wndProgBar.Create(WS_CHILD,CRect(),this,1));
m_wndProgBar.SetRange(0,100);
return0;
}
OnCreate()函数在状态栏的式样中加了一个WS_CLIPCHILDREN,它告诉Windows不要绘制子窗口以下的状态栏区域,这样可以减少屏幕闪烁。
接着OnCreate()函数创建进度指示器控件并将它的范围设置成[0,100]。
注意在这里创建进度指示器控件时没有用WS_VISIBLE,因为我们要实现的目标是仅仅当装载文件时进度条才显现,其余时间内应用程序都隐藏它。
熟悉Windows编程的人都清楚,无论何时,只要在某个窗口里添加子窗口,那么一定要负责管理它的大小尺寸,也就是说,当父窗口大小改变后,子窗口的大小也要跟着作相应的改变。
一般来说,这个工作由父窗口的WM_SIZE消息处理函数OnSize()来作,所以我们也要处理该类的OnSize()函数。
voidCProgStatusBar:
:
OnSize(...)
{
CStatusBar:
:
OnSize(...);
CRectrc;
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、启动VisualC++6.0,生成一个单文档应用程序prgsbar,项目的视图类的基类选择CEdit类;
2、在程序的Resource.h文件中添加自定义消息的定义:
#defineMYWM_PROGRESS(WM_USER+1)
3、在程序的主框架窗口CMainFrame类的头文件中声明MYWM_PROGRESS的消息响应函数afx_msgLRESULTOnProgress(WPARAMwp,LPARAMlp),在该类的实现中添加消息映射ON_MESSAGE(MYWM_PROGRESS,OnProgress);
4、将CMainFrame类中的工具条对象改为CProgStatusBarm_wndStatusBar;
5、重载CPrgsbarDoc:
:
Serialize(CArchive&ar)函数,用来处理读取文件时的进度条仿真;
6、添加代码,编译运行程序。
三、程序代码
////////////////////////////////////////////CprogStatusBar类的头文件;
//Statusbarwithprogresscontrol.
classCProgStatusBar:
publicCStatusBar{
public:
CProgStatusBar();
virtual~CProgStatusBar();
CProgressCtrl&GetProgressCtrl(){
returnm_wndProgBar;
}
voidOnProgress(UINTpct);
protected:
CProgressCtrlm_wndProgBar;//theprogressbar
afx_msgintOnCreate(LPCREATESTRUCTlpCreateStruct);
afx_msgvoidOnSize(UINTnType,intcx,intcy);
DECLARE_MESSAGE_MAP()
DECLARE_DYNAMIC(CProgStatusBar)
};
/////////////////////////////////////////////////////////////////////////////CprogStatusBar类的实现文件;
#include"StdAfx.h"
#include"ProgBar.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_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()
{}
////////////////////////////////////////创建状态条时也创建进程条
intCProgStatusBar:
:
OnCreate(LPCREATESTRUCTlpcs)
{
lpcs->style|=WS_CLIPCHILDREN;
VERIFY(CStatusBar:
:
OnCreate(lpcs)==0);
VERIFY(m_wndProgBar.Create(WS_CHILD,CRect(),this,1));
m_wndProgBar.SetRange(0,100);//设置进程条的范围;
return0;
}
////////////////////////////////////////////////////使进程度条的尺寸与状态条的尺寸同步变化;
voidCProgStatusBar:
:
OnSize(UINTnType,intcx,intcy)
{
CStatusBar:
:
OnSize(nType,cx,cy);
CRectrc;
GetItemRect(0,&rc);
m_wndProgBar.MoveWindow(&rc,FALSE);
}
////////////////////////////////////////////////////////////根据pct的当前值对进程条进行设置
voidCProgStatusBar:
:
OnProgress(UINTpct)
{
CProgressCtrl&pc=m_wndProgBar;
DWORDdwOldStyle=pc.GetStyle();
DWORDdwNewStyle=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);
}
/////////////////////////////////////////////////////////////////////////文档装载处理函数;
voidCPrgsbarDoc:
:
Serialize(CArchive&ar)
{
CWnd*pFrame=AfxGetMainWnd();
if(!
ar.IsStoring()){
for(intpct=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、在对话框上,放置一个"StaticText"控件,修改其ID,只要不是默认的IDC_STATIC就可以了。
4、让这个控件和一个Control类型的变量关联,如变量名可以叫m_bmpprog。
5、找到该变量定义的地方,应该是CStaticm_bmpprog,修改CStatic为CBmpProgCtrl。
并将头文件BmpProgCtrl.h包含进来。
6、调用该类的方法。
类成员方法介绍:
voidGetRange(int&lower,int&upper)返回进度条范围。
intGetPos()获得当前位置
intStepIt()以当前步长使进度条增长
intSetStep(intnStep)设置步长
intSetPos(intnPos)设置位置
voidSetRange(intnLower,intnUpper)设置进度条范围。
具体的可以看源代码。
你可以修改它以符合自己的需要。
你可能觉的这些方法很熟悉,是的,我参考了CProgressCtrl的方法名。
结束语
这个东西,比较简单,你可以很容易就使用。
一条语句改变进度条颜色及去掉进度条边框
改变进度条颜色
在VC里想改变进度条颜色,在网上找了很多方法,都很麻烦,觉得很郁闷。
后来想起在用VB做时,增经用API实现过,很简单。
后来再一查,原来是SendMessage这个函数,几经试验,终于成功,高兴,与大家分享!
!
!
!
代码如下:
m_Progress1.SendMessage(PBM_SETBKCOLOR,0,RGB(0,0,255));//背景色为蓝色
m_Progress1.SendMessage(PBM_SETBARCOLOR,0,RGB(255,0,0));//前景色为红色
至于别的控件能不能按这种办法来改变颜色,我还没试过,大家可以试一试,如果可以,请留言告诉我,先谢谢了。
以下摘自《新编win32API大全》:
函数功能:
该函数将指定的消息发送到一个或多个窗口。
此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。
而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。
函数原型:
LRESULTSendMessage(HWNDhWnd,UINTMsg,WPARAMwParam,LPARAMIParam);
参数:
hWnd:
其窗口程序将接收消息的窗口的句柄。
如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:
指定被发送的消息。
wParam:
指定附加的消息指定信息。
IParam:
指定附加的消息指定信息。
返回值:
返回值指定消息处理的结果,依赖于所发送的消息。
备注:
需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。
如果指定的窗口是由调用线程创建的,则窗口程序立即作为子程序调用。
如果指定的窗口是由不同线程创建的,则系统切换到该线程并调用恰当的窗口程序。
线程间的消息只有在线程执行消息检索代码时才被处理。
发送线程被阻塞直到接收线程处理完消息为止。
WindowsCE:
WindowsCE不支持Windows桌面平台支持的所有消息。
使用SendMesssge之前,要检查发送的消息是否被支持。
速查:
WindowsNT:
3.1及以上版本:
Windows:
95及以上版本;WindowsCE:
1.0及以上版本;头文件:
winuser.h;输入库:
user32.lib;Unicode:
在WindowsNT环境下以Unicode和ANSI方式实现。
以下摘自MSDN:
RGB(red,green,blue)
Arguments
red
Required.Numberintherange0-255representingtheredcomponentofthecolor.
green
Required.Numberintherange0-255representingthegreencomponentofthecolor.
blue
Required.Numberintherange0-255representingthebluecomponentofthecolor.
二、 去掉进度条边框
m_Progress1.ModifyStyleEx(WS_EX_STATICEDGE,0);
m_Progress.Invalidate(false);
vc进度条控件
(二).
2011-05-2717:
49:
50| 分类:
MFC| 标签:
|字号大中小 订阅
转可以设置刻度的进度条
现在做的软件上要用图形来显示串口传过来的信号值大小,最简单的办法,莫过于用进度条显示了。
但是在使用的过程中发现一个问题,就是没有刻度。
如果有美工,问题也好解决,在没有美工的情况下,只好靠自己动手DIY了。
由于以前没有做过控件,就在网上找了别人做的拿来参考,于是,就发现了颜色渐变进度条的代码。
这个代码严格说来并不完全,进度条只能横着不能竖起来。
在读懂了颜色渐变进度条后,我做出了带刻度的进度条控件。
目前,我做的这个控件有以下功能:
1、设置前景色
2、设置背景色
3、设置有无刻度,刻度位置,刻度数量
4、设置进度条有无边框
5、设置文字显示
头文件如下:
#if!
defined(AFX_GRADIENTPROGRESSCTRL_H__91ECB8BC_A7DA_42EB_B2C5_37419D31B753__INCLUDED_)
#defineAFX_GRADIENTPROGRESSCTRL_H__91ECB8BC_A7DA_42EB_B2C5_37419D31B753__INCLUDED_
#endif
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#if!
defined(AFX_MEMDC_H__A68B97E6_DDB4_4B4F_8A18_429844C3659C__INCLUDED_)
#defineAFX_MEMDC_H__A68B97E6_DDB4_4B4F_8A18_429844C3659C__INCLUDED_
#endif
classCMemDC:
publicCDC
{
public:
CMemDC(CDC*pDC);
CMemDC*operator->(){returnthis;}
operatorCMemDC*(){returnthis;}
virtual~CMemDC();
private:
CBitmapm_bitmap;
CBitmap*m_pOldBitmap;
CDC*m_pDC;
CRectm_rect;
BOOLm_bMemDC;
};
////////////////////////////////////////////////
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vc 进度条控件 进度条 控件
![提示](https://static.bdocx.com/images/bang_tan.gif)