5

WM_PAINT手動で送信してはならず、代わりに電話する必要があることを読みInvalidateRectましたが、そうしない理由については何も見つかりませんでした。では、なぜですか?

更新は動作しますが、動作しInvalidateRectませんSendMessage(WM_PAINT)

LRESULT CALLBACK window_proc(HWND wnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
  switch (msg)
  {
    case WM_PAINT:
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(wnd, &ps);

        Polyline(..);

        EndPaint(wnd, &ps);
        return 0;

    case WM_USER:           
        // SendMessage(wnd, WM_PAINT, NULL, NULL);
        // InvalidateRect(wnd, NULL, FALSE);

        return 0;
  }
}
4

4 に答える 4

8

WM_PAINTコメントセクションの最初の文にすべきではないという状態の公式ドキュメント。真剣に、それはそうしない理由として十分なはずです.

技術的な理由については、これがその 1 つであり、BeginPaintコメント セクションから引用されていると思います。

更新領域は、InvalidateRectまたはInvalidateRgn関数によって設定され、サイズ変更、移動、作成、スクロール、またはクライアント領域に影響を与えるその他の操作の後にシステムによって設定されます。

そのため、手動でBeginPaint送信すると正しく機能しない場合があります。WM_PAINT

もっと多くの理由/驚きがあるかもしれません。

于 2014-03-16T16:58:54.820 に答える
6

すぐに再描画をトリガーしたい場合、正しいアプローチは次のいずれかです。

  1. InvalidateRect()の後にを使用しUpdateWindow()ます。

  2. を使用しRedrawWindow()ます。

WM_PAINTこれらは、生成される新しいメッセージをトリガーします。

于 2014-03-16T22:38:58.450 に答える
2

他のプログラムのウィンドウがあなたのウィンドウを覆い隠しているという情報はありません。オペレーティング システムだけがこの情報を持っています。そのため、いつ、どこでウィンドウを再描画する必要があるかを常に把握しているわけではありません。WM_PAINT と BeginPaint は、この欠けている情報を提供します。

于 2014-03-16T17:21:47.390 に答える
1

WM_PAINT本当のメッセージではないからです。

各ウィンドウには「無効な領域」、つまり「画面上のウィンドウのこの部分は最新ではなく、再描画する必要がある」を格納する構造があると考えてください。

その無効な領域は、ウィンドウ マネージャー自体 (ウィンドウのサイズ変更、カバーの解除など) によって、または 、 などの呼び出しによって変更されInvalidateRectます。ValidateRectEndPaint

さて、これはこれを処理する方法の大まかなモックアップですGetMessage:

... GetMessage(MSG* msg, ...)
{
  while(true) {
    if(ThereIsAnyMessageInTheMessageQueue()) {
      *msg = GetFirstMessageOfTheMessageQueue();
      return ...;
    } else if(TheInvalidRegionIsNotEmpty()) {
      *msg = CreateWMPaintMessage();
      return ...;
    } else {
      WaitUntilSomethingHappend();
    }
  }
}

tl;dr: WM_PAINT送信するのではなく、受信することを意図しています。

于 2015-04-24T09:57:22.457 に答える