こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

InvalidateRect Windowsアプリ

初歩的な質問すみません。
現在、Windowsアプリケーションでプログラミングをしています。

cppファイルを複数使ってプロジェクトを作成したいので、
【下記ソース】のような感じで、ウィンドウハンドルhWnd を グローバル変数hParentに格納し、
他のcppファイルからでもウィンドウハンドルを使った記述ができるようにしたつもりです。

ここからが本題なのですが、
他のcppファイルで hParentを用いてInvalidateRectを使用したところ、
WM_PAINTにメッセージが送られることなく、そのまま処理を続けてしまっています。

他のcppファイルの記述ですが、グローバル変数 HWND hParentを用いて
 InvalidateRect(hParent, NULL, FALSE);
と書いています。
戻り値には1が入っていたので失敗はしていないようです。

私としては、WM_PAINTにとんで、そこで描画処理をしてほしかったのですが・・・
アドバイスお願いします。

<環境> Microsoft Windows XP Professional Version 2002 Service Pack 3
Microsoft Visual Studio Academic Edition 2005


【下記ソース】
-----------------------------
// グローバル変数
extern HWND hParent


// インスタンスハンドルを保存し、メインウィンドウを作成
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // グローバル変数にインスタンス処理を格納します。

hWnd = CreateWindow(szWindowClass, TEXT("練習"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hParent = hWnd; // グローバル変数にウィンドウハンドルを格納

return TRUE;
}
-----------------------------
※上記関数のほかにも、こちらのcppファイル(ファイル(1))には、
  APIENTRY _TWinMain関数や、CALLBACK WndProc関数などの大元が含まれています。
  InvalidateRect関数を使っているのは、他のcppファイル(ファイル(2))ということです。

投稿日時 - 2010-12-06 17:36:50

QNo.6366968

すぐに回答ほしいです

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

ひょっとして、InvalidateRectの代わりにUpdateWindowを使いましたか?
UpdateWindowは、無効領域がある場合に描画をするので、InvalidateRectと一緒に使用しなければなりません。

投稿日時 - 2010-12-06 19:20:52

お礼

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

>ひょっとして、InvalidateRectの代わりにUpdateWindowを使いましたか?

ご指摘していただいたとおりです。
  InvalidateRect(hParent, NULL, FALSE);
  UpdateWindow(hParent);
のようにしたらWM_PAINTにメッセージを送ることができました。

ありがとうございました!

投稿日時 - 2010-12-06 22:43:05

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

InvalidateRectは、Windowsに対して対象のウィンドウに無効領域があることを知らせます。
しかし、Windowsはすぐに描画をするわけではありません。
処理に優先順位をつけ、優先順位の高い処理から行います。画面の更新は、Windowsの処理の中ではかなり優先順位の低い部類に入ります。そのため、重い処理をすると、画面が更新されなくなったりすのです。

そもそもWindowsの場合、1つのメッセージを処理している間は、基本的に別のメッセージを処理できません。メッセージを処理して、WndProcからWindowsへ制御を移さないと、次のメッセージの処理は走りません。なので、無限ループのように長時間Windowsに制御を戻さないようなことをすると、画面の更新どころかボタンクリックなどの処理もされなくなります。

というわけで、InvalidateRectを実行しても、すぐに画面が更新されるわけではありません。
すぐに更新したい場合は、UpdateWinodwを呼び出します。

投稿日時 - 2010-12-06 18:07:10

補足

早速の回答ありがとうございます。
m-take0220さんの回答を引用させていただきます。


>InvalidateRectを実行しても、すぐに画面が更新されるわけではあり
>ません。すぐに更新したい場合は、UpdateWinodwを呼び出します。

早速、UpdateWindow(hParent); として使ってみましたがダメでした。


>無限ループのように長時間Windowsに制御を戻さないようなことをす
>ると、画面の更新どころかボタンクリックなどの処理もされなくなりま
>す。

InvalidateRect使用時でもUpdateWindow使用時でもどちらも重いような感じで、確かにボタンクリックなどもできなくなっていました。

通常InvalidateRectは、WM_TIMERの中で使うことが一般的かと思われます。しかし、私の場合、WM_COMMANDで、WPARAM wParam(コマンドメッセージ?) にIDM_MOVIE(メニュー[動画]が選択)が来たときに、処理が書いてある他ファイルの関数を呼び出し、そこで InvalidateRectしようとしているので、おかしなことになっているのかもしれないです。

プロジェクトのイメージとしては、
  (1)メニュー[動画]が選択されたときは、
    InvalidateRectなどを使い、描画する モード
  (2)メニュー[計算]が選択されたときは、
    描画は一切せずに、何らかの計算結果を出力する モード
のように、2つの機能を有したものを1つのプロジェクトで作ろうと思ってます。

この2つのモードをうまく機能させたいのですが、どのように書くのが良いでしょうか? もしかしたら私の方法が根本的におかしいのかもしsれないので、何かアドバイスあればお願いします。

投稿日時 - 2010-12-06 18:48:00

あなたにオススメの質問