經過編寫串口助手工具學習MFC過程 編程
由於之前也作過幾回MFC的編程,每次都是項目完成時,MFC基本操做清楚了,可是過好長時間再也不接觸MFC的項目,再次作MFC的項目時,又要從頭開始熟悉。此次經過作一個串口助手再次熟悉一下MFC,並作了一下記錄,以便方便之後查閱。作的過程當中可能是遇到問題直接百度和谷歌搜索來的,因此不少都是不求甚解,知其然不知其因此然。另外作此工具只是爲了熟悉瞭解,許多功能尚未完善!(開發工具VS2008) windows
(二)經過「打開串口」按鈕瞭解基本操做 編輯器
須要什麼控件直接從這個對話框編輯器直接添加便可。 函數
一、添加一個按鈕用於打開串口 工具
二、設置按鈕控件的屬性 學習
調出屬性對話框,設置ID 開發工具
Caption是靜態選項,程序中能夠動態設置按鈕顯示的文字,這裏修更名字的好處是,方便編寫代碼是查看這個按鈕是什麼。 this
設置這個控件的ID名稱,這樣MFC就會對這個名稱起一個對應的數字真正的ID,能夠在工程中Resource.h 查看。 3d
工程中,右鍵.rc文件->選擇」查看代碼」,下圖是部分截圖,就會看對按鈕的尺寸和位置和顯示內容、ID名字。 指針
三、添加按鈕變量
再將這個按鈕向對話框對應的類添加變量,在按鈕上右鍵->選擇添加變量->在變量名的文本框裏填入變量名。以下圖:
添加後工程的變化,在對話框的頭文件「serial testDlg.h : 頭文件」,CserialtestDlg類中增長對象成員變量(頭文件名和類名是創建工程時起的)
「serial testDlg.cpp : 實現文件」中
像註釋說明的那樣,按鈕變量m_ComBoComContrl和控件IDC_BUTTON_OPENCOM關聯起來了,之後對此變量操做也就是對該按鈕控件進行操做。
另一種操做按鈕的方法是CWnd* GetDlgItem(ID)函數,返回窗口中指定參數ID的子元素的句柄,能夠經過返回的句柄對相應的控件操做。而且這個操做能夠在任何地方使用,按鈕變量只能在對話框類中使用同,相應比獲取句柄方式有侷限性,也不夠方便。(我的理解。)
CWnd* GetDlgItem(ID)的應用後面有涉及到。
四、添加按鈕控件響應事件
方法一:在對話框裏,雙擊按鈕。
直接跳轉到「serial testDlg.cpp : 實現文件」自動生成以下函數
//串口打開關閉按鈕
void CserialtestDlg::OnBnClickedButtonOpencom()
{
}
大部分的控件經過雙擊都會生成相應的響應事件函數。
方法二:右擊控件按鈕->「添加事件處理函數」
能夠修改消息類型,不一樣的控件裏的消息類型不一樣,此處選擇點擊消息,BN_CLICKED;
函數處理程序名稱設置好,類列表中能夠選擇生成在哪一個類中,按默認的生成,即在對話框類中生成。
在「serial testDlg.cpp : 實現文件」生成的 消息增長此消息,包括消息類型、控件ID、響應事件的函數指針。
經過以上信息,若是不使用嚮導增長變量和消息事件,也能夠本身添加。
//串口打開關閉按鈕
/*
這個函數主要實現功能是打開串口時,若是沒有建立串口,先建立串口,根據串口原來的狀態,實現串口打開或關閉。同時設置串口按鈕的文字內容「打開或關閉串口」,設置串口顯示的圖片。
將串口參數設置的幾個ComboBox組合框實現使能和失能的控制*/
void CserialtestDlg::OnBnClickedButtonOpencom()
{
// TODO: 在此添加控件通知處理程序代碼
//組織用於CComSerial類指針實例化時的數據,將對話框類的控件變量的地址獲取給CComSerial
// 類,CComSerial類從這些控件獲取相應數據,對串口參數進行設置
struct StruComCWnds stComCWnds;
stComCWnds.pComboBaudActual = this->pComboBaudActual;
stComCWnds.pComboSelSeri = &this->m_ComboSelSeri;
stComCWnds.pComboCheckBit = &this->m_ComboCheckBit;
stComCWnds.pComboDataBit = &this->m_ComboDataBit;
stComCWnds.pComboStopBit = &this->m_ComboStopBit;
if(NULL == pCComSer) //第一次點按鈕時pCComSer爲Null
{
pCComSer = new CComSerial(&stComCWnds);
if(NULL == pCComSer)
{
return;
}
}
//判斷點擊前串口是什麼狀態,原來鏈接狀態,如今關閉;原來關閉,如今打開
if(pCComSer->GetConStatus())
{
//原來鏈接,如今要關閉
pCComSer->CloseComm(); //串口關閉操做
((CButton *)GetDlgItem(IDC_BUTTON_OPENCOM))->SetBitmap(hBitmapComOFF); //設置按鈕圖片
SetDlgItemText(IDC_BUTTON_OPENCOM, _T("打開串口")); //設置按鈕顯示文字內容
//串口參數設置的組合框使能,能夠進行設置
m_ComboSelSeri.EnableWindow(TRUE);
m_ComboBaud.EnableWindow(TRUE);
m_ComboCheckBit.EnableWindow(TRUE);
m_ComboStopBit.EnableWindow(TRUE);
m_ComboDataBit.EnableWindow(TRUE);
m_ComboBaudEdit.EnableWindow(TRUE);
}
else
{
//原來未鏈接如今要鏈接
if(pCComSer->OpenComm()) //串口打開操做
{
//打開串口成功,設置按鈕圖片和顯示文字內容
((CButton *)GetDlgItem(IDC_BUTTON_OPENCOM))->SetBitmap(hBitmapComON);
SetDlgItemText(IDC_BUTTON_OPENCOM, _T("關閉串口"));
//串口參數設置的組合框失能,打開串口後不能夠再進行設置
m_ComboSelSeri.EnableWindow(FALSE);
m_ComboBaud.EnableWindow(FALSE);
m_ComboCheckBit.EnableWindow(FALSE);
m_ComboStopBit.EnableWindow(FALSE);
m_ComboDataBit.EnableWindow(FALSE);
m_ComboBaudEdit.EnableWindow(FALSE);
}
}
}
此處注意,在這裏動態分配了內存,pCComSer = new CComSerial(&stComCWnds);
因此在銷燬對話框時也要釋放此內存,可在對話框類的析構函數裏增長對動態內存分配的釋放。由於這個類是MFC自動生成的,在WINDOWS的銷燬工做裏會自動調用系統自動生成類的析構函數,因此把釋放功能增長到這個函數裏。
CserialtestDlg::~CserialtestDlg()
{
//pCComSer->CloseComm();
if(pCComSer != NULL)
{
delete pCComSer;
pCComSer = NULL;
}
}
由於C++還在學習過程當中,對類的設置很差。函數中實現了幾個功能,下面介紹一下:
(1)控件的使能和失能
控件的EnableWindow(TRUE)和EnableWindow(FALSE)實現控件的使能和失能。函數執行效果。
(2)按鈕顯示文字
SetDlgItemText(IDC_BUTTON_OPENCOM, _T("關閉串口"));
從函數和名字中能夠看出SetDlgItemText();設置控件的文本顯示,第一個參數就是控件的ID號,第二個參數是文本信息。下面這幾行代碼也能夠實現一樣的功能。
CString str ;
str.Format(_T("串口打開"));
SetDlgItemText(IDC_BUTTON_OPENCOM,str);
百度這個函數:Windows API宏,在WinUser.h中根據是否已定義Unicode被分別定義爲SetWindowTextW和SetWindowTextA,這兩個函數改變指定窗口的標題欄的文本內容(若是窗口有標題欄)。若是指定窗口是一個控件,則改變控件的文本內容。特別須要引發重視的是,【SetWindowText函數不改變在其餘應用程序中的控件的文本內容,若是須要能夠用另一個SendMessage函數發送一條WM_SETTEXT消息】
查看定義,都是三個定義的參數,沒有發現有兩個參數的重載,不知緣由。
_T("關閉串口")做用將字符串轉爲當前環境的字符寬度。如本工程設置的是Unicode寬字符。
和此功能相似的函數GetWindowText(),從函數名字能夠看出此功能是獲取控件文本內容的。從文本編輯框edit控件中讀取數據就是用的這個方法。介紹文本編輯框時再詳細介紹。
CString str;
GetDlgItem(IDC_EDIT_DATASEND)->GetWindowText(str); //從發送框讀數據
(3)按鈕顯示圖片
往上查找說有三種方法,本例中用其中之一,
a、將圖片導入到資源管理器中,ID設置爲IDB_BITMAP_COMON和IDB_BITMAP_COMOFF。
如何導入,右鍵工程->添加->資源->選擇」BITMAP」。注意BITMAP文件必須確實是轉換成此格式的,不能只改後綴名,那樣圖片格式不對是不能實現功能的。
b、在顯示圖片前加載圖片,下面兩行代碼。
//按鈕開關
hBitmapComON = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_COMON)); // IDB_BITMAP_TEST爲資源圖片ID
hBitmapComOFF = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_COMOFF)); // IDB_BITMAP_TEST爲資源圖
hBitmapComON變量和 hBitmapComOFF變量在CserialtestDlg中定義,以下圖所示。這兩個變量就是這兩個圖片的句柄。
c、而後得到按鈕句柄並調用SetBitmap便可。
((CButton *)GetDlgItem(IDC_BUTTON_OPENCOM))->SetBitmap(hBitmapComON);
此處再次使用GetDlgItem()函數來獲取按鈕控件的句柄,相應的改爲變量也能實現相同功能。
m_ComboComContrl.SetBitmap(hBitmapComON);
此句與上句功能相同,一個得到控件句柄來操做,一個用控件變量來操做。
(4)按鈕Bitmap屬性對顯示圖片效果的影響
個人工程在unicode字符集下上面添加圖片的方法,可行,可是在使用多字節字符集就不行了。爲此我選擇了使用Unicode字符集(寬字符)。
VC++6.0 默認是多字節字符集,VS2005之後默認是使用Unicode字符集。
使用unicode字符集編譯出的軟件 就像windows vista以後的軟件,使用多字節字符集編譯出的就像是XP時代的軟件,但看到有人用VS2013|的多字節字符集編譯的效果也是像vista以後的效果。
Unicode字符集和多字節字符集中的字符寬度不一樣,前者是寬字符,一個字符兩個字節,後者是一個字節。操做過程當中須要多注意。