かなり長いプロセスの実行中に進行状況メッセージを表示するフォームがあります。これはWebサービスの呼び出しなので、進行状況バーに完全なパーセンテージを意味のある形で実際に表示することはできません。(プログレスバーのマーキープロパティは特に好きではありません)
アニメーションGIFを表示して、プロセスにアクティビティの感触を与えたいと思います(たとえば、Windowsコピープロセスのように、あるコンピューターから別のコンピューターにファイルが飛んでいる)。
これどうやってやるの?
かなり長いプロセスの実行中に進行状況メッセージを表示するフォームがあります。これはWebサービスの呼び出しなので、進行状況バーに完全なパーセンテージを意味のある形で実際に表示することはできません。(プログレスバーのマーキープロパティは特に好きではありません)
アニメーションGIFを表示して、プロセスにアクティビティの感触を与えたいと思います(たとえば、Windowsコピープロセスのように、あるコンピューターから別のコンピューターにファイルが飛んでいる)。
これどうやってやるの?
回答:
難しいことではありません。
考慮すべき事項:
アニメーションGIF:
アニメーションGIFを探している場合は、生成することができます。
AjaxLoad-Ajax Loading gifジェネレーター
それを行う別の方法:
私が見つけたもう1つの方法は、コードプロジェクトで見つけた非同期ダイアログコントロールです。
Application.DoEvents();
。可能なアプローチ:何かが部分的に行われたときにビジネスロジックがイベントを発生させ、Application.DoEvents()を使用してプロパティ(たとえば、進行状況バーやパーセンテージ)を更新し、アニメーションを更新できます
同じ問題がありました。バックグラウンドでの長時間の操作のため、フォーム全体(gifを含む)が再描画を停止します。これが私がこれをどのように解決したかです。
private void MyThreadRoutine()
{
this.Invoke(this.ShowProgressGifDelegate);
//your long running process
System.Threading.Thread.Sleep(5000);
this.Invoke(this.HideProgressGifDelegate);
}
private void button1_Click(object sender, EventArgs e)
{
ThreadStart myThreadStart = new ThreadStart(MyThreadRoutine);
Thread myThread = new Thread(myThreadStart);
myThread.Start();
}
この操作を担当する別のスレッドを作成しただけです。この最初のフォームのおかげで、問題なく再描画を続けています(gifの動作を含む)。ShowProgressGifDelegateおよびHideProgressGifDelegateは、gifを含むpictureBoxのvisibleプロパティをtrue / falseに設定する形式のデリゲートです。
Windowsでは、伝統的にアニメーションGIFは使用せず、AVIアニメーションはほとんど使用しないことに注意してください。それらを表示するだけのWindowsネイティブコントロールがあります。アニメーション化されたGifをAVIに(そしてその逆も)変換するツールさえあります。
System.Windows.Forms.PictureBox
コントロールでサポートされている場合は、アニメーションGIFを使用します。
同じスレッドで実行しているため、すべての処理が停止するため、長い操作を遅れて開始した場合はそうなりません。
Public Class Form1
Private animatedimage As New Bitmap("C:\MyData\Search.gif")
Private currentlyanimating As Boolean = False
Private Sub OnFrameChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
Me.Invalidate()
End Sub
Private Sub AnimateImage()
If currentlyanimating = True Then
ImageAnimator.Animate(animatedimage, AddressOf Me.OnFrameChanged)
currentlyanimating = False
End If
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
AnimateImage()
ImageAnimator.UpdateFrames(animatedimage)
e.Graphics.DrawImage(animatedimage, New Point((Me.Width / 4) + 40, (Me.Height / 4) + 40))
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
BtnStop.Enabled = False
End Sub
Private Sub BtnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStop.Click
currentlyanimating = False
ImageAnimator.StopAnimate(animatedimage, AddressOf Me.OnFrameChanged)
BtnStart.Enabled = True
BtnStop.Enabled = False
End Sub
Private Sub BtnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStart.Click
currentlyanimating = True
AnimateImage()
BtnStart.Enabled = False
BtnStop.Enabled = True
End Sub
End Class
私は同じ問題を抱えていましたが、以前はいくつかの異なる問題に直面していた実装によって、異なる解決策に出会いました。最後に、以下は、さまざまな投稿からいくつかの作品をまとめたもので、期待どおりに機能しました。
private void btnCompare_Click(object sender, EventArgs e)
{
ThreadStart threadStart = new ThreadStart(Execution);
Thread thread = new Thread(threadStart);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
次に、PictureBoxコントロールの呼び出しも実行するExecutionメソッドを示します。
private void Execution()
{
btnCompare.Invoke((MethodInvoker)delegate { pictureBox1.Visible = true; });
Application.DoEvents();
// Your main code comes here . . .
btnCompare.Invoke((MethodInvoker)delegate { pictureBox1.Visible = false; });
}
PictureBoxは[プロパティ]ウィンドウからは見えないか、以下のようにします。
private void ComparerForm_Load(object sender, EventArgs e)
{
pictureBox1.Visible = false;
}