• ベストアンサー
  • すぐに回答を!

DrawTextでの描画

お世話になります。 現在開発中のアプリケーションにて行き詰ってしまった箇所が あったためご質問させていただきました。 Visual Studio2005にてダイアログベースのアプリケーションを作成しており、オリジナルのCStatic派生のクラスCSampleStaticクラスを作成します。 このCSampleStaticクラスはメインダイアログでのサブクラスにした際に PreSubclassWindow() ないでタイマーイベントを発生させます。タイマーイベントの内容は1秒ごとにタイマーを呼び、ランダムの値をそのCStaticの値に代入し、ダイアログ上に表示させる動作をします。 その際の処理のプログラムは以下のように作成しています CString str;//メンバー変数 //メインダイアログにてサブクラス化した際に呼ばれる CSampleStatic::PreSubclassWindow() { SetTimer(1,1000,NULL);//1秒毎に } CSampleStatic::OnTimer(UINT_PTR nIDEvent) { str.Format(_T("%d"),rand()%200); //1~199の乱数をstrに代入  Invalidate();           //OnPaint()を呼ぶ  CStatic::OnTimer(nIDEvent); } CSampleStatic::OnPaint() { CPaintDC dc(this); CFont MyFont; MyFont.CreateFont(-----); //フォント設定 CDC* myDC = GetDC(); CRect Myrect; GetClientRect(&Myrect); myDC->SelectObject(&Myrect); myDC->DrawText(str,-1,&Myrect,DT_CENTER); //strを表示 ReleaseDC(myDC); MyFont.DeleteObject(); } というプログラムを作成しているのですが、この方法でのダイアログへの文字の表示では、たとえば90が表示され、次に100が表示されるのであればいいのですが、100のあとに90が表示された時に100の上にそのまま90が表示されてしまい、うまく表示できません。 再描画のときに、上書きではなく、前回の数値を消去してから新たな数値を表示できればいいとは思うのですが、やり方がわからず、ご意見をいただければと思い質問させていただきました。 どうか宜しくお願いいたします。 開発環境は Windows CE 6.0 Visual Studio 2005 です。

共感・応援の気持ちを伝えよう!

  • 回答数2
  • 閲覧数1338
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1
  • redfox63
  • ベストアンサー率71% (1325/1856)

WM_ERASEBKGNDメッセージのハンドラOnEaseBkgndをオーバーライドして ココで消去するように組めばいいように思います CBrush型のメンバー変数を追加しておいて コンストラクタの中で初期化します CSampleStatic::CSampleStatic() {   m_brBack.Create( RGB( 255, 255, 255 ) ); } OnEraseBkgndでクライアント領域を塗りつぶします BOOL CSampleStatic::OnEraseBkgnd(CDC* pDC) { CRect rc; GetClientRect( &rc ); pDC->FillRect( rc, &m_brBack ); return CStatic::OnEraseBkgnd(pDC); } これでInvalidate()を呼んだときに OnEraseBkgndも呼ばれるので 前回描画した領域を背景色で塗りつぶします 外部から背景色をアクセスしたいなら m_brBackを変更できるような GetBKColor/SetBkColorなどをメンバー関数に加えましょう 例 メンバー変数として COLORREF m_bkColor; を追加 COLORREF CSampleStatic::GetBKColor() {   return m_bkColor; } void CSampleStatic::SetBKColor( COLORREF col ) {   if ( m_brBack.m_hObject ) {     m_brBack.DeleteObject();   }   m_brBack.Create( col ); } といった具合で ・・・

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答ありがごうございます。 返答が遅くなり、申し訳ございません。 早速、redfox63様のおっしゃるようにコードを入力し、実行してみましたところ、前回の数値にだぶって新しい数値が表示されることはなくなりました。 こういうメッセージがあるのを初めて知りました。 ありがとうございました。

関連するQ&A

  • ピクチャーコントロールへの描画方法について

    お世話になります、fujitomoです。 現在、Visual Studio2005にてC++のダイアログベースのアプリケーションを作成しており、行き詰った箇所があったため質問させて頂きました。 アプリケーションの内容としては 現在、アプリケーションで、ダイアログベース上にピクチャーコントロールを2つ設置し、それぞれに波形を描画させています。 ピクチャーコントロールへの波形の描画にはメモリデバイスコンテキストを使い、それぞれ波形描画用のCStatic派生クラスを作成し、そのクラスを SubclassDlgItem でメインダイアダイアログのサブクラスとし、描画間隔として、それぞれの描画クラス内で SetTimer(1,10,NULL) でタイマーイベントを起こし、メモリデバイスコンテキストの描画更新をしています。 ここで質問させていただきたい事なのですが、 2つのピクチャーコントロールのうち、1つのピクチャーコントロールへのみ波形描画を実行させているときはピクチャーコントロールの端から端まで描画が約7秒かかるのに対し、 2つのピクチャーコントロールの描画を同時に実行させた場合には端から端までで約11秒もかかってしまいます。 これを何とか、1つのピクチャーコントロールへの描画時間と同じ時間まで早く出来ればなと思っているのですが、どの様に工夫すれば時間短縮をさせることが出来ますでしょうか? 2つのクラスでそれぞれ10msのタイマーを動かしているのが問題なのかと思い、メインダイアログで10msのタイマーイベントを発生させ、それぞれの描画クラスに描画更新のメッセージを送信させるようにコードを変更してみたのですが、やはり同じ結果となりました。 開発環境は Widows CE 6.0 Visual Studio 2005 です。 ご意見、ご回答をお待ちしております。よろしくお願い致します。

  • 3つのスタティックに共通の動作をさせる手法

    お世話になります、fujitomoです。 現在、Visual Studio 2005にてVisual C++のMFCを使ったダイアログベースの プログラムを作成しております。 そこで行き詰ってしまった箇所があった為、今回質問させて頂きました。 アプリケーションの内容としては オリジナルのCStatic継承のクラスを作成し、そのインスタンスを3つ、メインダイアログ内のメンバ変数として定義します。 これらのインスタンスの動作としては、1秒毎に乱数を計算し、それをダイアログ上に表示させる、といったことをします。 ここで質問したいことなのですが、 これら3つのCStaticにはある範囲をもたせており、乱数がその範囲外になるとCStaticの数値、背景の色を変更させたいと思っています。 そこで、これら3つのうち、1つでもその乱数が範囲外になった場合に、3つとも全てのCStaticの数値、背景の色を変化させるにはどのようにすればいいでしょうか? イメージとしては、3つのCStaticがある1つの親からの継承で、その親側で色の変化のコードを作成すれば、それが子のクラスのCStaticクラスにも影響を与えるのかな?と思っています。 なにかご意見がありましたら、宜しくお願い致します。 尚、開発環境は Windows CE 6.0 Visual Studio 2005 です。 ご回答をお待ちしております。

  • ダイアログにビットマップを貼り付けた時にフリーズしてしまう

    お世話になります、fujicafeです。 現在、MFCにてダイアログベースのアプリケーションを作成中なのですが、ダイアログにビットマップを貼り付けてOnPaint()で表示するようにプログラムを作成したのですが、何度かダイアログの表示を繰り返すとOnPaintでのビットマップの読み込みが途中まででフリーズしてしまう現象が起きてしまいました。 プログラムは以下のように作成しています void C****Dlg::OnPaint() {  CDC* pDC = this->GetDC(); CDC myDC; CBitmap newbitmap; CBitmap* oldbitmap; CRect rc; GetClientRect(rc); newbitmap.LoadBitmap(IDB_BITMAP); myDC.CreateCompatibleDC( pDC ); oldbitmap=myDC.SelectObject( &newbitmap ); pDC->BitBlt( 0, 0, rc.Width(), rc.Height(), &myDC, 0, 0, SRCCOPY ); myDC.SelectObject(oldbitmap); } としています。 初めにこのダイアログを表示時は、ちゃんとビットマップが表示されるのですが、他のダイアログでこのダイアログを表示させた時にビットマップが上半分まで表示されて、動作がフリーズしてしまう現状です。 なにかよい打開策がありましたら、教えていただけたらと思っています。宜しくお願いいたします。

その他の回答 (1)

  • 回答No.2
  • redfox63
  • ベストアンサー率71% (1325/1856)

OnPaintだけでもできますけどね ・・・ DrawTextのフラグに DT_CALCRECTを加えれば 引数のRECTに描画する領域を返します ただし 実際の描画はされません その返された RECTを クラス変数などで記憶しておいて 次回の描画の際にはその領域だけ 背景色で塗りつぶすとか この方式の弱点は 2回のDrawTextを実行するといった点です 一度目は DT_CENTER | DT_CALCRECT ... 領域計算 二度目は DT_CENTER ... こちらで実際に描画 になります 前回の回答は背景色でコントロール全体を塗りつぶしています コントロールが大きくなると描画する無駄が生じます また、OnPaintでまいかいFontを作成していますが 頻繁に大きさや太さなどの情報が変化するのでなければ クラス変数にでFontを確保して コンストラクタで初期化、デストラクタで破棄といった具合でもいいと思います OnPaintでわざわざ GetDCを使いDCを取得していますが もともとの CPaintDCを使いたくない理由があるのでしょうか デフォルトの CPaintDCなら デストラクタでDC自体を開放しますので ReleaseDCを使って開放する必要もありません

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • if文の判定について

    <環境> WIN98 VC++6.0 MFC  ダイアログベースにて 以下コードにて、タイマーによる変数nの変化に伴い絵1と絵2が切り替わっています。 int n; void CxxxDlg::OnPaint() { 略 m_p9[0].LoadBitmap(IDB_BITMAP1); m_p9[1].LoadBitmap(IDB_BITMAP2); tempDC9.SelectObject(&m_p9[n]); 略 } void CxxxDlg::OnTimer(UINT nIDEvent) { n=n+1; if(n>=2){ n=0; } Invalidate();   CDialog::OnTimer(nIDEvent); } ところがコードの一部を以下のように変更すると、 if文で正しく判定できなくなります。 どうしてなのでしょうか? if (n=0){ m_p9[0].LoadBitmap(IDB_BITMAP1); } m_p9[1].LoadBitmap(IDB_BITMAP2);

  • メインダイアログが最背面に表示されてしまいます。

    お世話になります、fujitomoです。 C++のダイアログベースのプログラムを作成しているのですが、ご質問 させていただきたい件がありまして、こちらへ書かせて頂きました。 質問させて頂きたい内容は、メインダイアログにて、他ダイアログをAfxBeginThread()を用いて別スレッドでモーダル表示させた時、その他ダイアログを他ダイアログ内でEndDialog(IDOK)で閉じた際に、メインダイアログが最背面になってしまうのですが、この原因として考えられることはありませんでしょうか? ちなみに、他ダイアログを別スレッドではなく、メインダイアログ内にてモーダル表示をし、EndDialog(IDOK)で閉じた際には、メインダイアログが最背面になることはありませんでした。 参考となるご意見がありましたら、よろしくお願い致します。 開発環境は Visual Studio 2005です。

  • Visual Studioのタイマ処理を使って描画を行うプログラムを

    Visual Studioのタイマ処理を使って描画を行うプログラムを 作成したのですがうまくいきません. プログラムの開発環境はWindows XP SP2でVC++6.0 外部に接続したセンサからのデータを50Hzで サンプリングして そのデータを元に描画を行う予定なのですが計測時間が100秒を超えると 異常終了してしまいます. 原因がよく分かりません. どうしたらよいのでしょうか? void CMyDlg::OnSamplingStart() { i=0; // サンプリング用タイマ開始 //なぜか12にするとちょうど50Hzでサンプリングする SetTimer(1,12,NULL); // 0.02秒毎タイマ割り込み,50Hz } void CMyDlg::OnTimer(UINT nIDEvent) { /* ここで,センサからのデータをサンプリングし,いろいろな計算をする. */ CDC* pDC=m_pict.GetDC(); CRect myRECT; m_pict.GetClientRect(myRECT); pDC->FillSolidRect(myRECT, RGB(255,255,255)); CPen BlueBoldPen,*OldBlueBoldPen; BlueBoldPen.CreatePen(PS_SOLID,5,RGB(0,0,255)); OldBlueBoldPen=pDC->SelectObject(&BlueBoldPen); pDC->MoveTo((int)(X0/10),(int)(Y0/10)); pDC->LineTo((int)(L3_x[i]/10),(int)(L3_y[i]/10)); pDC->LineTo((int)(C7_x[i]/10),(int)(C7_y[i]/10)); // ペンを元に戻す pDC->SelectObject(OldBlueBoldPen); BlueBoldPen.DeleteObject(); m_time=(double)i/50; UpdateData(FALSE); i=i+1; CDialog::OnTimer(nIDEvent); } 計測終了はボタンを押して終了します. どうが具体的な解決策を教えてください.

  • SDIでTabCtrlを使用

    VC++でSDIにTabCtrlを用いたアプリケーションを作成しようとしているのですが、どうも上手くいきません。 SDIWindowにタブを表示する方法はわかったのですが、タブの上にどのように表示させるものを登録すればよいのか、わかりません。CStaticを継承したクラスを作成し、OnPaint()に描画処理を入れればよいのでしょうか? ※今回はOpenGLを表示し、タブ切り替えで画面を変えたいと考えています。 もし、方法をご存知の方おられましたら教えていただけないでしょうか?

  • VC++ タブコントロールについて

    以下の環境にてタブコントロールを実装しようとしています。 ・VisualStudio2008 VC++ ・ネイティブ(.NET未使用) ・ダイアログベース、スタティックライブラリ タブを表示させるメインダイアログと他に、子ダイアログ3つを用意して タブが押されたときに表示をON/OFF(ShowWindow使用)させるものを作ったのですが、 以下の問題が出ています。 うまい対策または、タブコントロールの文献で参考になるサイトを教えてください。 [現象と質問] ・メインダイアログを移動させると子ダイアログが追従しない。  → OnPaint()にてOnTcnSelchangeSelectTab()を呼ぶようにしたら追従しましたが、    すばやくダイアログを動かすと、子ダイアログが遅れてついてくるように見えてしまいます。    子ダイアログを追従させるうまい方法(本来のやりかた)はどうすればよいでしょうか。 ・子ダイアログをクリックすると、メインダイアログのタイトルが薄くなる(裏に隠れるような感じ)。  → メインダイアログと子ダイアログのプロパティの組み合わせでなんとかなると思っていますが、    どのようにしたらいいのか、てこずっています。    アドバイスをいただけたらと思います。

  • ダイアログ間のメッセージの送信について

    いつもお世話になっております。 現在、Visual Studio 2005にてMFCのダイアログベースのアプリケーションを作成しており、メッセージの送信の件で詰まった箇所があり質問させて頂きました。 現在のアプリケーションの全体像なのですが、 ダイアログベースなので、アプリケーション立ち上げ時に1つメインダイアログが表示されます。 そのメインダイアログ内にボタンを設置したとして、それぞれのボタン1,ボタン2からダイアログ1,ダイアログ2をDoModal()で表示させます。 それぞれのダイアログ1,2にはボタンが1つずつ設置されているとします。 質問させて頂きたいことは メインダイアログへダイアログ1,2からメッセージ送信をする場合には ::SendMessage(GetParent()->GetSafeHwnd(),MYMSG,0); でメッセージ送信をすることは出来ました。 しかしメインダイアログから呼び出されるダイアログ1,2間でメッセージを送信する場合に,例えばダイアログ1からダイアログ2へメッセージを送信させたいときに void C****1Dlg::OnBnClicked(){ C****2Dlg m_dlg2; ::SendMessage(m_dlg2.GetSafeHwnd(),MYMSG,0); とダイアログ1のボタンクリック時の関数内にコードを入力してもダイアログ2へメッセージは送信されず(ダイアログ2内のメッセージ受信関数OnMyMsg()が呼ばれず)、そのままスルーされるようなのです。 上述のコードで何か間違えている箇所があるでしょうか? メッセージを扱うのは初めてで、とにかく相手先のウィンドウのハンドルを取得できればいいのかなと思ってコードを書いてみたのですが。。 ご存知の方がいらっしゃいましたら、ご意見宜しくお願い致します。 尚、開発環境は Windows CE 6.0 Visual Studio 2005 です。

  • 別のクラスからのタイマの起動方法

    CXXXDlg ダイアログクラスに // ---------- タイムカウントタイマ起動 ---------- UINT CXXXDlg::StartTimeCount(UINT Interval) {   return SetTimer(1, Interval, NULL); } と言うメンバ関数を作り、別のクラスCTestで、下記の様な 感じでタイマ起動をしてOnTimerにて、ある変数のインクリ メント行おうとしているのですが、エラーが発生してしまいます。(コンパイルはOKです。OnTimerはもちろんCXXXDlgクラスに宣言) void CTest::TestTest() { CXXXDlg CXDlg; //100msタイマ起動 CXDlg.StartTimeCount(100); <- ここでエラー . . . (処理) . . . } WM_TIMERメッセージはウインドウが無いといけないことは 知っているのですが、上記の様な起動の仕方でも、やはり 駄目なのでしょうか?理由を教えて頂けるとありがたいで す。また、ダイアログクラスとは別のクラスでタイマの 起動・停止が可能でしたら、その方法もご存じの方 教えて下さい。 環境はWin2000 VC++ 6.0 SP6 MFC ダイアログベース です。よろしくお願いいたします。

  • メインダイアログからの各ダイアログの呼び出し時に発生するエラーについて

    お世話になっています、fujitomoと申します。 現在、Visual C++のダイアログベースプログラムを作成しており、 メインダイアログから、各ダイアログ(計7つほど)にメッセージを送信したり、DoModal()で表示するために、メインダイアログのメンバ変数に各ダイアログのインスタンスを定義しました。 Ex) CSampleAClass A; CSampleBClass B; このように、定義し、いざメインダイアログからダイアログを呼び出そうとしたときに以下のようなメッセージのエラーが表示されました。 Unhandled exception at 0x40042c10 in Sample.exe: 0xC00000FD: Stack overflow. これはWindows CEのみのメッセージかもしれないのですが、たぶん言いたいことはスタックオーバーしてるよ、ということだと思います。 そこで、計7つのダイアログの定義を少なくして、6つにしたところ、上のエラーメッセージはでず、正常にダイアログが表示されました。 次にメンバ変数で各ダイアログのインスタンスを定義するのではなく、そのポインタを定義するようにプログラムを変更してみました。 Ex) CSampleAClass* A; CSampleBClass* B; このようにすると、計7つのダイアログをメンバ変数に定義してもエラーが発生せずに、正常にダイアログを表示させることが出来ました。 この理由はなぜでしょうか? C言語を始めて時間はたっているのですが、いまだにいまいちインスタンスのオブジェクトとそのポインタでの定義における違いがよく分かっていません。今回のことから、クラスをメンバ変数に定義するときはポインタで定義したほうがいいということなのでしょうか? ご参考となる意見がございましたら、ご意見宜しくお願い致します。 尚、開発環境は Windows CE 6.0 Visual Studio 2005 です。 宜しくお願い致します。

  • Access Violationについて

    VC++6.0 MFCダイアログベースアプリを作成しているものです。 メインダイアログの他に別ダイアログを追加しようと思い、 新規にクラスを追加し、ダイアログを作成しました。 メインダイアログに終了ボタンがあり、押下することにより、 OnClose()を呼び、アプリを終了させています。 ここで、終了ボタンを押すと、以下のメッセージが表示されます。 ハンドルされていない例外は*****にあります。 0xC0000005: Access Violation 新規追加したクラス宣言部をコメントアウトすると、例外が発生しませんでした。 VC初心者でして、このエラーがメモリー関係では?とは想像がつくのですが、 どのようにアプリに影響しているのかがわかりません。 Access Violationが発生した時の対処法とかクラスを新規追加したことによる、 影響範囲がどの程度あるのか等、ご教授願えませんでしょうか? よろしくお願い致します。

  • ダイアログを継承したダイアログの作成について

    お世話になります。 今回お聞きしたいことは、 オリジナルに作成したダイアログを継承したオリジナルのダイアログを作成した際に、オリジナルに作成した基底ダイアログのダイアログ上のコントロールや、そのコントロールの位置を継承することはできますでしょうか? ということです。 何がしたいかといいますと、4つのダイアログをメインダイアログから呼び出すのですが、その4つのダイアログには共通するコントロールがあり、そのコントロールの動作もその位置も全く同じなのです。 そのため、いちいち4つのダイアログにコントロールの貼り付けや、処理を記入せずに、その共通のコントロールをもった基底ダイアログを作成して、その基底ダイアログの継承としてダイアログが作れたらなと思い、質問させて頂きました。 継承をすると、基底クラスの関数等を使うことができるというのはわかるのですが、ダイアログ上のコントロールの位置までは不可能なのかなと疑問に思いました。 ご回答を宜しくお願い致します。 開発環境は Windows CE 6.0 Visual Studio 2005 です。