您的位置:首页 > 编程语言

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

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

在项目开发中CPropertySheet对话框非常重要,作用也非常大,如果一个非常强大的系统在运行前需要做很多配置时,我们就可以使用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);


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 を返します。
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息