在利用MFC
編制應用程序尤其是涉及到數值分析與模擬程序時,要進行大量的數值運算,如在屏幕上顯示三維、二維圖形和圖像就需要進行數據擬合、樣條以及插值等算法,而且為了保證精度,運算時數據點一般還采用浮點甚至雙精度浮點數,這樣應用程序就需要大量的CPU
時間來完成相應的工作,一般持續幾分鐘、幾十分鐘甚至更多的時間。如果應用程序不輸出一些信息的話,常常會讓人誤解系統是不是死掉了。因此Windows
系統提供了一個函數:
LoadCursor( UINT nIDResource ) const ;
通過這個函數可以改變鼠標的形狀為沙漏來表明系統正處于一個耗時的過程。但是一般而言這種改變很容易讓人忽略,并且不知道當前進程完成了多少,還剩下多少。
在MFC 中,提供了進程條控件CProgressCtrl
類,利用該類可以很方便地顯示進程的完成狀況。為了顯示當前進程的完成狀況,用進程條控件CProgressCtrl
類來實現有很多種方法,如采用多線程編程方法,通過線程通信來顯示,也可以在同一線程當中,采用含進程條控件CProgressCtrl
類的無模式對話框來顯示。但是這幾種方法都比較復雜且不方便,需要占用一定的系統資源,狀態顯示響應也不是十分迅捷。
Windows
應用程序一般在其底部有一個小條通稱狀態條。狀態條的右邊是幾個可以動態增加或刪除的狀態格,MFC
中提供了狀態條控件CStatusBar
類來完成狀態格的管理。因此我們可以采用在應用程序的狀態條中增加一個進程條狀態格的方法來顯示當前進程任務的完成狀態。顯然相比于前面所述的方法,這種方法比較方便且容易實現,不占用系統資源,狀態顯示響應十分迅捷。下面具體闡述實現方法:
用AppWizard 創建一個工程文件pBar,單文檔應用或者多文檔應用皆可。其他選項均可采用缺省。
在Visual Studio 的工作臺,選擇“View"菜單下的“Resource
Symbols"菜單命令,彈出對話框后按下“New"
按鈕,增加一條新的符號ID_INDICATOR_PROGRESS_PANE 并采用系統分配的缺省ID
值,如圖1 所示。
在MainFrm.cpp
文件的狀態條狀態格指示數組(緊接在消息映射代碼段后)中增加資源符號ID_INDICATOR_PROGRESS_PANE
或者其ID 值。注意如果將符號ID_INDICATOR_PROGRESS_PANE
放在數組的最后則表明進程條狀態格將在狀態條的最右邊,如果你將符號ID_INDICATOR_PROGRESS_PANE
放在數組的前面則表明進程條狀態格將在狀態條的最左邊,如果將符號ID_INDICATOR_PROGRESS_PANE
放在數組的中間則表明進程條狀態格將在狀態條的中間。具體參見如下代碼:
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_PROGRESS_PANE,
// means the progress pane in far left.
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
打開資源編輯器,選擇字符串表,單擊鼠標右鍵,選擇“New
String"命令(或者通過工作臺的“Insert"菜單選擇“New
String"命令),彈出字符串屬性編輯對話框如圖2 所示,在ID
欄鍵入符號ID_INDICATOR_PROGRESS_PANE,在Caption
編輯欄鍵入空格。注意空格的多少將決定狀態條中進程狀態格的長度,具體見圖2。
在頭文件MainFrm.h 中,增加兩個變量:一個為CProgressCtrl 控件設為m_Progress;另一個為邏輯步爾變量設為m_bCreated,該變量用來標志CProgressCtrl
控件是否成功創建。
在源文件MainFrm.cpp 的OnCreate() 函數中,初始化m_bCreated 為FALSE。如下所示:
m_bCreated = FALSE;
模擬一個耗時過程函數OnSomeLongProcess()
來演示狀態條中的進程狀態格。這里簡單地采用睡眠函數來模擬一個耗時過程。函數代碼如下:
void CMainFrame::OnSomeLongProcess()
{
RECT MyRect;
// substitute 1 with the zero -based index of
your status bar pane. For example, if you put your
// pane first in the indicators array,
you put 0, second you put 1, etc.
m_wndStatusBar.GetItemRect(1, &MyRect);
if (m_bCreated == FALSE)
{
//Create the progress control
m_Progress.Create(WS_VISIBLE|WS_CHILD,
MyRect, &m_wndStatusBar, 1);
m_Progress.SetRange(0,100);.
//Set the range to between 0 and 100
m_Progress.SetStep(1); // Set the step amount
m_bCreated = TRUE;
}
// Now we'll simulate a long process:
for (int I = 0; I < 100; I ++)
{
Sleep(20);
m_Progress.StepIt();
}
}
狀態條中的進程狀態格創建成功后,如果應用程序主窗口尺寸發生變化,進程狀態格的大小不會自動適應主窗口的變化,因此需要重載主窗口的OnSize()函數。通過ClassWizard
在主窗口中增加WM_SIZE 消息映射函數,如圖3 所示。
具體的源代碼如下:
void
CMainFrame::
OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if(m_bCreated == TRUE){
RECT rc;
m_wndStatusBar.GetItemRect(1, &rc);
// Reposition the progress control correctly!
m_Progress.SetWindowPos( &wndTop, rc.left, rc.top, rc.right
?。璻c.left,rc.bottom -rc.top, SWP_SHOWWINDOW);
}
}
打開資源編輯器,在“查看”菜單下增加“Test"菜單命令,ID
設為ID_TEST。然后利用ClassWizard 增加一條消息映射函數OnTest(),代碼如下:
void CMainFrame::OnTest()
{
// TODO: Add your command handler code here
OnSomeLongProcess();
}
在完成所有以上步驟后,編譯、運行程序,選擇“查看”菜單下的“Test"菜單命令就會看到狀態條中的進程狀態格的進程顯示情況。
上面我們用一個簡單的睡眠函數模擬了耗時過程中,狀態條的進程狀態格的顯示情況。在實際應用中我們只需將源碼中OnSomeLongProcess()
函數替換成相應的耗時過程函數即可。