ククログ

株式会社クリアコード > ククログ > MFCアプリケーションのUI開発(初級レベル)

MFCアプリケーションのUI開発(初級レベル)

最近、ChronosというChromiumベースのWebブラウザの開発をしている橋田です。

ChronosはMFCで作成されています。 今回、Chronosに新しいダイアログを追加しました。 Visual Studio + MFCでのUI開発に初めて対応したため、MFCでのUI開発方法について得た知見を紹介したいと思います

リソース ビュー

ビジュアルにリソースを編集するためにリソースファイル(.rc)をダブルクリックしリソース ビューを開きます。 Chronosでは、Sazabi.rcです。

ソリューションエクスプローラーからSazabi.rcを選択

このとき、Resource.hなどのリソース関連ファイルを編集画面で開いていると「他のエディターで使用中」と表示され上手く表示されません。 不要なファイルは閉じておきましょう。

他のエディターで使用中

問題がなければ、以下のようにリソース ビューが表示されます。

リソース ビューを表示

新しいリソースの追加

ここでは新しいダイアログを追加します。

リソースの中のDialogを右クリックし、リソースの追加を選択します。

リソースの追加

これにより新しいダイアログリソースが追加されリソースエディターでそのダイアログが開きます。

追加されたダイアログ

コンポーネントを追加する

ツールボックスを開き、追加したいコンポーネントを選びます。

ツールボックスを表示

今回はコンボボックスを追加しました。

コンボボックスの追加

コンポーネントのプロパティを変更する

追加したコンボボックスはデフォルトの状態なので、必要に応じてプロパティを変更します。 図の右下のプロパティ一覧から、変更したいプロパティを変更します。

プロパティの変更

ここでコンポーネントのIDも重複しないように適切に変更します。

コンポーネントのイベントハンドラーを追加する

例えばコンボボックスの値が変わった時に独自の処理を実行するなど、イベント発生時に何か処理をしたい場合があります。 その場合は、以下の手順でイベントハンドラーを追加します。

ハンドラーを追加したいコンポーネントをダブルクリックします。 コンポーネントのクラス追加のダイアログが表示されるので、適切な名前を付けてクラスを作成します。

コンボボックスの対応クラスの追加

このダイアログでOKボタンをクリックするとクラスが自動生成されます。

自動生成されたクラス

その後、リソースエディターに戻り、プロパティのイベントマークをクリックと、イベント一覧が表示されるようになります。 ハンドラーを追加したいイベントの部分をクリックすると、イベントハンドラーの雛形が作成されます。

イベントハンドラーの設定

文字列リソースの追加

String Tableの更新

入力された値に応じて変わるメッセージなど、固定で指定できないメッセージも存在します。 そのようなメッセージについては、リソース ビューからString Tableを開き文字列リソースを追加します。 直接ソースコード上に文字列を埋め込むこともできますが、後述の国際化対応も考慮すると、String Tableに追加しておくのが良いでしょう。

挿入したい位置の文字列リソースを右クリックし、新しい文字列リソースを選択します。

String Tableの挿入

空の文字列リソースが作成されるので、ID、キャプションを設定します。

String Tableの値の編集

追加したメッセージは以下のように CString.LoadString などで読み込みます。

CString title;

title.LoadString(ID_CERTIFICATION_ISSUER);

注意

リソースIDについて

Visual Studioではリソース エディターで追加したリソースのIDを以下のResource.hの定義を使って自動採番しています。

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS                     1
#define _APS_NEXT_RESOURCE_VALUE        435
#define _APS_NEXT_COMMAND_VALUE         33015
#define _APS_NEXT_CONTROL_VALUE         1094
#define _APS_NEXT_SYMED_VALUE           104
#endif
#endif

https://learn.microsoft.com/en-us/cpp/mfc/tn035-using-multiple-resource-files-and-header-files-with-visual-cpp?view=msvc-170&redirectedfrom=MSDN

_APS_NEXT_RESOURCE_VALUE は、ダイアログ リソース、メニュー リソースなどを対象として使用する次のシンボル値です。 リソース シンボル値の有効な値の範囲は 1 ~ 0x6FFF です。

_APS_NEXT_COMMAND_VALUE は、コマンド ID を対象として使用する次のシンボル値です。 コマンド シンボル値の有効な値の範囲は 0x8000 ~ xDFFF です。

_APS_NEXT_CONTROL_VALUE は、ダイアログ コントロールを対象として使用する次のシンボル値です。 ダイアログ コントロール値の有効な値の範囲は 8 ~ 0xDFFF です。

_APS_NEXT_SYMED_VALUE は、シンボル ブラウザー内で [新規] コマンドを使用して手動でシンボル値を割り当てるときに発行される次のシンボル値です。

リソース エディターで追加したリソースについては、上記の通り _APS_NEXT_RESOURCE_VALUE の値に基づいて自動採番されます。 一方、String Tableで追加した文字列リソースに対しては、上記の定義による自動採番が実行されません。 また、自動採番の際に既に同じIDのリソースが存在する場合、重複して採番されてしまいます。 そのため、String Tableで追加した文字列リソースが _APS_NEXT_RESOURCE_VALUE 以上かつ近い値になっている場合、将来的に自動採番された番号と重複してしまう可能性があります。

メッセージ追加後、 _APS_NEXT_RESOURCE_VALUE の値を確認し、問題ないかどうか確認する必要があります。 毎回この確認・更新をするのは大変なので、直接String Tableに追加する文字列リソースのIDの範囲と、自動で採番されるリソースの範囲を予め分けておくのが良いでしょう1

例:

  • 直接String Tableに追加する文字列リソースのIDの範囲: 1 - 4999
    • このくらいあれば将来的にも枯渇しないだろう、という値。
  • 自動で採番されるリソースの範囲: 5000 - 28671(0x6FFF)

という範囲分けを考え、最初に _APS_NEXT_COMMAND_VALUE に5000を指定しておく。

国際化

一つの言語用のリソース完成後、国際化を行います。

もし、まだ対象の言語用のリソースが存在していない場合、その言語用のリソースを作成します。

リソースを右クリックしてコピーの挿入を選択します。

国際化対応のためのコピー挿入

リソース コピーの挿入ダイアログが表示されるので、言語を選択してOKボタンをクリックします。 ここでは英語を指定しています。

国際化対応のためのコピーの言語選択ダイアログ

英語用のリソースが作成されるので、このリソースで表示される各メッセージを翻訳します。

コピーされた英語用リソース

表示内容も各言語に合わせて必要に応じて調整します。

ここではダイアログリソースでの例を紹介していますが、String Tableなどでも同様です。

まとめ

今回はMFCでのUI開発方法について初心者向けの内容を紹介しました。

クリアコードではこのように知見や成果を公開することを重視しています。 クリアコードで働くことに興味を持たれた方は、クリアコードの採用情報をぜひご覧ください。

  1. Chronosではまだ適切にIDの範囲が分かれていないので修正の予定。