0

カスタムコントロールのライブラリがあります。これで、パネルのように見えるコントロールができました。それが開いたら、次のように垂直方向に成長するアニメーションを作成します。

For h As Single = 0 To finalHeight Step 0.5
    Me.Height = CInt(h)
    '  HERE I WANT TO CALL DoEvents'
Next
Me.Height = finalHeight 

ループ内でDoEventsを呼び出さないと、アニメーションは表示されず、途中で視覚的なフィードバックなしで最終的な高さを取得するだけです。

メインのWinFormプロジェクト内からDoEventsを呼び出すことはできますが、ライブラリ内から呼び出すことはできません。

深い糸の水に溺れることなく、どうすればそれを行うことができますか?

4

6 に答える 6

3

申し訳ありませんが、ここでDoEventsを安全に使用することは完全に不可能です。アニメーションの進行中にユーザーがフォームを閉じると、何も起こりません。ObjectDisposed例外でプログラムをクラッシュさせます。DoEventsを安全にするには、フォームのEnabledプロパティをfalseに設定して、ユーザーが誤ってこのような事故を引き起こさないようにする必要があります。コントロールは、特にアニメーションの場合、フォームのEnabledプロパティをfalseに合理的に設定することはできません。

回避策は非常に簡単です。15ミリ秒の間隔でタイマーを使用するだけです。アニメーションをスムーズに見せるために十分な速さ。これを行うサンプルコードは、このスレッドの私の回答にあります。

于 2010-09-21T13:04:44.090 に答える
2

たぶん、あなたはただへの参照(またはインポート)を見逃していますSystem.Windows.Formsか?DoEventsはの静的メソッドでApplicationあるため、ライブラリからも呼び出すことができるはずです。

Imports System.Windows.Forms

...

    Application.DoEvents()

(使用は危険なことをすでにご存知のようですDoEventsので、ここでは通常の講義をスキップします。)

于 2010-09-21T12:12:28.370 に答える
2

はい、電話できるはずです

System.Windows.Forms.Application.DoEvents()

コードライブラリ内から。DoEventsは悪い考えだと理解しているようですので、なぜそれを呼んでいるのかわかりません。これは、OnVisibleChangedやOnPaintなどのオーバーライド内に配置されていると思います。この場合、これらの操作中にコントロールの更新が一時停止されるため、目的の結果が得られない可能性があります。

おそらくあなたがしたいのは、シングルティックタイマーを作成し、ティック時にコントロールの高さを増やし、finalheightに達したときにタイマーを無効にするか、そうでない場合は別のティックをスケジュールすることです。または、タイマーを作成し、各ティックに上記のループを配置します。InvokeRequired使用するタイマーのタイプに応じて、クロススレッド呼び出しを認識していることを確認してください。

于 2010-09-21T12:38:32.330 に答える
1

再現の失敗。

簡単なセットアップ、アセンブリ内のUserControlでテストしました。

UCがループでDoEvents()を呼び出すと、MainFormのタイマーが刻々と進みます。

だから:あなたの問題をもう一度探してください、それはあなたが思っている場所ではありません。

于 2010-09-21T12:42:34.003 に答える
0

オリジナルのforループでMe.Refresh、doeventsを呼び出したい場所に配置します。

For h As Single = 0 To finalHeight Step 0.5
    Me.Height = CInt(h)
    Me.refresh
Next
Me.Height = finalHeight
于 2012-01-04T17:34:01.103 に答える
-1

これは私が見つけたものです:タイマーは、速い間隔でさえ、それは本当に遅いです。理由はわかりませんが、アニメーションはタイマーで非常にびくびくしています。簡略化されたコード:

 rolex = New Timer()
 rolex.Interval = 150
 AddHandler rolex.Tick,
            Sub(sender As Object, e As EventArgs)

                Me.Height += 5

                If Me.Height < finalHeight Then Exit Sub

                rolex.Stop()
                rolex = Nothing

                Me.Height = finalHeight 
            End Sub
 rolex.Start()

タイマーなしで私はループを使用します:

For i As Single = 0 To finalHeight Step 0.5
            Height = CInt(i)
            Application.DoEvents()
Next
Height = finalHeight 

これで動作しますが、問題は、アニメーションの速度がループが実行されるマシンに依存しすぎることです。このため、タイマーを使用したいのですが、先ほど言ったように遅すぎます。

ヒントはありますか?

于 2010-09-21T13:51:28.160 に答える