5

さて、私のアプリケーションには、たくさんの winAPI といくつかのカスタム コントロールがあります。わーい...

現在、通常、アニメーション、状態の変更などのために静かに再描画するだけで、すべて正常に機能します。

しかし、私は fix() と呼ばれるクラス Window のメソッドを持っています。これは、ウィンドウ全体を更新する必要があるたびに呼び出されます。コントロールのサイズを変更し、ウィンドウを無効にします。

これが発生すると、背景が描画され、次にタブ コントロールが描画され、その上に他のすべてが描画されます。これにより、特にウィンドウのサイズを変更するときに、非常にいらいらするまばたきが発生します (fix() が常に呼び出されるため)。

私が試したこと:

  • WS_EX_COMPOSITED。これは、個々のコントロールをダブル バッファリングするだけです。改善されていますが、ちらつきは避けられません。
  • 背景描画をオフにします。問題をほとんど解決せず、実際に事態を悪化させます。

だから:ウィンドウ全体をダブルバッファリングできるようにするためのテクニック/方法/何でも必要です。WM_PAINT メッセージを自分で処理することが解決策になるかもしれないと考えましたが、どこから始めればよいかわかりません。これも仕方のないことなのかな…という感じです。

助けてください、これは重大な問題です。この愚かな小さな問題が修正されると、私は非常に安心します.

4

5 に答える 5

6

マイクロソフトがネイティブ開発者を無視していることに気付いたのはこの時です。実際、ネイティブ開発者にWPFへの移行を強制するために、Microsoftがネイティブペインティングを意図的に破壊したという妄想的な妄想を抱き始める可能性があります。

まず、を検討してWS_EX_COMPOSITEDください。WS_EX_COMPOSITEDマスタードのようです:-子コントロールの最上位のペイント順序にボットンを強制し、基本的にWM_PAINTメッセージがバッチで処理されることを示しています。これは、Windows 2000(5.0)で追加されたものであり、数行下に、デスクトップコンポジションが有効になっていると機能しないことを示しています。つまり、Aero Glassがオフになっていない限り、Windows Vista(6.0)で動作を停止し、誰がそれを実行するのでしょうか。

次に、ちらつきのないペイントを機能させるための2つの「ハック」が考えられます。

  • まず、上塗りの量を最小限に抑える必要があります。WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGSウィンドウの特定の領域が1回だけペイントされるようにするために必要です。BeginDeferWindowPosまた、サイズ変更操作をバッチ処理して、一時的な状態(1つのウィンドウが別のウィンドウと重なる場合)が発生しないようにする必要もあります(つまり、ウィンドウAのサイズが変更されたが、ウィンドウBのサイズは変更されていない場合)。

もちろん、スキンダイアログを描画したり、グループボックス、タブコントロール、またはその他の制限を使用したりする場合は、WS_EX_CLIPSIBLINGS適切ではありません。

  • WM_SETREDRAW魔法のメッセージです。この機能にアクセスするためのAPIはありませんWM_SETREDRAW。DefWindowProcによって直接処理され、基本的にウィンドウを非表示としてマークします。送信後WM_SETREDRAW, FALSE、親ウィンドウハンドル(およびそのすべての子)を使用してGetDC / GetDCEx / GetWindowDCなどを呼び出すと、画面に描画されないDCが返されます。これにより、子ウィンドウにあらゆる種類の処理を実行する機会が与えられます。送信が完了したら、を送信しますWM_SETREDRAW,TRUE(その後、ウィンドウを手動で再描画します)。すべての子ウィンドウは、もちろん、独自の時間にペイントし、親ウィンドウが背景を消去した後、WM_SETREDRAWは万能薬のようなものではありません。

壊れた後WS_EX_COMPOSITED、In .NETのWinFormsとWPFは、ネイティブコントロールを使用しないようにコントロールをゼロから書き直したため、そこでバッファリングされたペイントでベイク処理できました。そしてアルファサポートも。

于 2010-10-11T10:35:39.693 に答える
1

うーん。人々が急いでこのトピックを重複して閉じる前に、あなたの問題はダブルバッファリング自体ではなく、コントロールを再配置するときにちらつき、「手動の」ダブルバッファリングはいくつかの解決策の 1 つにすぎないことを述べておきます。

たとえばBeginDeferWindowPos、友達がちらつきを修正できる可能性があります。

免責事項: 以前は Win16 API の詳細をほぼすべて知っていましたが、API レベルのプログラミングを始めてから数年が経ちました。

乾杯 & hth.,

– アルフ

于 2010-10-11T07:07:24.313 に答える
0

コードがないと実際の状況はほとんど想像できません...しかし、WM_ERASEBKGNDを処理して、それらを受信するたびにTRUEを返して消去をスキップすることができます。

于 2010-10-11T07:06:53.930 に答える
0

ウィンドウのハンドルWM_ERASEBKGNDと実装では、各子コントロールの四角形を除外してから、残りの背景を適切に塗りつぶし、 を返すことで背景自体をペイントしたことをフレームワークに伝えますtrue。あなたの場合、タブコントロールのような他のコントロールを保持する他のすべての子コントロールに対して同じことを行います。

MFC を使用した例については、こちらを参照してください。

于 2010-10-11T07:07:34.500 に答える
0

.net にはControlStyle.AllPaintingInWmPaint、各コンテナー ウィンドウ (つまり、メイン ウィンドウとタブ) に設定する必要があるものがあります。winapi に相当するものが見つかりませんでした。しかし、これが行うことは、背景のペイントを WM_ERASEBKGND から WM_PAINT に移動することです。また、ちらつきを避けるために、子コントロールの領域を親から減算します。これを手動で行う必要がある場合があります。

WS_EX_COMPOSITED が役に立たないことに驚いています。トップレベルのウィンドウでそれを設定し、サブコントロールで RedrawWindow を呼び出さない場合、それは機能するはずです。

また、DWM/Aero の有無にかかわらずテストしてください。さまざまな結果を得ることができます。

于 2010-10-11T07:10:49.250 に答える