MFC 建立屬性嚮導

2020-08-10 10:38:35

描述:

程式:單文件應用程式

屬性頁:3個屬性頁

一個屬性表由一個CPropertySheet物件和一個或多個CPropertyPage物件構成。(這句話先看一遍就行)

 

 

建立應用程式,就不說了。說一下新建三個表單Dialog。

1、資源檢視 - Dialog - 插入3個 Dialog,將表單中的空間全部刪掉,更改ID 如下。

2、將每個Dialog對話方塊style屬性設定爲:child

3、爲每個對話方塊建立類,對話方塊上右鍵--->新增類。注意基礎類別爲CPropertyPage

4、給三個對話方塊新增內容,隨便弄幾個控制元件

Prop1:三個 radio button和一個listBox

爲控制元件建立關聯變數,Radio Button只用對第一個建立,因爲屬性修改了Group後,會自動對後面兩個進行關聯:類別爲value

還需要對後面的ListBox新增的變數進行初始化。

爲CProp1這個類新增虛擬函式OnInitDialog

函數程式碼:

BOOL CProp1::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	// TODO:  在此新增額外的初始化
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("北京");
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("上海");
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("深圳");
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("廣州");
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("成都");
	((CListBox*)GetDlgItem(IDC_WORKADDR))->AddString("杭州");

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 異常: OCX 屬性頁應返回 FALSE
}

Prop2:四個checkBox,同樣也要對每個控制元件都進行建立關聯變數,型別爲BOOL

Prop3:一個ComboBox

同樣對ComboBox重寫虛擬函式OnInitDialog進行初始化

BOOL CProp3::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	// TODO:  在此新增額外的初始化
	((CComboBox*)GetDlgItem(IDC_SALARY))->AddString("1000 元以下");
	((CComboBox*)GetDlgItem(IDC_SALARY))->AddString("1000 - 2000 元");
	((CComboBox*)GetDlgItem(IDC_SALARY))->AddString("2000 - 5000 元");
	((CComboBox*)GetDlgItem(IDC_SALARY))->AddString("5000 元以上");

	((CComboBox*)GetDlgItem(IDC_SALARY))->SetCurSel(0);

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 異常: OCX 屬性頁應返回 FALSE
}

至此,屬性視窗建好了。後面就要利用前面說過的CPropertySheet類,CPropertySheet類物件表示屬性表,它由一個或多個CPropertyPage物件構成。前面建立的三個對話方塊都是CPropertyPage,可以將他們放在一個CPropertySheet中組成一個屬性表。

5、建立一個繼承自CPropertySheet的類:類嚮導--->MFC類

6、編輯剛纔新增的這個類: .h檔案和 .cpp檔案

至此,含有三個對話方塊的屬性表準備好了。

7、在單文件視窗的選單欄上新增一個名叫屬性的選單,並對屬性進行單擊響應實現。

建立:

實現:通過類嚮導,建立剛纔建立的選單的命令響應函數

用屬性表單物件(一個CPropertySheet物件)的DoModal之前,先呼叫SetWizardMode函數,此成員函數用來建立一個作爲嚮導的屬性頁,它會爲每個屬性頁面(CPropertyPage)生成上一步,下一步,取消按鈕。DoModal返回ID_WIZFINISH或IDCANCEL。

void CMFC屬性頁和嚮導View::OnProp()
{
	// TODO: 在此新增命令處理程式程式碼
	CPropSheet propSheet("個人資訊");
	propSheet.SetWizardMode();  // DoModal呼叫該函數將屬性頁變爲嚮導
	if (ID_WIZFINISH == propSheet.DoModal())  // ID_WIZFINISH:使用者點選完成,IDCANCEL:取消
	{
		//這裏可以先不用做什麼
	}
}

8、啓動程式,點選屬性選單,可以看到:

爲了解決步驟8出現的問題,需要對三個屬性對話方塊進行修改,而且,在點選下一步的時候,應該對選擇情況進行判斷,並作出相應處理。

9、修改嚮導過程中按鈕問題,並完善按鈕點選事件:

需要用到三個虛擬函式:

OnSetActive()  //在該虛擬函式中呼叫SetWizardButtons修改嚮導中按鈕

void SetWizardButtons( DWORD dwFlags );

SetWizardButtons參數: dwFlags 參數可以是下列值的組合: 

· PSWIZB_BACK                         Back按鈕。
· PSWIZB_NEXT                          Next按鈕。
· PSWIZB_FINISH                        Finish按鈕。
· PSWIZB_DISABLEDFINISH    Disabled Finish按鈕。

OnWizardNext()  //在點選下一步按鈕的時候進行判斷  返回-1:頁面不改變,返回0:頁面跳轉到下一頁

OnWizardFinish()  //點選完成按鈕處理事件

對Prop1和Prop2新增OnSetActive()、OnWizardNext()虛擬函式,對Prop3新增OnSetActive()、OnWizardFinish() 虛擬函式:

CProp1的兩個函數程式碼:

BOOL CProp1::OnSetActive()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);

	return CPropertyPage::OnSetActive();
}

LRESULT CProp1::OnWizardNext()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	UpdateData();
	if (m_occupation == -1)
	{
		MessageBox("請選擇你的職業!");
		return -1;
	}
	if (m_workAddr == "")
	{
		MessageBox("請選擇你的工作地址!");
		return -1;
	}

	return CPropertyPage::OnWizardNext();
}

CProp2的兩個函數程式碼:

LRESULT CProp2::OnWizardNext()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	UpdateData();
	if (m_code | m_book | m_game | m_money)
	{
		return CPropertyPage::OnWizardNext();
	}
	MessageBox("請選擇興趣愛好!");
	return -1;
}


BOOL CProp2::OnSetActive()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);

	return CPropertyPage::OnSetActive();
}

CProp3的兩個函數程式碼:

BOOL CProp3::OnSetActive()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);

	return CPropertyPage::OnSetActive();
}


BOOL CProp3::OnWizardFinish()
{
	// TODO: 在此新增專用程式碼和/或呼叫基礎類別
	int index = ((CComboBox*)GetDlgItem(IDC_SALARY))->GetCurSel();
	((CComboBox*)GetDlgItem(IDC_SALARY))->GetLBText(index, m_salary);

	return CPropertyPage::OnWizardFinish();
}

10、改變按鈕後,執行結果:

11、將嚮導中頁面中的資訊輸出到單文件主頁面的view檢視中

①view類中標頭檔案新增接收嚮導變數的值

public:
	int m_occupation;  // 工作
	CString m_workAddr;  // 工作地址
	BOOL m_like[4];  // 興趣愛好
	CString m_salary;  // 薪水範圍

②建構函式中初始化變數(便於理解 我的專案採用的是中文)

CMFC屬性頁和嚮導View::CMFC屬性頁和嚮導View()
{
	// TODO: 在此處新增構造程式碼
	m_occupation = -1;
	m_workAddr = "";
	m_salary = "";
	memset(m_like,0,sizeof(m_like));

}

③對nDraw函數進行編輯

void CMFC屬性頁和嚮導View::OnDraw(CDC* pDC)
{
	CMFC屬性頁和嚮導Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此處爲本機數據新增繪製程式碼
	CFont font;
	font.CreatePointFont(300, "華文行楷");
	CFont *pOldFont = pDC->SelectObject(&font);
	CString strTmp = "你的職業是:";
	switch (m_occupation)
	{
	case 0:
		strTmp += "程式猿";
		break;
	case 1:
		strTmp += "程式媛";
		break;
	case 2:
		strTmp += "BOSS";
		break;
	default:
		break;
	}
	pDC->TextOut( 0, 0, strTmp);

	strTmp = "你的工作地點是:";
	strTmp += m_workAddr;
	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);
	pDC->TextOut(0, tm.tmHeight, strTmp);

	strTmp = "你的興趣愛好是:";
	if (m_like[0])
	{
		strTmp += " 寫程式碼";
	}
	if (m_like[1])
	{
		strTmp += " 看書";
	}
	if (m_like[2])
	{
		strTmp += " 打遊戲";
	}
	if(m_like[3])
	{
		strTmp += " 賺錢";
	}
	pDC->TextOut(0, tm.tmHeight * 2, strTmp);

	strTmp = "你的薪資範圍是:";
	strTmp += m_salary;
	pDC->TextOut(0, tm.tmHeight * 3, strTmp);

	pDC->SelectObject(pOldFont);
}

④繼續編寫「屬性」選單的實現函數

void CMFC屬性頁和嚮導View::OnProp()
{
	// TODO: 在此新增命令處理程式程式碼
	CPropSheet propSheet("個人資訊");
	propSheet.SetWizardMode();  // DoModal呼叫該函數將屬性頁變爲嚮導
	if (ID_WIZFINISH == propSheet.DoModal())  // ID_WIZFINISH:使用者點選完成,IDCANCEL:取消
	{
		m_occupation = propSheet.m_prop1.m_occupation;
		m_workAddr = propSheet.m_prop1.m_workAddr;
		m_like[0] = propSheet.m_prop2.m_code;
		m_like[1] = propSheet.m_prop2.m_book;
		m_like[2] = propSheet.m_prop2.m_game;
		m_like[3] = propSheet.m_prop2.m_money;
		m_salary = propSheet.m_prop3.m_salary;

		Invalidate();
	}
}

12、結果:

over!