ボタンにアニメーションGIFを配置しました。アニメーションは問題ありませんが (ほとんどの場合:P)、ウィンドウが再描画 (再描画) されるとアニメーションが停止します。Paint イベントの処理中にボタン (button.Refresh() ) を更新しようとしましたが、問題は解決しませんでした。\
誰でもこれを修正する方法を知っていますか?
ボタンにアニメーションGIFを配置しました。アニメーションは問題ありませんが (ほとんどの場合:P)、ウィンドウが再描画 (再描画) されるとアニメーションが停止します。Paint イベントの処理中にボタン (button.Refresh() ) を更新しようとしましたが、問題は解決しませんでした。\
誰でもこれを修正する方法を知っていますか?
おそらく私は間違っていますが、問題は、フォームが再描画されたときではなく、アニメーション化されたオブジェクトが別のウィンドウに隠れたときにアニメーション化が停止することだと思います。これは意図された動作です。バグは、Windows Vista と Windows 7 では、ディスプレイが合成されるため、ウィンドウが「隠されている」場合でも、実際には隠されておらず、隠されていないときにペイント メッセージを受け取ることがなく、アニメーションが元に戻ることです。
このバグは、アニメーション化されたオブジェクトを持つ ButtonBase 派生コントロールに影響を与えるようです。
問題は Control.IsWindowObscured 関数です。true が返されます。ButtonBase.cs ファイルの System.Windows.Forms.ButtonBase.OnFrameChanged で、最後に次のようなコード行があることがわかります。
if (IsWindowObscured) {
StopAnimate();
return;
}
そこに問題があります。
参考までに、OnFrameChanged は ImageAnimator スレッドから呼び出されます。これは、ImageAnimator.Animate(image, eventhandler) で指定されたコールバックです。ButtonBase はこれを private void Animate(bool animate) 関数で設定します。ImageAnimator スレッドは 50 ミリ秒ごとにポーリングし、監視している画像のいずれかに新しいフレームが必要かどうかを確認します。その場合、フラグを設定してコントロールを無効にし、新しいフレームを描画します。
これは私たちにはアクセスできないので、私たちにできることはあまりないと思います。回避策として、500 ミリ秒ごとにコントロールを無効にするタイマーをフォームに実装したので、以前に停止していた場合は強制的に再起動します。それをオーバーライドしたり、アクセスすることさえできないのは非常に面倒です。残念ながら、唯一の解決策は上記のハックか、自分またはサードパーティが作成したコントロールを作成または使用することです。
明確にするために、これはデスクトップ コンポジションを使用する Windows Vista または Windows 7 でのみ発生する問題です。問題は、デスクトップ コンポジションを使用していないときのように、ウィンドウが完全に隠れることがないことです。それらは常にウィンドウマネージャーによってバッファリングされます。(Windows 2000 以降には特別なレイヤード ウィンドウがありますが、今は無視してください)。以前は、ウィンドウの一部が画面上にない場合、または別のウィンドウによって隠されている場合、ウィンドウの一部を使用できませんでした。フォーカスや位置などを変更することによってそれらがビューに戻ると、システムはその領域を再描画するように通知します。ただし、デスクトップ コンポジションを使用する場合、ウィンドウの実際の内容は別の場所にバッファリングされるため、再描画は必要ありません。これが、ウィンドウのプレビューがタスクバーや Flip-3d などで機能する理由です。副次的な影響として、隠蔽された後に再び表示されたときにペイント メッセージを受け取ることを期待するコードは失敗します。ButtonBase コードは、ビューに戻ったらペイント メッセージを受信することを想定しています。これにより、アニメーションが再び開始されます。したがって、この最適化はバグになりました。
この問題は Microsoft Connect で報告する必要がありますが、解決される可能性は低いです。