Natural Intelligence による記事要点まとめ
・リストボックスの文字のサイズは自由に変更できる。
・メモリを無駄に消費しないよう注意して設定しよう。
・別のフォントを使用するように変えることもできる。
大きな字に変更したい場合はどうしたらよいか、忘れないように記録しています。 また、自由なフォントを使う方法についても書いています。
コードは Windows 10、Visual Studio 2022 で作成、確認したものです。
リストボックスの横スクロールバーを実装する
VC++ でダイアログにリストボックスを設置しても、プロパティ設定だけでは横スクロールせずテキストがはみ出します。
適切に横スクロールバーを表示するには工夫が必要です。
なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 December 16, 2022
リストボックスなどの
テストのために、ダイアログベースの MFC アプリを作成しました。 ここでは ChangeLBProp という名前にしています。
ダイアログにリストボックスを追加し、コントロール名を IDC_LIST としました。
この状態で、どのような表示になるかを確かめます。
ダイアログの初期化関数 OnInitDialog() で、リストボックスに確認用の文字列を出力します。 OnInitDialog 関数は、ダイアログクラス内に、 BOOL CChangeLBPropDlg::OnInitDialog() のように実装されています。
CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST); pList->ResetContent(); pList->AddString(_T("東京")); pList->AddString(_T("神奈川")); pList->AddString(_T("埼玉")); pList->AddString(_T("千葉"));
ビルドの設定は、Debug ビルドの x64 になっています。 このあたりは何も影響がないと思います。
枠に対して文字がだいぶ小さいので、大きくしたいと思います。
ちなみに VS2022 ではデフォルトでリストボックスのソート(並べ替え)のプロパティが True になっていますので、 (設定した順ではなく)文字コード順に並んでいます。 設定順に表示させるには、「並べ替え」や「ソート」「Sort」のようなプロパティを False に変更します。
文字のサイズを変えるため描画のフォントを変えますので、ヘッダファイル、例えば ChangeLBPropDlg.h で、ダイアログクラスに CFont クラスを定義します。 これは MFC の、フォント情報を格納するクラスです。
protected: CFont* m_pFont; CFont m_font;
m_ で始まっているのはクラスのメンバである、という意味です。 CFont* は、 CFont を指すポインタです。
動作を確認するためにユーザーの操作を求めていますが、初期化時に行ってしまっても問題ないでしょう。
void CChangeLBPropDlg::OnBnClickedOk() { //CDialogEx::OnOK(); CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST); LOGFONT lf; m_pFont = pList->GetFont(); // 元のフォントを取得 m_pFont->GetLogFont(&lf); // フォント情報を取り出し lf.lfHeight = -48; // 欲しいサイズを指定 m_font.CreateFontIndirect(&lf); // フォントを作成 pList->SetFont(&m_font); // 作成したフォントを選択 }
まずは自動生成された、OK を返してダイアログを終了するための呼び出し OnOK() をコメントアウトします。
対象となるリストボックスを取得し、pList に設定しています。 また、フォント情報を格納する LOGFONT 構造体 を用意しています。
フォントの指定には WM_SETFONT メッセージを使うようですが、MFC ならウィンドウクラスの CWnd::SetFont 関数を使います。 CListBox は CWnd の派生クラスですので、このあとの手法はエディットコントロール CEdit など他のコントロールでも利用できるはずです(エディットコントロールのみテスト済み)。
CWnd::SetFont 関数には LOGFONT 構造体 を渡しますが、間違いなく設定するのは面倒ですので、 GetFont 関数で現在のリストボックスのフォント情報を取得します。 そして必要な部分のみ書き換えます。
フォントのサイズは lfHeight で指定されています。 文字の高さをピクセル値で指定するには、負の値を設定します。 文字の高さを 48 ピクセルにしたい場合なら、-48 を設定します。
フォントサイズだけ変更し、あとは現在のままとなったフォント情報から、 CreateFontIndirect 関数で m_font にフォントを作成しています。 ちゃんとしたツールに仕上げる場合は、フォントが正しく作成されたかを確認すべきでしょう。 上記のコードでは確認していませんので。
最後に SetFont 関数でリストボックスに設定しています。
プログラムを実行し、OK ボタンをクリックすると、画面は自動的に更新されて大きな文字で表示されました。
投稿 December 16, 2022
とりあえずは目的を達成できましたが、OK ボタンでフォントを生成して設定していますので、 OK ボタンが複数回クリックされると m_font がどんどん作成されてしまいます。
現代ではオブジェクトの参照がなくなったら自動的に削除してくれる、ということもありますが、 そうでない場合はメモリを浪費しますし、やってくれるにしてもマナーが悪い感じですから、対策を入れておきます。
フォント設定を呼び出したか、また呼び出していないかの判定に m_pFont が使えそうです。 ダイアログの初期化関数 OnInitDialog で、m_pFont を NULL にしておきます。
// フォント情報を取得していません。
m_pFont = NULL;
OK ボタン処理 OnBnClickedOk 関数では、 m_pFont が NULL の場合のみ、取得することとします。
if (!m_pFont) { m_pFont = pList->GetFont(); // 元のフォントを取得 } else { pList->SetFont(m_pFont, FALSE); m_font.DeleteObject(); // 作成したフォントを削除 }
else 節、すでに m_pFont が設定されている場合は、前回作成した m_font を削除しています。
前回 m_font を作成していますので、m_font を再作成する前に削除しておけばクリーンです。 作成したフォントは DeleteObject() 呼び出しで削除できますが、 今はリストボックスに設定中ですから、そのタイミングで削除するのは良くなさそうです。
m_font の選択を解除するため、いったんもとの m_pFont に戻します。 なおここで指定している SetFont 関数の第 2 引数 FALSE は「再描画しない」という意味です。 省略すると TRUE ですので「再描画する」です。
これで少しマナーが良くなりましたが、まだプログラム終了時に設定しっぱなしになっています。
プログラム終了時についてはまず間違いなく正しくクリーンアップされるとは思いますが、 念のため、キャンセルボタン処理にフォントを戻すコードを入れておきます。
void CChangeLBPropDlg::OnBnClickedCancel()
{
if (m_pFont) {
CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST);
pList->SetFont(m_pFont, FALSE);
m_font.DeleteObject(); // 作成したフォントを削除
m_pFont = NULL;
}
CDialogEx::OnCancel();
}
m_pFont が NULL ではない場合は m_font が作成され、リストボックスに選択されている状態ですから、 もとのフォント m_pFont を選択しなおして、m_font を削除しています。 m_font が削除されたら、m_pFont を NULL に戻しておき、何らかの理由でプログラムを終了しなかった場合に備えます。
これでプログラム終了時にもフォントが削除されることになります。
ちなみに、ウィンドウ右上のバツボタンやシステムメニューの「閉じる」で閉じたときも この関数 OnBnClickedCancel が呼び出されていますので、 わざわざデストラクタや WM_CLOSE 処理などにコードを追加する必要はないと思います。
CDialogEx::OnCancel(); の前に
MessageBox(_T("フォントをクリアしました。"));
のようなコードを追加すると、その動作を確認できます。
投稿 December 16, 2022
LOGFONT を取得したついでに、フォントの指定も行ってみます。
本来であればインストールされているフォントを調べてその文字列を使用するべきですが、 今はテストですので、インストール済みのフォント名を直接指定してみます。 なお、フォント名は LF_FACESIZE バイト以内に収める必要がありますので、31 バイト + NULL まで、 つまりフォント名の部分は 31 文字(全角の場合は 2 文字分使用)までです。
wsprintf(lf.lfFaceName, _T("メイリオ")); // LF_FACESIZE(31文字)まで
フォントサイズの設定に続けて、フォント名の設定をしてみます。
行間が空きましたが、最初のゴシック系より少し細いフォントになったようです。
このように直接指定する場合には、インストールされていないフォントを指定しないように注意しなくてはいけません。
Windows PC で 2 台のモニタを接続している場合、2 台接続を検出し、座標を特定するためのコードについて書いています。