1. 程式人生 > >MFC之為對話方塊新增變數

MFC之為對話方塊新增變數

進來一直在學MFC,現在基本都在VS2008下練習寫一些小程式,偶爾也會在VC6.0下,很多教程都是在VC6.0下寫的程式碼,但是做一個大工程的話,個人感覺VS還是比較好的。

順便也發表一下自己的觀點。帶實驗的時候看到一些剛接觸C語言的同學就用VS,他們毫無程式設計經驗,對C語言本身都是一知半解,寫的又都是控制檯程式,通常很小很小的程式,最多也就100行程式碼了,可是非要用VS,如此功能強大的VS讓他們用來寫hello world,我都感覺有些糟蹋了。通常情況下都是他們被VS難倒而不是C語言本身。我個人認為,在初學C、C++時,VC6.0就是一個很好的平臺,即簡單又便捷,當學到一定程度後,如果想研究VS,再去在VS平臺上做東西,當然VC6.0也可以做很多東西,只是相對來說VS整合的東西更多更全。當然我不是說誰好誰壞,只是選擇適合自己的才是明智的。

不扯廢話了,上正題,說說今天我遇到的一個很foolish的問題。

我看了MFC的網路程式設計,模仿書上敲了一段程式碼,但是結果執行時,還未彈出對話方塊,就彈出了錯誤警告,如圖:


點選重試跟蹤進去,發現assert 的地方的程式碼是:

_AFXCMN_INLINE int CListCtrl::InsertColumn(int nCol, const LVCOLUMN* pColumn)
	{ ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn); }

主要問題就是IsWindow(m_hWnd)上面,也就是我訪問了一個非法的控制代碼。於是乎,老一套,設斷點除錯跟蹤程式碼,跟蹤發現在執行下面這段程式碼時便出問題了:
	CTest2Dlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();

於是傻呵呵的去查DoModal()函式的詳細說明,結果一無所獲了。接下來苦思冥想,怎麼也想不出問題在哪裡。上網搜搜,也未搜到對應的答案,苦惱了。。。。

一狠心,重新建了一個工程,重頭開始一點一點的試,寫一段就除錯執行一把,終於把問題找出來了。

我在對話方塊中添加了一個List Control控制元件,前面我寫了一篇文章記述了關於訪問控制元件的幾種方法,在這裡就不羅嗦了,有興趣的可以看我之前的文章。有一種訪問方式便是為控制元件新增一個變數,與控制元件繫結。而我在第一次建工程的時候,傻呵呵的手動去添加了,也就是直接在程式碼裡新增的,結果少加了一句最關鍵的程式碼,也就是繫結的程式碼,如下:

void CTest2Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_PackList);
}

最關鍵的就是DDX_Control(pDX, IDC_LIST1, m_PackList);,我第一次的時候沒有加這句話,所以就導致了變數m_PackList沒有與控制元件IDC_LIST1繫結,而在後續使用的時候就使得系統不知道m_PackList是什麼,在assert的時候,判斷m_PackList也就不是一個window了,這樣就出現了前面所說的情況,彈出了那個框框。。。。

那麼手動為控制元件新增變數時都需要做哪些工作呢,在VS2008中,需要在兩個地方新增程式碼,一個是dialog類中,宣告一個與控制元件對應的public 控制變數,一個就是上面的定義綁定了。

在宣告變數時,需要注意的是變數的型別要注意,一定要是控制元件對應的,否則白搭了。。。。。

下面來看看DDX_Control函式,其原型是:

void AFXAPI DDX_Control( CDataExchange* pDX, int nIDC, CWnd& rControl );

引數:
pDX 指向CDataExchange物件的指標。框架提供了這個物件以建立資料交換的環境,包括其方向。
nIDC 與控制元件屬性相關的被子類化的控制元件的資源ID。
rControl 對對話方塊、表格視或控制元件視的成員變數的引用,將與該變數發生資料交換。

說明:
DDX_Control函式管理著在對話方塊、表格視或控制元件視中被子類化的控制元件與對話方塊、表格視或控制元件視的CWnd資料成員之間的資料交換。

到這,問題就算解決了,這種問題太不好找了,編譯沒有錯誤,費了好久好久。也可能是我還是生手,需要好好努力,等我成大牛了,也許這種問題i就不是問題了。

加油,向前走!