MFC 自定義子線程新建對話框的數據傳輸問題 -- 以及由此對MFC的一些思考

    MFC是很老的技術了,但在工控領域,還是有優勢的。只是其中一些技術比較隱蔽,不能想當然。

    廢話少說,上菜~~

    一個簡單而常用的工控架構: 一個主對話框,對話框中有一個編輯控件輸入, 和一個OK按鈕控件。此處省略菜單,各種特殊事件響應,不在此討論。如下圖:

    故事開始,左鍵點擊OK按鈕,後臺子線程開始運行。子線程運行過程中,彈出一個非模態對話框,用於一部分信息輸入。如下:

    關鍵點來了:彈出的子對話框 pDlgOption 中的 combobox 控件 m_combo_x,需要根據主對話框的輸入進行初始化以及讀取操作。於是我想當然的這麼幹:

UINT ThreadFunc_TCS_SPOTFIRE(LPVOID lpParam)
{	
	CDlgTCSSpotfire* pDlg = (CDlgTCSSpotfire*) lpParam;	//main dialog
	CDlgTCSOption pDlgOption;	// modeless input dialog

	if(pDlgOption.DoModal() == IDOK){
		CString combo_info;
		pDlgOption.m_combo_x.GetWindowTextA(combo_info);		
	}

	::PostMessage(pDlg->GetSafeHwnd(), TCS_SPOTFIRE_DATA_HANDLE_END, NULL, NULL);	// 

	return TRUE;
}

    很不幸,編譯通過,但是運行時錯誤。問題在於這句:

		pDlgOption.m_combo_x.GetWindowTextA(combo_info);		

    子線程表示,在我的管轄範圍,讀寫訪問你的控件是違法的。


    解決之道,直接來不行,可以繞個道。

    1. 先在子對話框的類中聲明需要傳輸的數據。如定義一個 vector 等等,把需要對子對話框進行的操作信息放到裏面。

    2. 在子線程裏面對子對話框的類數據成員傳數據,如上一部定義的 vector,當然必須是public的。

    3. 以上完成後,再調用 DoModal()

    4. 最後對子對話框控件的操作,在它的類中完成,如重載 OnInitDialog(),OnBnClickOk() 等等。

    代碼如下:

UINT ThreadFunc_TCS_SPOTFIRE(LPVOID lpParam)
{	
	CDlgTCSSpotfire* pDlg = (CDlgTCSSpotfire*) lpParam;	//main dialog
	CDlgTCSOption pDlgOption;	// modeless input dialog

	pDlgOption.testno_vec.clear();
	for(vector<string>::iterator it = log_data.test_vec.begin(); it != log_data.test_vec.end(); ++it){
		pDlgOption.testno_vec.push_back(*it);
	}

	if(pDlgOption.DoModal() == IDOK){
	}

	::PostMessage(pDlg->GetSafeHwnd(), TCS_SPOTFIRE_DATA_HANDLE_END, NULL, NULL);	// 

	return TRUE;
}

BOOL CDlgTCSOption::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  Add extra initialization here
	for(vector<string>::iterator it = testno_vec.begin(); it != testno_vec.end(); ++it){
		m_combo_x.AddString((*it).c_str());
	}
	m_combo_x.SetCurSel(0);
	UpdateData(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}


    小小思考:對話框雖然在子線程中聲明定義,但是對話框運行時有自己的線程,它的控件部分會被自己的線程綁定,不能在子線程中訪問控件,否則會出現兩個線程同時操作一個控件的問題。然而對話框的非控件數據成員沒有被綁定,仍然可以被聲明對話框的線程調用。

    但是,在主對話框的線程中,訪問它的子對話框控件是沒問題的。猜想是,子對話框的線程會自動 assign 到 主對話框中。

    這是MFC定義各類對象,相互間的權限問題。估計是安全考慮。這是需要在 MFC 或者 C++ 編程中需要注意的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章