MFCプロジェクトでCStaticクラスを操作する

今回はMFCアプリで頻繁に使うコントロールの一つ、
CStaticクラスの操作方法について。

主に、自分がよく使う操作の備忘録です。

準備

プロジェクト作成

プロジェクトの作成方法、コントロールの配置方法は
こちらをご覧ください。

今回のプロジェクト名は「CStaticTest」にします。

コントロールID

Static Textを配置後、IDを変更します。
デフォルト(IDC_STATIC)でも問題ないですが、
わかりやすくするため変更を。

プロパティタブへ飛び、ID欄から変更します。

今回は、ID名をIDC_STATIC_TESTに変更します。
また、お好みで幅を広げたり、デフォルトのテキストを消します。
コントロールを選択後、Deleteボタンで消すことができます。

ビルド

最後にソリューションのビルドを実施し、
出来上がるexeファイルを一度確認します。

完成したのがこちら。

処理記述場所

プロジェクトを一つ作成すると、
プロジェクト名Dlg.cpp
というファイルが出来上がります。

今回ですとCStaticTestDlg.cppです。

そこの
OnInitDialog
関数内に処理を記述します。

Visual Studioのバージョンによって異なるかもしれませんが、
デフォルト処理は下記のよう。

BOOL CCStaticTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

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

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

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		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: 初期化をここに追加します。

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

ご丁寧に30行目に処理追加コメントがありますので、
それよりも下に処理を入れていきます。

テキスト変更 (おまけで方式説明)

プロパティから変更

表示⇒キャプションから変更です。

これはわかりやすい。

しかし、これだと動的な変更ができません。

プログラムからテキスト変更することもできます。
というか、こちらの方を(自分は)よく使います。

プログラムから変更

動的コントロール取得 (GetDlgItem方式)

GetDlgItemを使用して、コントロールのポインタを動的に取得し、操作します。

先のOnInitDialogに記述。

BOOL CCStaticTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 略

	// TODO: 初期化をここに追加します。
	CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_TEST);
	pStatic->SetWindowText(_T("OnInitDialogからGetDlgItemを使用して変更しました"));

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

書き方は
CStatic* 変数名 = (CStatic*)GetDlgItem(コントロールID);
変数名->SetWindowText(変更したい文字列);

です。

一度これでビルドします。

出来上がったexeを開くと

反映されました。

メンバ変数バインド (DDX_Control方式)

DDX_Controlマクロを使用してコントロールを事前にメンバ変数にバインドし、
そのメンバ変数を使って操作します。

事前準備。
プロジェクト名Dlg.hというファイルがあるので開きます。
今回ですと、CStaticTestDlg.hです。

メンバ変数m_ctrlStaticを定義します。

class CCStaticTestDlg : public CDialogEx
{
// 略

private:
	CStatic m_ctrlStatic;
};

次いでCStaticTestDlg.cppに戻り、バインド準備。
昔だと自分は紐づけって言ってましたが、
バインドの方が一般らしいです。

元から用意されてあるDoDataExchange関数に1行追加します。

void CCStaticTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_STATIC_TEST, m_ctrlStatic);
}

4行目のDDX_Controlを追加です。

この準備の下、OnInitDialogでテキストを変更する処理を加えます。

BOOL CCStaticTestDlg::OnInitDialog()
{
	// 略

	// TODO: 初期化をここに追加します。
	//CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_TEST);
	//pStatic->SetWindowText(_T("OnInitDialogからGetDlgItemを使用して変更しました"));

	m_ctrlStatic.SetWindowText(_T("OnInitDialogからDDX_Controlを使用して変更しました"));
	UpdateData(FALSE);

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

必要なのは9行目と10行目。
メンバ変数.SetWindowText(変更したい文字列);
です。

その後、UpdateData(FALSE)で、実際のコントロールに反映させます。

ビルドします。

反映されました。

どっちがいいの?

どちらもCStaticクラスの関数を呼ぶことができます。

一長一短なので、使い分ければいいかと。

動的コントロール取得の場合、

  • 必要な時にコントロールを取得する⇒簡単な操作では便利
  • 反面、スコープ外に出るとまたポインタ変数を再定義する必要あり
  • 再利用や保守性がやや低め

メンバ変数バインドの場合、

  • 事前にバインドするので上記の例だと1行で済む
  • 保守性は高い(らしい 自分はそこは詳しくないです)
  • たった1回だけ操作する場合、ヘッダー、DoDataExchangeと、
    コード記載量と実際の処理とで労力が見合わない

シンプルな操作の場合はGetDlgItemを、
何度も操作したり複雑な操作が必要な場合はDDX_Controlを使用するケースが
望ましいかもしれません。

以降、GetDlgItem方式で紹介します。

テキスト表示・非表示

スタティックテキストの表示・非表示を切り替えることができます。

BOOL CCStaticTestDlg::OnInitDialog()
{
	// 略

	// TODO: 初期化をここに追加します。
	CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_TEST);

	pStatic->ShowWindow(SW_HIDE);	//非表示

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

引数をSW_SHOWにすると表示させることができます。
デフォルトは、表示させる設定です。

活性・非活性

そのコントロールが活性か、非活性かを切り替えることができます。

スタティックテキストの場合、わかりにくいかもしれません。
ボタンやエディットボックスの場合、非活性だと触れない(編集できない)ようになります。

一応スタティックテキストも、非活性の場合は文字が薄くなります。

BOOL CCStaticTestDlg::OnInitDialog()
{
	// 略

	// TODO: 初期化をここに追加します。
	CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_TEST);

	pStatic->EnableWindow(FALSE);	//非活性

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

見えにくいですが、薄くなってますね。

引数をTRUEにすると、活性化します。
デフォルトは活性です。

おまけ

ポインタを指定しないままSetWindowTextを使用した場合、
ダイアログのキャプションを変更できます。

BOOL CCStaticTestDlg::OnInitDialog()
{
	// 略

	SetWindowText(_T("これはダイアログ上部に現れるキャプションです"));

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

終わりに

今回は、自分がよく使うCStatic関連の処理をまとめてみました。

他にも、枠線で囲うことも稀にありますが、
プロパティから設定できるので、ぜひ試してみてください。

SampleSrc/CPlusPlus/ControlOpeartion/ControlTest at main ?? Tatsumath/SampleSrc
Various sources, mostly C++. Contribute to Tatsumath/SampleSrc development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました