MFC进度条编程
1. 進度條的主要功能進度條控制(Progress Control)主要用來進行數據讀寫、文件拷貝和磁盤格式等操作時的工作進度提示情況,如安裝 程序等,伴隨工作進度的進展,進度條的矩形區域從左到右利用當前活動窗口標題條的顏色來不斷填充。 進度條控制在MFC類庫中的封裝類為CProgressCtrl,通常僅作為輸出類控制,所以其操作主要是設置進度條的范圍和當 前位置,并不斷地更新當前位置。進度條的范圍用來表示整個操作過程的時間長度,當前位置表示完成情況的當前時刻。 SetRange()函數用來設置范圍,初始范圍為0-100, SetPos()函數用來設置當前位置,初始值為0,SetStep()函數 用來設置步長,初始步長為10,StepIt()函數用來按照當前步長更新位置,OffsetPos()函數用來直接將當前位置移動 一段距離。如果范圍或位置發生變化,那么進度條將自動重繪進度區域來及時反映當前工作的進展情況。進度條的對象結構進度條控制的建立方法CProgressCtrl &ProgressCtrl 建立進度條控制對象結構 Create 建立進度條控制對象并綁定對象 進度條控制類CprogressCtrl::Create的調用格式如下: BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 其中參數dwStyle用來確定進度條控制的控制風格;參數rect用來確定進度條控制的大小和位置;參數pParentWnd用來 確定進度條父窗口指針;參數nID用來確定進度條控制的控制符ID值。2 進度條控制的類屬性進度條控制的類屬性包括設置進度條最大最小控制范圍SetRange、設置進度條當前位置 SetPos、設置進度條當前位置偏
移值OffsetPos和設置進度條控制增量值SetStep。3 進度條控制的操作方法進度條控制的操作方法主要是使進度條控制并重繪進度條的StepIt函數。進度條控制的應用技巧示例1、利用應用程序向導AppWizard生成基于對象框的應用程序CProgDlg;2、在對話框中設置進度條和靜態文本控制,其ID分別為IDC_PROG和IDC_PERCENT;在對話框初始代碼中增加控制的范圍和位置:在ProgDlg.h中設置兩個數據成員,用來表示進度條的最大值和步長://ProgDlg.hclass CProgDlg:public Cdialog{ ......//其它代碼public:int m_nMax,m_nStep;...... //其它代碼}(2)在ProgDlg.cpp中設置初始狀態BOOL CProgDlg::OnInitDialog(){ Cdialog::OnInitDialog();......//其它代碼//TODO:Add extra initialization hereCProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROG);pProgCtrl->SetRange(0,200);//設置進度條范圍......//其它代碼m_nMax=200;m_nStep=10;SetTimer(1,1000,NULL);//設置進度條更新時鐘return TRUE;}(3)完善WM_TIMER消息處理,使進度條按照當前步長進行更新,同時完成進度條的百分比顯示:void CProgDlg::OnTimer(UINT nIDEvent){ //TODO:Add your message handlerCProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROG);int nPrePos=pProgCtrl->StepIt();//取得更新前位置char test[10];int nPercent=(int)(((nPrePos+m_nStep)/m_nMax*100+0.5);//可修改wsprintf(test,"%d",nPercent);GetDlgItem(IDC_PERCENT)->SetWindowText(test);Cdialog::OnTimer(nIDEvent);}------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------vc 進度條控件(一)方法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 barafx_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_FILEstatic char THIS_FILE[] = __FILE__;#endifIMPLEMENT_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, RGB(0, 0, 255));//背景色為藍色m_Progress1.SendMessage(PBM_SETBARCOLOR, 0, RGB(255, 0, 0));//前景色為紅色至于別的控件能不能按這種辦法來改變顏色,我還沒試過,大家可以試一試,如果可以,請留言告訴我,先謝謝了 。以下摘自《新編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)ArgumentsredRequired. Number in the range 0-255 representing the red component of the color.greenRequired. Number in the range 0-255 representing the green component of the color.blueRequired. Number in the range 0-255 representing the blue component of the color.二、去掉進度條邊框m_Progress1.ModifyStyleEx(WS_EX_STATICEDGE,0);m_Progress.Invalidate(false);
總結
- 上一篇: cap理论具体含义_CAP理论中的P到底
- 下一篇: java 数字转大写_Java把数字转换