前回までの記事
ダイアログ追加
今回作成したいのは、条件付き表示を設定するダイアログ。
どの列を表示するか、どの項目がどの点以上か、などです。
見た目はこんな感じ。

IDに関する条件はなく、常に表示させようかと。
とりあえず順番に、まずはダイアログ追加から。
リソースビューから、Dialogを右クリック→リソースの追加。
ダイアログが追加されるので、IDをIDD_CONDITIONにしておきます。

コントロールを配置します。
1行につき、
- チェックボックス
- エディットボックス(点以上の方の入力)
- スタティック(「点以上」)
- エディットボックス(点以下の方の入力)
- スタティック(「点以下」)
これを5種類。
加えてボタンを3つ追加
((((((((((っ・ω・)っ追加中

はい、できました。
ID名や各コントロールの位置はこんな感じに。
これはお好みですね。

ここまで出来たら、一度このダイアログを呼び出すようにしてみます。
まずはこのダイアログの処理を行うクラス等の作成。
適当に、リソースビューの「保存&表示」ボタンをダブルクリックします。

MFCクラス追加画面が出てくるので、
クラス名やファイル名を記載します。
今回、基底クラスはCDialogに。
基底クラスの話は以前実験しました。
これでOKボタンを押して、作成します。

追加されました。
これはいったん放置。
今度はダイアログを呼び出す処理を追加します。
リソースビューからIDD_TESTRESULT_DIALOGを開きます。
そのまま、条件変更ボタンをダブルクリック。

ボタン押下時に呼応される処理です。
続いて上部に以下のインクルード文を追加。
#include "Condition.h"さっき作ったOnBnClickedButtonConditional内に以下を入れます。
void CTestResultDlg::OnBnClickedButtonConditional()
{
CCondition dlgCondition;
// 後で処理をを入れる
INT_PTR iRTN = dlgCondition.DoModal();
if (iRTN == IDOK)
{
// 「保存&表示」または「保存」ボタン
}
else
{
// キャンセルボタン
}
}ここまで出来たら、一回ビルドを行います。
条件変更ボタンを押すと

OK!
なんかできることが多くなって嬉しいですね(´▽`*)
エディットボックスはせいぜい3桁の100が上限なので、
こんなに幅はいらないと思いますが、まぁ気が向いたら縮めます。
条件変更ダイアログの制御
新規作成したダイアログの制御だけ行って今回は終わります。
とりあえずOnInitDialogは欲しいので、
表示→クラスビュー
でCConditionを選択、プロパティからオーバーライドを選択。

OnInitDialogがあるので追加します。

次いで、Condition.hに色々メンバ変数を用意します。
まず、TestResultDlgでも追加したenumを。
typedef enum
{
SUBCON_JA = 0, //国語 = 0
SUBCON_MA, //数学 = 1
SUBCON_EN, //英語 = 2
SUBCON_SC, //理科 = 3
SUBCON_SS, //社会 = 4
SUMCON_NUM //教科数 = 5
} SUBJECTCONDITION;今考えれば、enumをどのcppからでも使える共通ファイルみたいなの作ればよかったかなーと思ったり。
次いで要素が5つある配列を6つ。
それと制御関数。
private:
BOOL m_bCheck[SUMCON_NUM]; // 各チェックボックスの状態
CButton m_chk[SUMCON_NUM]; // 各チェックボックス用メンバ変数
CString m_strIJO[SUMCON_NUM]; // 各教科の点以上
CString m_strIKA[SUMCON_NUM]; // 各教科の点以下
CEdit m_editIJO[SUMCON_NUM]; // 各エディットボックス用メンバ変数(以上用)
CEdit m_editIKA[SUMCON_NUM]; // 各エディットボックス用メンバ変数(以下用)
private:
void EditEnableWrite(); // エディットボックス入力可能制御とりあえずこれだけで。
今更ですが仕様は、
チェックボックスにチェックが入っているときはエディットボックス入力可能、
チェックが入っていない時は入力不可です。
Condition.cppを開き、
コンストラクタと、DoDataExchangeと、先ほど追加したOnInitDialogに処理を追加します。
CCondition::CCondition(CWnd* pParent /*=nullptr*/)
: CDialog(IDD_CONDITION, pParent)
{
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
m_bCheck[iLoop] = TRUE; // チェックボックス状態初期化
m_strIJO[iLoop] = _T("0"); // 以上初期化
m_strIKA[iLoop] = _T("100"); // 以下初期化
}
}
void CCondition::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHECK_1JP, m_chk[SUBCON_JA]); // 国語チェックボックス
DDX_Control(pDX, IDC_CHECK_2MA, m_chk[SUBCON_MA]); // 数学チェックボックス
DDX_Control(pDX, IDC_CHECK_3EN, m_chk[SUBCON_EN]); // 英語チェックボックス
DDX_Control(pDX, IDC_CHECK_4SC, m_chk[SUBCON_SC]); // 理科チェックボックス
DDX_Control(pDX, IDC_CHECK_5SS, m_chk[SUBCON_SS]); // 社会チェックボックス
DDX_Control(pDX, IDC_EDIT_1JP_IJO, m_editIJO[SUBCON_JA]); // 国語エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_2MA_IJO, m_editIJO[SUBCON_MA]); // 数学エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_3EN_IJO, m_editIJO[SUBCON_EN]); // 英語エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_4SC_IJO, m_editIJO[SUBCON_SC]); // 理科エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_5SS_IJO, m_editIJO[SUBCON_SS]); // 社会エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_1JP_IKA, m_editIKA[SUBCON_JA]); // 国語エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_2MA_IKA, m_editIKA[SUBCON_MA]); // 数学エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_3EN_IKA, m_editIKA[SUBCON_EN]); // 英語エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_4SC_IKA, m_editIKA[SUBCON_SC]); // 理科エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_5SS_IKA, m_editIKA[SUBCON_SS]); // 社会エディットボックス(以上)
DDX_Text(pDX, IDC_EDIT_1JP_IJO, m_strIJO[SUBCON_JA]); // 国語エディットボックス(以下)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_2MA_IJO, m_strIJO[SUBCON_MA]); // 国語エディットボックス(以下)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_3EN_IJO, m_strIJO[SUBCON_EN]); // 国語エディットボックス(以下)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_4SC_IJO, m_strIJO[SUBCON_SC]); // 国語エディットボックス(以下)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_5SS_IJO, m_strIJO[SUBCON_SS]); // 国語エディットボックス(以下)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_1JP_IKA, m_strIKA[SUBCON_JA]); // 国語エディットボックス(以上)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_2MA_IKA, m_strIKA[SUBCON_MA]); // 国語エディットボックス(以上)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_3EN_IKA, m_strIKA[SUBCON_EN]); // 国語エディットボックス(以上)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_4SC_IKA, m_strIKA[SUBCON_SC]); // 国語エディットボックス(以上)の数値をメンバ変数に
DDX_Text(pDX, IDC_EDIT_5SS_IKA, m_strIKA[SUBCON_SS]); // 国語エディットボックス(以上)の数値をメンバ変数に
}
BOOL CCondition::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: ここに初期化を追加してください
SetWindowText(_T("条件変更ダイアログ")); //タイトル
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
int iCheck = BST_CHECKED;
if (!m_bCheck[iLoop])
iCheck = BST_UNCHECKED;
m_chk[iLoop].SetCheck(iCheck); // チェックボックスの状態
m_editIJO[iLoop].SetWindowTextA(m_strIJO[iLoop]); // 以上のエディットボックスに初期値セット
m_editIKA[iLoop].SetWindowTextA(m_strIKA[iLoop]); // 以下のエディットボックスに初期値セット
}
EditEnableWrite(); //制御チェック
return TRUE; // return TRUE unless you set the focus to a control
// 例外 : OCX プロパティ ページは必ず FALSE を返します。
}DoDataExchange内に記載のDDX_Textのところは今回は必要ありません。
次回、エディットボックスの中身を取得する際に必要となります。
続きまして、制御関数EditEnableWriteの中身
void CCondition::EditEnableWrite()
{
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
if (m_chk[iLoop].GetCheck() == BST_CHECKED)
{
// チェックが入っている状態
// エディットボックス書き込み可
m_editIJO[iLoop].SetReadOnly(FALSE);
m_editIKA[iLoop].SetReadOnly(FALSE);
}
else
{
// チェックが入っていない状態
// エディットボックス書き込み不可
m_editIJO[iLoop].SetReadOnly(TRUE);
m_editIKA[iLoop].SetReadOnly(TRUE);
}
}
}最後に、チェックボックスの状態が変更されるたびに呼ばれるOnBnClickedを追加します。
リソースビューからダイアログを開き、
5つのエディットボックスすべてをダブルクリックして関数を追加させます。

後はそれぞれで、先ほどの制御関数を呼応させます。
void CCondition::OnBnClickedCheck1jp()
{
EditEnableWrite();
}
void CCondition::OnBnClickedCheck2ma()
{
EditEnableWrite();
}
void CCondition::OnBnClickedCheck3en()
{
EditEnableWrite();
}
void CCondition::OnBnClickedCheck4sc()
{
EditEnableWrite();
}
void CCondition::OnBnClickedCheck5ss()
{
EditEnableWrite();
}もう一つついでに。
リソースビューを開き、エディットボックスを選択後プロパティから
数字のみ入力可能にする項目をTrueにしておきます。
(忘れてましたね)
これを10個すべてに。
さて、ビルド。
条件変更ボタンを押すと。

チェックボックスとエディットボックスに初期値が入れられてます。
さて、ここで国語のチェックを外すと。

色が変わって、確かに書き込み不可になりました。
ただ、カーソルを合わせることはできるんですよね。
これは…設定でできるのかな?
ともかく、書き込み不可処理は実施できたので今回はここまでにします。
終わりに
いやー、なんかここまでできると結構達成感はあります。
でももう少し、頑張ります。
次回はこの2つのダイアログ間でチェックの状態と点数の受け渡し処理を行います。
今回の成果物
TestResultDlgの方に関してはボタン処理を追加しただけなのでそこだけ。
TestResultDlg.h
// TestResultDlg.h : ヘッダー ファイル
//
//略
class CTestResultDlg : public CDialogEx
{
//略
public:
afx_msg void OnBnClickedButtonConditional();
};TestResultDlg.cpp
#include "Condition.h"
// 色々略
/**
* @fn
* @brief 条件変更ボタン押下時の処理
* @param なし
* @return なし
*/
void CTestResultDlg::OnBnClickedButtonConditional()
{
CCondition dlgCondition;
// 後で処理をを入れる
INT_PTR iRTN = dlgCondition.DoModal();
if (iRTN == IDOK)
{
// 「保存&表示」または「保存」ボタン
}
else
{
// キャンセルボタン
}
}Condition.h
#pragma once
#include "afxdialogex.h"
// CCondition ダイアログ
typedef enum
{
SUBCON_JA = 0, //国語 = 0
SUBCON_MA, //数学 = 1
SUBCON_EN, //英語 = 2
SUBCON_SC, //理科 = 3
SUBCON_SS, //社会 = 4
SUMCON_NUM //教科数 = 5
} SUBJECTCONDITION;
class CCondition : public CDialog
{
DECLARE_DYNAMIC(CCondition)
public:
CCondition(CWnd* pParent = nullptr); // 標準コンストラクター
virtual ~CCondition();
// ダイアログ データ
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_CONDITION };
#endif
private:
BOOL m_bCheck[SUMCON_NUM]; // 各チェックボックスの状態
CButton m_chk[SUMCON_NUM]; // 各チェックボックス用メンバ変数
CString m_strIJO[SUMCON_NUM]; // 各教科の点以上
CString m_strIKA[SUMCON_NUM]; // 各教科の点以下
CEdit m_editIJO[SUMCON_NUM]; // 各エディットボックス用メンバ変数(以上用)
CEdit m_editIKA[SUMCON_NUM]; // 各エディットボックス用メンバ変数(以下用)
private:
void EditEnableWrite(); // エディットボックス入力可能制御
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnBnClickedCheck1jp(); //国語チェックボックス
afx_msg void OnBnClickedCheck2ma(); //数学チェックボックス
afx_msg void OnBnClickedCheck3en(); //英語チェックボックス
afx_msg void OnBnClickedCheck4sc(); //理科チェックボックス
afx_msg void OnBnClickedCheck5ss(); //社会チェックボックス
};Condition.cpp
// Condition.cpp : 実装ファイル
//
#include "pch.h"
#include "TestResult.h"
#include "afxdialogex.h"
#include "Condition.h"
// CCondition ダイアログ
IMPLEMENT_DYNAMIC(CCondition, CDialog)
/**
* @fn
* @brief コンストラクタ
* @param なし
* @return なし
*/
CCondition::CCondition(CWnd* pParent /*=nullptr*/)
: CDialog(IDD_CONDITION, pParent)
{
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
m_bCheck[iLoop] = TRUE; // チェックボックス状態初期化
m_strIJO[iLoop] = _T("0"); // 以上初期化
m_strIKA[iLoop] = _T("100"); // 以下初期化
}
}
CCondition::~CCondition()
{
}
void CCondition::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHECK_1JP, m_chk[SUBCON_JA]); // 国語チェックボックス
DDX_Control(pDX, IDC_CHECK_2MA, m_chk[SUBCON_MA]); // 数学チェックボックス
DDX_Control(pDX, IDC_CHECK_3EN, m_chk[SUBCON_EN]); // 英語チェックボックス
DDX_Control(pDX, IDC_CHECK_4SC, m_chk[SUBCON_SC]); // 理科チェックボックス
DDX_Control(pDX, IDC_CHECK_5SS, m_chk[SUBCON_SS]); // 社会チェックボックス
DDX_Control(pDX, IDC_EDIT_1JP_IJO, m_editIJO[SUBCON_JA]); // 国語エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_2MA_IJO, m_editIJO[SUBCON_MA]); // 数学エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_3EN_IJO, m_editIJO[SUBCON_EN]); // 英語エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_4SC_IJO, m_editIJO[SUBCON_SC]); // 理科エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_5SS_IJO, m_editIJO[SUBCON_SS]); // 社会エディットボックス(以下)
DDX_Control(pDX, IDC_EDIT_1JP_IKA, m_editIKA[SUBCON_JA]); // 国語エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_2MA_IKA, m_editIKA[SUBCON_MA]); // 数学エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_3EN_IKA, m_editIKA[SUBCON_EN]); // 英語エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_4SC_IKA, m_editIKA[SUBCON_SC]); // 理科エディットボックス(以上)
DDX_Control(pDX, IDC_EDIT_5SS_IKA, m_editIKA[SUBCON_SS]); // 社会エディットボックス(以上)
}
BEGIN_MESSAGE_MAP(CCondition, CDialog)
ON_BN_CLICKED(IDC_CHECK_1JP, &CCondition::OnBnClickedCheck1jp)
ON_BN_CLICKED(IDC_CHECK_2MA, &CCondition::OnBnClickedCheck2ma)
ON_BN_CLICKED(IDC_CHECK_3EN, &CCondition::OnBnClickedCheck3en)
ON_BN_CLICKED(IDC_CHECK_4SC, &CCondition::OnBnClickedCheck4sc)
ON_BN_CLICKED(IDC_CHECK_5SS, &CCondition::OnBnClickedCheck5ss)
END_MESSAGE_MAP()
// CCondition メッセージ ハンドラー
BOOL CCondition::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: ここに初期化を追加してください
SetWindowText(_T("条件変更ダイアログ")); //タイトル
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
int iCheck = BST_CHECKED;
if (!m_bCheck[iLoop])
iCheck = BST_UNCHECKED;
m_chk[iLoop].SetCheck(iCheck); // チェックボックスの状態
m_editIJO[iLoop].SetWindowTextA(m_strIJO[iLoop]); // 以上のエディットボックスに初期値セット
m_editIKA[iLoop].SetWindowTextA(m_strIKA[iLoop]); // 以下のエディットボックスに初期値セット
}
EditEnableWrite(); //制御チェック
return TRUE; // return TRUE unless you set the focus to a control
// 例外 : OCX プロパティ ページは必ず FALSE を返します。
}
/**
* @fn
* @brief エディットボックス制御処理
* @param なし
* @return なし
*/
void CCondition::EditEnableWrite()
{
for (int iLoop = SUBCON_JA; iLoop < SUMCON_NUM; iLoop++)
{
if (m_chk[iLoop].GetCheck() == BST_CHECKED)
{
// チェックが入っている状態
// エディットボックス書き込み可
m_editIJO[iLoop].SetReadOnly(FALSE);
m_editIKA[iLoop].SetReadOnly(FALSE);
}
else
{
// チェックが入っていない状態
// エディットボックス書き込み不可
m_editIJO[iLoop].SetReadOnly(TRUE);
m_editIKA[iLoop].SetReadOnly(TRUE);
}
}
}
/**
* @fn
* @brief 国語チェックボックス変更時の処理
* @param なし
* @return なし
*/
void CCondition::OnBnClickedCheck1jp()
{
EditEnableWrite();
}
/**
* @fn
* @brief 数学チェックボックス変更時の処理
* @param なし
* @return なし
*/
void CCondition::OnBnClickedCheck2ma()
{
EditEnableWrite();
}
/**
* @fn
* @brief 英語チェックボックス変更時の処理
* @param なし
* @return なし
*/
void CCondition::OnBnClickedCheck3en()
{
EditEnableWrite();
}
/**
* @fn
* @brief 理科チェックボックス変更時の処理
* @param なし
* @return なし
*/
void CCondition::OnBnClickedCheck4sc()
{
EditEnableWrite();
}
/**
* @fn
* @brief 社会チェックボックス変更時の処理
* @param なし
* @return なし
*/
void CCondition::OnBnClickedCheck5ss()
{
EditEnableWrite();
}

コメント