2011-06-24 4 views
0

私は、2つのソースイメージ(塗りつぶして塗りつぶしたもの)を使用してプログレスバーを描画するWIN32オーナー描画静的コントロールを持っています。WIN32:オーナーが描画したスタティックコントロールに自分自身をリフレッシュするように指示する方法を教えてください。

case WM_DRAWITEM: 
    { 
     DRAWITEMSTRUCT* draw = (DRAWITEMSTRUCT*)lparam; 
     // Manually draw the progress bar. 
     if(draw->hwndItem == hwndProgress) 
     { 
      // Progress bar is 526 pixels wide. 
      int left = progressPercent * 526/100; 
      // Paint sections of window with filled and unfilled bitmaps 
      // based on progress bar position. 
      HDC hdcMem = ::CreateCompatibleDC(draw->hDC); 
      ::SelectObject(hdcMem, hBmpProgressFull); 
      ::BitBlt(draw->hDC, 0, 0, left, 36, hdcMem, 0, 0, SRCCOPY); 
      ::DeleteDC(hdcMem); 
      HDC hdcMem2 = ::CreateCompatibleDC(draw->hDC); 
      ::SelectObject(hdcMem2, hBmpProgressEmpty); 
      ::BitBlt(draw->hDC, left, 0, 526-left, 36, hdcMem2, left, 0, SRCCOPY); 
      ::DeleteDC(hdcMem2); 
      return TRUE; 
     } 
    } 
    return 0; 

しかし、私は物事を正しく消去して再ペイントすることができないようです。私はWM_PAINTとRedrawWindowでのSendMessageを試したし、どちらもはかなり右に働いています

bool SetLoginProgressBar(float value) 
{ 
    if(hwndProgress != NULL) 
    { 
     progressPercent = (int)(value * 100.0); 
     //::RedrawWindow(hwndProgress, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT); 
     ::SendMessage(hwndProgress, WM_PAINT, NULL, NULL); 
    } 
    return true; 
} 

代わりに新しい値でウィンドウを再描画する、それだけで最初に描画された画像と一緒にそこに座っていると、さらに描画コマンドを無視します。それは、0%、50%などの初期値の進捗状況を正しく描画し、WM_DRAWITEMメッセージハンドラコードが呼び出されていることを確認できます。

ので、WIN32に消去して再描画するために、このコントロールを伝えるための正しい方法は何ですか?

ですが、私はBeginPaint関数/ EndPaintような何かを、または私が渡されてきたDRAWITEMSTRUCTでのhDCを削除する必要があること可能ですか?

+1

コントロール領域をカバーする矩形でInvalidateRect()を呼び出してみましたか? – Rom

答えて

6

あなたがDCを破壊する前に、メモリDCからビットマップを選択解除されていません。おそらくビットマップは、Windowsがそれらを再度選択することを許可しない状態にあるので、BitBltsは失敗しています。

P.S. RedrawWindowは私がこの状況で使っているものです。 InvalidateRectも動作しますが、メッセージループが実行されている場合のみです。これは別の観察につながります。あなたが長期間実行されている操作の途中にいる場合は、メッセージループに戻らない可能性があり、進行状況ウィンドウの更新を含むアプリケーションがハングアップしているように見えます。

+0

メッセージループが実行されていない場合は、ストーリーの終わりです。 –

+0

@David Heffernan、私が意図している意味は「掛けられている」とは、一時的な条件であることです。 –

+0

私はRedrawWindowを自分で使う必要はなかった。私はInvalidateRectが十分ではない理由を想像することはできませんが、それは良い理由があると確信しています。 –

3

InvalidateRect()は、あなたが呼び出す必要があり機能です。

あなたは決して送信したり、WM_PAINTメッセージ・ウィンドウマネージャを投稿し、あなたのために彼らは(自分のウィンドウ上にドラッグ、例えば窓)を必要としているときことを行います。再描画が、ウィンドウマネージャが知らない変更によるものである場合は、InvalidateRect()を呼び出して再描画サイクルを強制します。 lpRectNULLを渡すと、クライアント領域全体が再描画されます。 TRUEbEraseに渡すと、再ペイントサイクルが開始されるときにバックグラウンドが強制的に消去されます。

InvalidateRect()を呼び出すと、WM_PAINTメッセージがメッセージキューに置かれ、InvalidateRect()関数呼び出しが返されます。次にメッセージキューをクリアすると、メッセージはWM_PAINTと処理されます。

私はあなたがPetzoldのプログラミングのWindows帳のコピーを手に入れると、それについてのすべてを読むことを示唆しています。

関連する問題