重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

お世話になります。
現在MFCのダイアログベースアプリケーションを作成しており、ダイアログ上に大小さまざまフォントのスタティックテキストを貼り付けています。
さまざまフォントがあるということは、それだけスタティックテキストに割り当てるCFontも多数作らなければならないと思います。

そこで質問なのですが、
この大小さまざまな(約5種類ほど)のフォントのスタティックテキストを、複数のダイアログで貼り付けようと思っているのですが、その際にダイアログ毎にメンバ変数としてCFontを5種類定義するのと、5種類のサイズ用のCStaticのクラスを作成し、それらを複数のダイアログに貼り付けるのとどちらがよいでしょうか?

クラスをむやみに増やすのもプログラムが見づらくなる気もしますし、ダイアログ毎にその都度CFontをCreateFontするのも面倒かなと思い、質問させて頂きました。

ご意見をよろしくお願い致します。

A 回答 (2件)

>しかしCPaint()内でCreateFontをして、CPaint()の最後にリソースの確保をしたCFontをDeleteObjectすると、そのフォントがダイアログに反映されないのではないでしょうか?



フォントがスタティックテキストに反映されるのは「スタティックテキストのCPaint()内で行った描画のみ」です。

なので、ダイアログのCPaint()を書き換えても、何の意味もありません。

つまり、

・スタティックテキストのCPaint()をオーバーライドする
・そのCPaint()内で、CFontをCreateFontする
・スタティックテキストのDCをGetDCする。このDCは親から継承され、フォントや色などのプロパティは「スタティックテキストの親であるダイアログ」に設定されたプロパティと同じになっている筈
・得たDCに作成したフォントを設定する
・フォントを変えたDCに対してCDC::DrawTextExで文字列を描画する←ここで行った「DCに対する描画」のみがダイアログに反映される。他の場所で描画しても、ウィンドゥが再描画された瞬間に消えてしまう。
・GetDCしたDCをReleaseDCする←同時に使用できるDC数は非常に少ないので、これを忘れるとあっという間に破綻する
・CFontをDeleteObjectする

と言う事です。

ダイアログベースでなくフォームデザイナを使ってアプリを書く場合、フォームデザイナでフォームにスタティックテキストを貼り付ける際に、Fontプロパティを「好みのフォント」にしておけば済むので、上記のような「面倒な事」は一切必要ありません。

スタティックテキストのCPaint()をオーバーライドしなかった場合、以下のようなデフォルトの描画処理が行われます。

・スタティックテキストのDCがGetDCされる。このDCは親から継承され、フォントや色などのプロパティは「スタティックテキストの親であるダイアログ」に設定されたプロパティと同じになっている筈
・そのDCに対してCDC::DrawTextExで文字列が描画される。つまり、スタティックテキストの親であるダイアログと同じフォントで描画される
・GetDCしたDCをReleaseDCされる

要は「CPaint()の中で描画した事がすべて」です。「そこでやったことだけ」がウィンドゥに反映され、「そこでやらなかったこと」はウィンドゥに反映されません。

CDC::DrawTextExでなく、CDC:FillRectやCDC::Polylineをやったって構いません。ともかく「そこでやった描画がすべて」です。

逆にいうと「CPaint()を乗っ取ったら、他の場所で何やっても無駄」って事で、フォントを削除しても描画には何の影響も出ません。
    • good
    • 0
この回答へのお礼

理解が間違っていたらすみません。
とういうことは、ダイアログのOnPaint()に描画の処理やらを書くのではなく、CStatic継承のオリジナルのクラスを作成し、そのオリジナルクラスのOnPaint()内にフォントの設定等を書けばよいということでしょうか?
それだと、フォントの種類が様々ある場合、それに対応した複数のクラスを作成するか、フォントのサイズ等を引数としてそのクラスに渡すような処理が必要となるということでしょうか?

お礼日時:2009/05/29 12:03

要は「リソースの保持期間が重要なのでは」と思います。



「リソースは必要な期間のみ保持すべき」と言う点から言えば

>ダイアログ毎にその都度CFontをCreateFontする

のと、ダイアログをクローズしたら作成したCFontを破棄する、と言うのを行うのが良いと思います。

処理が多少重くなりますが、1度使用したフォントはフォントキャッシュに残っているだろうし「激しく重い」までは行かない筈です。

ホントの事を言うと「WM_PAINTメッセージを受け取って描画を行う必要がある時のみFontリソースを確保して、描画が終わったらリソースを開放、そうじゃない時(単にダイアログが開かれている最中)はFontリソースは保持してない、と言う状態がベストなんだけど。

そうすれば、同一のダイアログを数百個同時に開いても「同時にFontリソースを保持するのはWM_PAINTメッセージ処理中の数個だけ」なので「同一ダイアログを同時に100個くらい開いたら、リソースが不足してアプリが落ちる」と言う危険も減ります(一番危険なのは「同時に開けるデバイスコンテキストの少なさ」なんだけど、それは別の話)
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございます。

>ホントの事を言うと「WM_PAINTメッセージを受け取って描画を行う必要がある時のみFontリソースを確保して、描画が終わったらリソースを開放、そうじゃない時(単にダイアログが開かれている最中)はFontリソースは保持してない、と言う状態がベストなんだけど。

確かにその方がCFontのリソースを保持している期間が短いので理想的ですよね。
しかしCPaint()内でCreateFontをして、CPaint()の最後にリソースの確保をしたCFontをDeleteObjectすると、そのフォントがダイアログに反映されないのではないでしょうか?
それともDeleteObjectではない別のコマンドを使うと、リソースの破棄ではなく解放のみが出来るのでしょうか?

お礼日時:2009/05/29 09:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!