前一章【VC编程技巧】窗体☞3.1利用字体对话框和颜色对话框改变静态标签中字体颜色背景. 我讲了MFC内建的资源对话框,字体对话框,颜色对话框,这一章来讲属性对话框[CPropertyShee]。
在项目开发中CPropertySheet对话框非常重要,作用也非常大,如果一个非常强大的系统在运行前需要做很多配置时,我们就可以使用CPropertySheet做一个配置工具。当软件发布时,我们需要向用户提供安装包,也可以利用CPropertySheet来制作安装包。那么下面我先做一个配置工具,在后续我也会利用CPropertySheet做一个安装程序。
请参考MSDN:CPropertySheet选件类
说明 :本程序是利用VS2013制作的例子。
1)利用VS2013的工程向导制作创建对话框程序!
2)将继承于CDialogEx的主对话框类(CPropSheetDemoDlg)修改成:继承于CPropertySheet,并且删掉对应的对话框资源。
3)主对话框类(CPropSheetDemoDlg)中只留下如下由工程向导生成的函数,其余都删除掉。
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
CPropertySheet( );
explicit CPropertySheet(
UINT nIDCaption,
CWnd* pParentWnd = NULL,
UINT iSelectPage = 0
);
explicit CPropertySheet(
LPCTSTR pszCaption,
CWnd* pParentWnd = NULL,
UINT iSelectPage = 0
);
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 を返します。 }
#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 を返します。 }