• 締切済み

画面を強制的に再描画させる方法

MFCでプログラミングをしています。 SDIプログラムで、 メニューを選択すると「ある操作」をするように 作っています。 「ある操作」の中でループを回しており、 各ループ終了毎に更新結果を逐次描画させたいのですが、 うまく行きません。 ループの最後に Invalidate(TRUE) を書いてだめだったので、 pView->SetRedraw(TRUE); pView->RedrawWindow(); pDoc->UpdateAllViews(NULL); なども併用してみたのですが、 通過するだけで何もされません。 どなたかご教示よろしくお願いします。

  • zico
  • お礼率60% (48/80)

みんなの回答

回答No.5

InvalidateRect(0,0,false); //画面全体に再描画を要求 似たようなプログラムを作っていたところです HWNDを指定するところに0を渡しています 0はデスクトップ自体のHWNDを示しているので。 これで全てのウィンドウが再描画を開始します。 実証済みです

参考URL:
http://www.ne.jp/asahi/nagoya/ahomaro/builder/cpb-050.html
回答No.4

これはもしかすると、コマンドハンドラの中にループ処理がかかれているのではないでしょうか。 その場合、コマンドハンドラから抜けなければ Invalidate(TRUE) が発行した再描画メッセージを処理するチャンスがやってきません。 定期的にコマンドハンドラからメッセージループに処理を戻してやるか、別スレッドを作成すると簡単になります。 ユーザー インターフェイス スレッド を検索してみてください。

  • NINJA104
  • ベストアンサー率43% (133/306)
回答No.3

性懲りも無くまた来ました。 API32では強制全画面アップデートを掛けたい場合、 以下の呪文?を唱えます。 hWnd = 該当ウィンドウのウィンドウハンドル  InvalidateRect( hWnd, NULL, FALSE );  UpdateWindow( hWnd ); 多少のヒントになれば... #実は全く意図と違っていたりして...m(_"_;m

  • papataku
  • ベストアンサー率18% (11/58)
回答No.2

UpdateData(TRUE)かUpdateData(FALSE)だったと思います。

zico
質問者

補足

ご回答ありがとうございます。 早速MSDNで検索してみたのですが、 updatedataは ダイアログボックス用のコマンドのようです。 通常のビューの場合で、お心当たりあればお願いします。

  • NINJA104
  • ベストアンサー率43% (133/306)
回答No.1

MFCのクラスだとどうやるのかな... C(API及びAPI32)の場合では、Redraw用のレクトアングル情報を与え直してからUpdateするようにしていました。

関連するQ&A

  • ダイアログでの再描画

    こんばんわ。 ダイアログに2つBMPが表示されているとします。 説明上、AとBとします。 なんらかの処理後、 Aを表示したまま。 Bを表示されないよう消去したいのです。 コントロールを指定して描画をできないものでしょうか? 現在、 Invalidate(FALSE); GetDlgItem(IDCxxx)->Invalidate(TRUE); と、AもBも消去されないように残した後、 Bだけ再描画させて表示しないようにさせたのですが、 うまく動きません・・・。 宜しくお願いします。 Win98、VC++6.0、MFCで作成してます。

  • 初心者です。 ~時間差で再描画~

    まだまだ初心者ですが、フリーのBCCを使ってCプログラミングしているものです。 最近、トランプのゲームを作り始めて、時間差で再描画する必要が出たので InvalidateRect(hWnd, NULL, TRUE); Sleep(3000); InvalidateRect(hWnd, NULL, TRUE); と書いたのですが、うまく動作しません。 そこで、 InvalidateRect(hWnd, NULL, TRUE); Sleep(3000); と書いてみると、3秒間のブランクがあった後で、描き直されているようでした。 これはどういうことなのでしょうか。 そして、どうすれば正しく動作させられるのでしょうか。 出来れば、初心者でもわかりやすいような回答お待ちしています。

  • OnDrawが呼び出されません

    一つの画面をコントロール部と描画部にわけたものを作ろうとしています. (VC++6.0 MFC使用) ・CMyViewクラス(CFormViewクラス派生・コントロール部) ・CTest1Viewクラス(CViewクラス派生・描画部)(CTest1Docに関連付け) ・CTest1Docクラス MyViewのボタン入力でTest1Viewの画面を再描画させたいのですが,MyView内から以下のようにしてもTest1ViewのOnDrawが呼び出されません. (OnUpdateは呼び出されるようです) CTest1Doc *pDoc=(CTest1Doc *)GetDocument(); pDoc->UpdateAllViews(NULL, 1, NULL); 再描画させるにはどうすればよいのでしょうか.

  • 特定のビューへのポインタ取得方法について

    MFCプログラミング(MDI)について教えてください。 1つのドキュメントに 複数の子ウィンドウ+子ビューのセットがあるとき、 特定のビューへのポインタの取得方法を教えてください。 ちなみに、ビューの種類は、 1.CViewの派生クラス 2.CFormViewの派生クラス です。 MSDNを調べ回っった結果、 ドキュメントクラスのポインタから、 GetNextView(pos)を使って順番にビューを使うところまで来たのですが、その後が分かりませんし、 この方法の方向性自体の是非も良く分かりません。 ご指導よろしくお願いします。 POSITION pos = pDoc->GetFirstViewPosition(); while(pos != NULL) { CView* tmpView = pDoc->GetNextView(pos); if(tmpView == ???????)........????? }

  • MFCタブコントロールのグラデーション描画

    現在、VC++2010・MFC環境でMFCのタブコントロールのウィンドウ部(?)をグラデーション描画にしたいと考えています。 完成予想としては、Excelのメニュー(?)みたいな感じでグラデーションがかかるような感じにしたいのですが、現在、グラデーションの描画は何とか(たぶん無理やり)できましたが、タブを切替たり、ダイアログ自体が非アクティブ/アクティブを繰り返すとちらついてしまいます。 ソースは以下のようになっています。 ----------------------------------------------------------------- void CTabGradDlg::OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult) { // TODO: ここにコントロール通知ハンドラー コードを追加します。 int sel = m_xcTab.GetCurSel(); m_edit1.ShowWindow(SW_HIDE); m_edit2.ShowWindow(SW_HIDE); m_button1.ShowWindow(SW_HIDE); m_button2.ShowWindow(SW_HIDE); switch(sel) { case 0: m_edit1.ShowWindow(SW_SHOW); m_button1.ShowWindow(SW_SHOW); break; case 1: m_edit2.ShowWindow(SW_SHOW); m_button2.ShowWindow(SW_SHOW); break; } Invalidate(); *pResult = 0; } void CTabGradDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) { CDialogEx::OnActivate(nState, pWndOther, bMinimized); // TODO: ここにメッセージ ハンドラー コードを追加します。 switch( nState ) { case WA_INACTIVE : // 非アクティブ break; case WA_ACTIVE : // (マウスをクリックする以外の方法) アクティブ case WA_CLICKACTIVE : // (マウス クリック)アクティブ Invalidate(); break; } } ----------------------------------------------------------------- Invalidate();が原因でちらついていることまでは分かっているのですが、 なぜちらつくのか?ということと、対処方法もしくは別の方法はないのか? 別の方法があればどういったことなのか?ということが知りたいです。 初心者(小学生並み)にもわかるように教えていただければ幸いです。 宜しくお願いします。

  • MFCのタイマーのつかい方を教えてください

    タイマーのつかい方が今ひとつ分かりません。 MFCでタイピングのゲームを作成しているのですが、 25問を解き、正解だった場合もしくは制限時間を超えてしまった場合、次の問題を表示したいと思っております。 下記がプログラム内容です。 void CProgramView::Loop1(CDC* pDC) { CProgramDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if((m_nRight<26)|(0<m_nRight)) { m_nRight=0; //正解数 m_nQuestion=1; //問題数 } Haikei(pDC); //問題表示領域の枠表示 Tokei(pDC); //時計の秒針が表示される枠表示 Moji(pDC); //問題文表示 OnChar(ch, count,flags); //入力 if(m_fTimer==FALSE) { SetTimer(123,250,NULL); //タイマーをセット if(m_nQuestion<26) //25問以上問題を解いていないケース { m_fTimer = FALSE; } else m_fTimer = TRUE; //全問解いた場合 } Loop0(pDC); //秒針の描画クラス if(m_nx==715) //タイムアウトだった場合 { KillTimer(123); NGPaper(pDC); m_nQuestion++; //問題をカウント m_sAnser.Empty(); //回答文字列をクリア pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } if(m_nQuestion<m_nCount) //正解だった場合 { KillTimer(123); //タイマーを切る Tokei(pDC); //秒針の画像を消すために時計の画面を再描画 Right(pDC); //正解した場合の画像を描画 Haikei(pDC); //問題文・回答を消すために問題表示領域の枠を再描画 PartsPaper1(pDC); //正解した場合の壁紙を表示 m_nQuestion++; //問題数をカウント m_sAnser.Empty(); //回答文字列をクリアする pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } } そして、この動作を25問、解くまでループさせる関数として以下の関数を作成しました。 void CProgramView::Loop2(CDC* pDC) { if(m_fTimer==FALSE) { Loop1(pDC); } } //タイマーの内容 void CProgramView::OnTimer(UINT nIDEvent) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください if(nIDEvent == 123) { InvalidateRect(NULL); } CView::OnTimer(nIDEvent); } しかし、実際にこのプログラムを実行すると入力し、正解する間は次の問題が表示されるのですが、タイマーが切れません。 そして、制限時間になるとそこまで解いていた問題から凄い勢いで描画が始まり、止まりません。 おそらくタイマーが正常に使えていないという可能性が考えられるのですが・・・。 希望としては、25問を順次解き、解き終わった後は画像を描画し、次の問題を表示したいのですが、どうしたら良いか教えてください。

  • MFC SDIのDocからViewの関数を呼び出す方法

    現在、センサから取得したデータを処理・および表示するMFC SDIベースのプログラムを作成しております。 今まではdialogベースで作っていたのですが、今回はセンサーデータをグラフにプロット表示するためにViewがあるSDIを選びました。 現在、2画面にスプリットして、左側がViewベース、右側がFormViewベースにし、センサーの取得開始などの制御ボタンを右側のFormViewへ、あたかもダイアログベースアプリのように開発しています。左側のViewへは取得されたセンサデータをプロットするようにしています。 さて、Docの中に独自スレッドを立てて、RS232C経由で定期的にセンサデータは取得できているのですが、その数値をFormViewに配置しているEditBoxに表示させたいと考えております。 Dialogベースで作っていたときは、dialog自体のポインタをAfxBeginThreadの2番目の引数(LPVOID pParam)で渡して、Thread内から該当のEditBoxの表示を切り替える関数(CEDITのSetWindowText)を呼び出していました。 今回Docの中にThreadが立っているので、FormViewのポインタをどうやって取得すべきかわかりません。FormView内では、GetDocument()でDocを取得できますが、その逆のパターンです。 CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd(); CXXXXView* pView = (CXXXXView*)pFrame->GetActiveView(); こんな感じで取得してみたのですが、Thread内からこのpViewを呼び出すとアクセス違反で落ちてしまいます。 FormViewクラス内にOnTimerを設けて、定期的にpDocに該当変数をチェックし変化があったらEditBoxに表示させるという”非同期”の方法だと実現できるのですが、なんかしっくりきません。 知識不足で根本から考え方が違うのかもしれませんが、ご教示いただければと思います。

  • MFCダイアログベースでのボタン背景透過方法

    VC++初心者です。 MFCダイアログベースでボタンを描画したいのですが、 そのボタンの背景を透過(透明)にしたいのです。 環境はWinXP、VSC++2010です。 OnCtrlColor()関数でSetBkMode(TRANSPARENT)や brash.CreateStockObject(NULL_BRUSH)などを実装していますが、 背景は変わりません。 ちなみに、ダイアログにはbitmap画像を貼りつけています。 ボタンはCMFCButtonを使用しているので、 CMFCButtonの変数m_mfcBtnのメンバ(プロパティ?)の m_bTransparentをTrueにしてもダメでした。 なぜ背景が透過できないのかわかりません。 ご教授宜しくお願いします。

  • WIN32APIアプリでツールバー/スステータスバーの表示切り替え

    VC++6.0のwin32sdkで、MFCのSDI標準テンプレートのようにメニューでツールバー,ステータスバーを切り替えるアプリケーションにしたいと思います。 以下のようなコードにしていますが、このままでは表示非表示を切り替えた場合、中央ウインドウのサイズが変更されません。 ドラッグして全体のサイズを変更すると中央メインウインドウも正常な表示になりますが、なにか中央のウインドウを再描画する処理が必要と思われます。その再描画処理についてご教示くださいますようお願いします。 1)ステータスバーの高さ,ツールバーの高さをグローバル変数にする 2)メニューからのメッセージでこのグローバル変数を表示(夫々のバーの高さ)、非表示(夫々のバーの高さ=0)を切り替える。 3)WndProcのWM_SIZEで中央メインウインドウをMoveMindowする [グローバル変数] ---------------------------------------------- static int bShow = 16;//ステータスバーの高さ(非表示は0) static int tbShow = 25;//ツールバーの高さ(非表示は0) ---------------------------------------------- [LRESULT CALLBACK WndProcの一部] ----------------------------------------------- case WM_SIZE: ...... MoveWindow(中央のハンドル, 0, tbShow, LOWORD(lp), HIWORD(lp)-tbShow-bShow, TRUE); break; -----------------------------------------------

  • 描画のカクカクについて

    描画された画像が移動中たまに(動画を見ながら実行すると多く)カクカクするのですが、どうしたらこのカクカクをなくすことができるでしょうか? 多分ここだろうなと言うところを載せます。 //グローバル変数 static HDC g_hdcOff,g_hdcImg[MAX_IMAGE]; static HBRUSH g_hbrBg = NULL; // 背景用ブラシ static HBITMAP g_hbmImg[IMG_MAX]= {NULL}; // 画像のビットマップ //================================================================================ // オフスクリーンへ画像表示 // idx : 画像データの添え字 // x,y : 表示位置x,y // sx,sy : 画像切り出し位置x,y // w,h : 画像切り出し幅、高さ // src : 転送モード指定。通常はSRCCOPY,SRCPAINT,SRCANDなど //================================================================================ void DrawImg(int idx,int x,int y,int sx,int sy,int w,int h,DWORD src) { BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],sx,sy,src); } //================================================================================ // オフスクリーンへ画像表示。マスク表示→画像表示 // idx : 画像データの添え字 // x,y : 表示位置x,y // sx,sy : 画像切り出し位置x,y // w,h : 画像切り出し幅、高さ // mx,my : マスク切り出し位置x,y //================================================================================ void DrawImgMask(int idx,int x,int y,int sx,int sy,int w,int h,int mx,int my) { BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],mx,my,SRCPAINT); BitBlt(g_hdcOff,x,y,w,h,g_hdcImg[idx],sx,sy,SRCAND); } void Draw() { // 画面消去 HBRUSH oldbr = (HBRUSH)SelectObject(g_hdcOff, g_hbrBg); Rectangle(g_hdcOff, -1, -1, CLIENT_WIDTH+1, CLIENT_HEIGHT+1); SelectObject(g_hdcOff, oldbr); //---------------------------------------------------------- // ↓ここから描画処理 // キー状態の更新 KeyUpdate(); // プレイヤー移動 if (KeyIsHold(KC_LEFT)) { g_Player.x -= PL_VELX; if (g_Player.x < PL_LIMITL) g_Player.x = PL_LIMITL; } if (KeyIsHold(KC_RIGHT)) { g_Player.x += PL_VELX; if (g_Player.x > PL_LIMITR-g_ImgData[g_Player.type].w) g_Player.x = PL_LIMITR-g_ImgData[g_Player.type].w; } // プレイヤーの表示 DrawChr(g_Player.type, g_Player.x, g_Player.y); // ↑ここまで描画処理 //---------------------------------------------------------- // 再描画 InvalidateRect(g_hWnd,0,FALSE); UpdateWindow(g_hWnd); } // キャラクタ描画関数 // type : キャラタイプ(eChrType) // x : 表示位置X // y : 表示位置Y void DrawChr(int type,int x,int y) { DrawImgMask(g_ImgData[type].idx, x,y, g_ImgData[type].sx, g_ImgData[type].sy, g_ImgData[type].w, g_ImgData[type].h, g_ImgData[type].mx, g_ImgData[type].my); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ・・・ ・・・ ・・・ // メッセージループ while(true) { if (PeekMessage(&msg, NULL, 0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { static DWORD before_time; DWORD now_time; DWORD ideal_time=0; static int frame=0; TCHAR buff[100]; DWORD team=0; static long surplus_time=0; now_time=timeGetTime(); if(!before_time) before_time=timeGetTime(); surplus_time=(long)(now_time-before_time); ideal_time=(DWORD)(frame*1000)/60; wsprintf(buff,TEXT("%d %d %d\n"),ideal_time,surplus_time,(long)ideal_time-surplus_time); OutputDebugString(buff); if((long)ideal_time-surplus_time>0) Sleep((long)ideal_time-surplus_time); team=timeGetTime(); team-=before_time; if(team>=1000) { before_time=timeGetTime(); frame=0; } frame++; } Sleep(1); } ・・・ ・・・ ・・・ return (int)msg.wParam; } 環境はVC++2005、C言語とWINAPIっだけです。 説明が足りないのなら補足します。