(一)List Control控件的使用
新近開發(fā)了一個攝像機標定的MFC程序,標定完成后期望將求得的攝像機參數(shù)直觀地顯示到應用程序的界面上來,。起初的方案是為每一個參數(shù)都建立一個Edit控件,,并對每一個控件設定一個控制變量,,將該變量與相應參數(shù)對應起來,。這樣做是可行的,,但當參數(shù)眾多時比較繁瑣。鑒于此,,決定在程序中使用List Control控件,,將參數(shù)以List的形式呈現(xiàn)在界面上。以下是我在基于對話框的MFC程序中添加List Control控件的步驟,。
1.新加ListControl 控件,,屬性中的style屬性頁下的View選擇Report。并設置其對應的控制變量如:m_ListCtrl,。
2.初始化,,即設置列。
m_ListCtrl.InsertColumn(0,"參數(shù)名"); //插入列
m_ListCtrl.InsertColumn(1,"參數(shù)值");
m_ListCtrl.InsertColumn(2,"備注");
CRect rect3;
m_ListCtrl.GetClientRect(rect3); //獲得當前客戶區(qū)信息
m_ListCtrl.SetColumnWidth(0,rect3.Width()/4); //設置列的寬度,。
m_ListCtrl.SetColumnWidth(1,rect3.Width()*2/4);
m_ListCtrl.SetColumnWidth(2,rect3.Width()/4);
這部分初始化操作,,最好放在對話框類的OnInitDialog()函數(shù)里,自動初始化,。
3.插入數(shù)據(jù)
m_ListCtrl.InsertItem(0,"參數(shù)1"); //插入第一個數(shù)據(jù),,即第0條數(shù)據(jù)。先插入,,然后在修改其他的信息,。
m_ListCtrl.SetItemText(0,1,"參數(shù)1值"); //修改第0條數(shù)據(jù)的其他信息。
m_ListCtrl.SetItemText(0,2,"無");
SetItemText()函數(shù)負責向列表里添加字符串,。當需要添加的是非字符串的數(shù)據(jù)類型時,,需要先轉(zhuǎn)換為字符串類型再用SetItemText()完成添加。假設所需要添加的是double類型的浮點數(shù),。
double dbl=1.2345678;
char str[16]={0};
sprintf(str, "%lf", dbl);
m_ListCtrl.InsertItem(0,"參數(shù)1");
m_ListCtrl.SetItemText(0,1,str); //等價于m_ListCtrl.SetItemText(0,1,“1.2345678”);
需要注意的是用sprintf族函數(shù)時,,char數(shù)組一定要足夠大,否則程序運行時會出現(xiàn)錯誤提示“ Stack around the variable 'str' was corrupted ”,,解決方法是把數(shù)組改大一些,。
4.刪除所有數(shù)據(jù)。有些程序中需要刷新顯示數(shù)據(jù),,如果直接利用上述方法,,則會將當前顯示數(shù)據(jù)追加在前一次數(shù)據(jù)行的后面,造成隨著刷新次數(shù)的增加數(shù)據(jù)行線性增加的問題,。解決方法是每次在插入數(shù)據(jù)之前刪除已有數(shù)據(jù),,使用下面語句:
m_ListCtrl.DeleteAllItems();
5.如何設置ListView控件的完全行(Full Row)選項。 這個控件有個地方常常很惱人,,那就是在報告視圖中選中一行時,,它只加亮最左邊的一個欄目,。解決方法:向ListView控件發(fā)送一個VM_SETEXTENDEDLISTVIEWSTYLE消息。
::SendMessage(m_ListCtrl.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
這條語句可以加在OnInitDialog()函數(shù),,也可以加在負責插入數(shù)據(jù)的代碼部分,。
(二)MFC中實時顯示系統(tǒng)時間
下面給出在基于對話框的MFC應用程序的Edit控件中實時顯示系統(tǒng)時間的方法。首先來了解一下幾個主要的與定時器有關的函數(shù),。
SetTimer()函數(shù)表示定義一個定時器,。根據(jù)定義指定的窗口,在指定的窗口(CWnd)中實現(xiàn)OnTimer事件,,這樣,,就可以響應事件了。
SetTimer有兩個函數(shù),。一個是全局的函數(shù)::SetTimer()
UINT SetTimer( HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
其中hWnd 是指向CWnd的指針,,即處理Timer事件的窗口類。說道窗口類(CWnd),,我們有必要來看一下CWnd的繼承情況:CWnd有以下子類:CFrameWnd,CDialog,CView,CControlBar等類,。這也意味這些類中都可以定義SetTimer事件。
SetTimer()的另外一種定義為:
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );
nIDEvent:是指設置這個定時器的iD,,即身份標志,,這樣在OnTimer()事件中,才能根據(jù)不同的定時器,,來做不同的事件響應,。這個ID是一個無符號的整型。
nElapse:是指時間延遲,。單位是毫秒,。這意味著,每隔nElapse毫秒系統(tǒng)調(diào)用一次Ontimer(),。
void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD): Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application’s message queue and handled by the CWnd object。意思指:指定應用程序提供的TimerProc回調(diào)函數(shù)的地址,,來處里這個WM_TIMER 事件,。如果是NULL,則由定義這個Timer事件的CWnd對象來處理該Timer事件,。它將WM_TIMER消息傳遞給這個對象,,通過實現(xiàn)這個對象的OnTimer()事件來處理這個Timer事件。所以,,一般情況下,,我們將這個值設為NULL,由設置該定時器的對象中的OnTimer()函數(shù)來處理這個事件,。對于SetTimer()可以在初始化當中添加,!
OnTimer()函數(shù)是響應用SetTimer()函數(shù)設定的時鐘發(fā)送的時鐘消息的,,你沒設定時鐘,就不會有時鐘消息,,OnTimer()里的語句當然也不會被調(diào)用,。為類添加WM_TIMER消息響應,會看到類中出現(xiàn)OnTimer(UINT nIDEvent)函數(shù),。
KillTimer()同SetTimer()一樣,,它也有兩個,一個是全局的::KillTimer(),另一個是CWnd的一個函數(shù),。聲明如下:
//全局函數(shù)
BOOL KillTimer( HWND hWnd, // handle of window that installed timer
UINT uIDEvent // timer identifier
);
//CWnd函數(shù)
BOOL KillTimer( int nIDEvent );
這兩個函數(shù)表示的意思是將ID為nIDEVENT的定時器移走,使其不再作用,。其用法如同SetTimer()一樣。一般將KillTimer()語句放在需要移去定時器的地方或程序退出是的窗口銷毀過程中,。
在基于對話框的MFC應用程序中,,添加一個Edit控件,ID標號為IDC_EDIT_TIME,。
在OnInitDialog()函數(shù)中添加下面語句:
SetTimer(1,1000,NULL);//1000毫秒發(fā)生一次定時器事件
為類添加WM_TIMER消息響應函數(shù)OnTimer(UINT_PTR nIDEvent):
void CTestDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnTimer(nIDEvent);
CString str;
CTime theTime = CTime::GetCurrentTime();
str.Format("%02d:%02d:%02d",theTime.GetHour(),theTime.GetMinute(),theTime.GetSecond());
SetDlgItemText(IDC_EDIT_TIME,str);
}
為類添加WM_DESTROY消息響應函數(shù)OnDestroy():
void CTestDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
KillTimer(1);
}