【VC编程技巧】窗体☞3.2利用CPropertySheet制作设置工具.


前一章【VC编程技巧】窗体☞3.1利用字体对话框和颜色对话框改变静态标签中字体颜色背景. 我讲了MFC内建的资源对话框,字体对话框,颜色对话框,这一章来讲属性对话框[CPropertyShee]。

在项目开发中CPropertySheet对话框非常重要,作用也非常大,如果一个非常强大的系统在运行前需要做很多配置时,我们就可以使用CPropertySheet做一个配置工具。当软件发布时,我们需要向用户提供安装包,也可以利用CPropertySheet来制作安装包。那么下面我先做一个配置工具,在后续我也会利用CPropertySheet做一个安装程序。


(一)CPropertySheet的详细说明

请参考MSDN:CPropertySheet选件类


(二)配置工具例子效果图

【VC编程技巧】窗体☞3.2利用CPropertySheet制作设置工具._第1张图片

(三)制作配置工具

说明 :本程序是利用VS2013制作的例子。


1)利用VS2013的工程向导制作创建对话框程序

2)将继承于CDialogEx的主对话框类(CPropSheetDemoDlg)修改成:继承于CPropertySheet,并且删掉对应的对话框资源。

3)主对话框类(CPropSheetDemoDlg)中只留下如下由工程向导生成的函数,其余都删除掉。

virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

4)按照CPropertySheet类设计住对话框类的构造函数。

CPropertySheet( ); 
explicit CPropertySheet(
   UINT nIDCaption,
   CWnd* pParentWnd = NULL,
   UINT iSelectPage = 0 
);
explicit CPropertySheet(
   LPCTSTR pszCaption,
   CWnd* pParentWnd = NULL,
   UINT iSelectPage = 0 
);


此时,属性对话框CPropertyShee的框架已经完成!现在可以根据项目需要向属性对话框t中添加属性页了。

5)通过类向导创建继承于CPropertyPage类的属性页类(需要关联对话框资源),添加到属性对话框中就OK了。


(四)代码分享

属性对话框代码:PropSheetDemoDlg.h,PropSheetDemoDlg.cpp

// PropSheetDemoDlg.h : ヘッダー ファイル
//

#pragma once
#include "School.h"
#include "Work.h"

// CPropSheetDemoDlg ダイアログ
class CPropSheetDemoDlg : public CPropertySheet
{
	DECLARE_DYNAMIC(CPropSheetDemoDlg)
// コンストラクション
public:
	//重写构造函数
	//CPropSheetDemoDlg(CWnd* pParent = NULL);	// 標準コンストラクター
	CPropSheetDemoDlg(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
// ダイアログ データ
//	enum { IDD = IDD_PROPSHEETDEMO_DIALOG };//对话框资源删掉

	//PropertySheetのIDS
	static int IDS[];//属性对话框的中按钮的ID

protected:
	CSchool m_school;//属性页
	CWork   m_work;//属性页

// 実装
protected:
	HICON m_hIcon;

	// 生成された、メッセージ割り当て関数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	DECLARE_MESSAGE_MAP()

private:
	void SetTabTitle(int nID, LPSTR pszText);
	void HideButton(int nID);
	void MoveButton(int nID);
};


// PropSheetDemoDlg.cpp : 実装ファイル
//

#include "stdafx.h"
#include "PropSheetDemo.h"
#include "PropSheetDemoDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// アプリケーションのバージョン情報に使われる CAboutDlg ダイアログ

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// ダイアログ データ
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート

// 実装
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CPropSheetDemoDlg ダイアログ
int CPropSheetDemoDlg::IDS[] = {IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP};

IMPLEMENT_DYNAMIC(CPropSheetDemoDlg, CPropertySheet)
//変更
CPropSheetDemoDlg::CPropSheetDemoDlg(LPCTSTR pszCaption, CWnd* pParentWnd/* = NULL*/, UINT iSelectPage/* = 0*/)
	:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
	AddPage(&m_school);
	AddPage(&m_work);
}


BEGIN_MESSAGE_MAP(CPropSheetDemoDlg, CPropertySheet)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()


// CPropSheetDemoDlg メッセージ ハンドラー

BOOL CPropSheetDemoDlg::OnInitDialog()
{
	CPropertySheet::OnInitDialog();

	// "バージョン情報..." メニューをシステム メニューに追加します。

	// IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
	//  Framework は、この設定を自動的に行います。
	SetIcon(m_hIcon, TRUE);			// 大きいアイコンの設定
	SetIcon(m_hIcon, FALSE);		// 小さいアイコンの設定

	// TODO: 初期化をここに追加します。

	//设置属性页标题 
	SetTabTitle(0, _T("学歴"));
	SetTabTitle(1, _T("仕事時間"));
	
	//隐藏HELP按钮 
	HideButton(IDHELP);
	
	//移动按OK按钮,取消按钮,应用按钮
	MoveButton(IDOK);
	MoveButton(IDCANCEL);
	MoveButton(ID_APPLY_NOW);


	return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}

void CPropSheetDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CPropertySheet::OnSysCommand(nID, lParam);
	}
}

//设置指定属性页标题
void CPropSheetDemoDlg::SetTabTitle(int nID, LPSTR pszText)
{
	TC_ITEM item;  
	item.mask = TCIF_TEXT;  
	item.pszText = pszText;
	GetTabControl()->SetItem(nID, &item);

}

//设置指定属性对话框的是否显示
void CPropSheetDemoDlg::HideButton(int nID)
{
	for (int i = 0; i < sizeof(CPropSheetDemoDlg::IDS)/sizeof(int); i++)
	{
		if(CPropSheetDemoDlg::IDS[i] == nID)
		{
			//HideButton
			CWnd *pWnd = GetDlgItem(nID);
			pWnd->ShowWindow(FALSE);
		}
	}
}

//移动指定对话框的位置
void CPropSheetDemoDlg::MoveButton(int nID)
{
	for (int i = 0; i < sizeof(CPropSheetDemoDlg::IDS)/sizeof(int); i++)
	{
		if(CPropSheetDemoDlg::IDS[i] == nID)
		{
			//MoveButton
			CRect rectBtn;
			int nSpacing = 6;        // space between two buttons...
			CWnd *pWnd = GetDlgItem(nID);
			pWnd->GetWindowRect (rectBtn);
			ScreenToClient (&rectBtn);
			int btnWidth = rectBtn.Width();
			rectBtn.left = rectBtn.left + (btnWidth + nSpacing)* 1;
			rectBtn.right = rectBtn.right + (btnWidth + nSpacing)* 1;
			pWnd->MoveWindow(&rectBtn);
		}
	}
}


属性页代码:     

school属性页school.h,school.cpp 

#pragma once


// CSchool ダイアログ

class CSchool : public CPropertyPage
{
	DECLARE_DYNAMIC(CSchool)

public:
	CSchool();
	virtual ~CSchool();

// ダイアログ データ
	enum { IDD = IDD_DIALOG1 };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedRadio1();
	afx_msg void OnBnClickedRadio2();
	afx_msg void OnBnClickedRadio3();
	virtual BOOL OnApply();
	virtual void OnOK();
	virtual BOOL OnKillActive();

private:
	int m_nRadioFlag;
public:
	virtual BOOL OnInitDialog();
};

// School.cpp : 実装ファイル
//

#include "stdafx.h"
#include "PropSheetDemo.h"
#include "School.h"
#include "afxdialogex.h"


// CSchool ダイアログ

IMPLEMENT_DYNAMIC(CSchool, CPropertyPage)

CSchool::CSchool()
	: CPropertyPage(CSchool::IDD)
{
	m_nRadioFlag = 0;
}

CSchool::~CSchool()
{
}

void CSchool::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CSchool, CPropertyPage)
	ON_BN_CLICKED(IDC_RADIO1, &CSchool::OnBnClickedRadio1)
	ON_BN_CLICKED(IDC_RADIO2, &CSchool::OnBnClickedRadio2)
	ON_BN_CLICKED(IDC_RADIO3, &CSchool::OnBnClickedRadio3)
END_MESSAGE_MAP()


// CSchool メッセージ ハンドラー


void CSchool::OnBnClickedRadio1()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 1;//小学校
	SetModified();
}


void CSchool::OnBnClickedRadio2()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 2;//中学校
	SetModified();
}


void CSchool::OnBnClickedRadio3()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 3;//大学
	SetModified();
}


BOOL CSchool::OnApply()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。

	return CPropertyPage::OnApply();
}


void CSchool::OnOK()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	CString strMsg = _T("");
	switch ( m_nRadioFlag )
	{
	case 1:
		strMsg =  _T("小学校");
		break;
	case 2:
		strMsg =  _T("中学校");
		break;
	case 3:
		strMsg =  _T("大学");
		break;
	default:
		strMsg =  _T("error...");
		break;
	}
	AfxMessageBox(LPCTSTR(strMsg));
	CPropertyPage::OnOK();
}


BOOL CSchool::OnKillActive()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	AfxMessageBox(_T("school leave."));
	return CPropertyPage::OnKillActive();
}


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

	// TODO:  ここに初期化を追加してください
	CButton* pBtn = (CButton*)GetDlgItem(IDC_RADIO1);
	pBtn->SetCheck(BST_CHECKED);
	m_nRadioFlag = 1;
	return TRUE;  // return TRUE unless you set the focus to a control
	// 例外 : OCX プロパティ ページは必ず FALSE を返します。
}

Work属性页  work.h,work.cpp

#pragma once


// CWork ダイアログ

class CWork : public CPropertyPage
{
	DECLARE_DYNAMIC(CWork)

public:
	CWork();
	virtual ~CWork();

// ダイアログ データ
	enum { IDD = IDD_DIALOG2 };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedRadio1();
	afx_msg void OnBnClickedRadio2();
	afx_msg void OnBnClickedRadio3();
	virtual BOOL OnApply();
	virtual void OnOK();
	virtual BOOL OnKillActive();

private:
	int m_nRadioFlag;
public:
	virtual BOOL OnInitDialog();
};

// Work.cpp : 実装ファイル
//

#include "stdafx.h"
#include "PropSheetDemo.h"
#include "Work.h"
#include "afxdialogex.h"


// CWork ダイアログ

IMPLEMENT_DYNAMIC(CWork, CPropertyPage)

CWork::CWork()
	: CPropertyPage(CWork::IDD)
{
	m_nRadioFlag = 0;
}

CWork::~CWork()
{
}

void CWork::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CWork, CPropertyPage)
	ON_BN_CLICKED(IDC_RADIO1, &CWork::OnBnClickedRadio1)
	ON_BN_CLICKED(IDC_RADIO2, &CWork::OnBnClickedRadio2)
	ON_BN_CLICKED(IDC_RADIO3, &CWork::OnBnClickedRadio3)
END_MESSAGE_MAP()


// CWork メッセージ ハンドラー


void CWork::OnBnClickedRadio1()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 1;//1年
	SetModified();
}


void CWork::OnBnClickedRadio2()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 2;//2年
	SetModified();
}


void CWork::OnBnClickedRadio3()
{
	// TODO: ここにコントロール通知ハンドラー コードを追加します。
	m_nRadioFlag = 3;//3年
	SetModified();
}


BOOL CWork::OnApply()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	
	return CPropertyPage::OnApply();
}


void CWork::OnOK()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	CString strMsg = _T("");
	switch ( m_nRadioFlag )
	{
	case 1:
		strMsg =  _T("1年");
		break;
	case 2:
		strMsg =  _T("2年");
		break;
	case 3:
		strMsg =  _T("3年");
		break;
	default:
		strMsg =  _T("error...");
		break;
	}
	AfxMessageBox(LPCTSTR(strMsg));
	CPropertyPage::OnOK();
}


BOOL CWork::OnKillActive()
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	AfxMessageBox(_T("work leave."));
	return CPropertyPage::OnKillActive();
}


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

	// TODO:  ここに初期化を追加してください
	CButton* pBtn = (CButton*)GetDlgItem(IDC_RADIO1);
	pBtn->SetCheck(BST_CHECKED);
	m_nRadioFlag = 1;
	return TRUE;  // return TRUE unless you set the focus to a control
	// 例外 : OCX プロパティ ページは必ず FALSE を返します。
}


你可能感兴趣的:(mfc,对话框,CPropertySheet)