Windowsアプリケーションの起動時に、アプリケーションにロードするデフォルトのデータを取得するために、Webサービスを呼び出す必要があります。フォームのロード中に、バックグラウンドワーカーを実行してこのデータを取得します。このデータが取得されるまで待機カーソルを表示したい。どうすればいいですか?
Backgroundworkerを呼び出す前に待機カーソルを設定してみました。進行状況を100と報告したら、デフォルトのカーソルに戻しました。待機カーソルが表示されますが、マウスを動かすとカーソルが消えます。
環境:
編集:ジェイリッグスが提案した方法でカーソルを設定しています。マウスを動かさない場合にのみ機能します。
* * UPDATE:次のようなボタンクリックを作成しました。ボタンクリックをしてマウスを動かすと、マウスを動かしたかどうかに関係なく、待機カーソルが表示されます。
void BtnClick()
{
Cursor = Cursors.WaitCursor;
Thread.Sleep(8000);
Cursor = Cursors.Default;
}
次の場合:待機カーソルが表示され、マウスを動かすとフォーム内で消えます。ステータスバーまたはメニューバーに移動すると、待機カーソルが表示されます。
Cursor = Cursors.WaitCursor;
if (!backgroundWorker.IsBusy)
{
backGroundWorker.RunWorkerAsync();
}
void backGroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(8000);
}
void backGroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Cursor = Cursors.Default;
}
以下を実行した場合:待機カーソルが表示され、マウスを動かすとまだ表示されますが、テキストフィールド内で移動すると点滅したり消えたりすることがあります。カーソルは待機カーソルに変わりますが、妨げられません。何かをクリックしないでください。
if (!backgroundWorker.IsBusy)
{
backGroundWorker.RunWorkerAsync();
}
void backGroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
UseWaitCursor = true;
Thread.Sleep(8000);
}
void backGroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
UseWaitCursor = false;
}
UseWaitCursor
は機能しますか? (RunWorkerAsync()を呼び出す場合はtrueに設定し、完了イベントを呼び出す場合はfalseに設定します)。現在カーソルを設定するために何を使用していますか?
これに対して待機カーソルを表示しないでください。代わりに、フォームのコントロールを使用して、バックグラウンドワーカーが何かを行っていることを示します。待機カーソルは、UIスレッドが使用する適切なインジケーターです(ユーザーが何かに触れることができない/すべきではないことを示しているため)が、バックグラウンドで発生していることには適していません。
WPFでは、Backgroundworkerを開始する前にMouse.OverrideCursor
プロパティをCursors.Wait
に設定し、null
イベントでRunWorkerCompleted
にリセットすることでこれを実現しました。これまでのところかなりうまく機能しているようです。
public void go()
{
BackgroundWorker thread = new BackgroundWorker();
thread.DoWork += run;
thread.RunWorkerCompleted += taskCompleted;
thread.WorkerReportsProgress = true;
// Change mouse cursor to busy
Mouse.OverrideCursor = Cursors.Wait;
thread.RunWorkerAsync();
}
private void taskCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Reset mouse cursor
Mouse.OverrideCursor = null;
}
カーソルをデフォルトに戻すには、BGWの RunWorkerCompleted event を使用する必要があります。
編集:
BGWを起動する前に次のコードを呼び出して、カーソルが待機するように設定します。
this.Cursor = Cursors.WaitCursor;
BGWのRunWorkerCompletedイベントでカーソルをリセットします。
this.Cursor = Cursors.Default;
ここにはすでにたくさんの答えがありますが、私に役立つ別の解決策を見つけたので、それをリストに入れようと思いました。
private void ShowWaitCursor(){
Application.UseWaitCursor = true; //keeps waitcursor even when the thread ends.
System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; //Normal mode of setting waitcursor
}
private void ShowNormalCursor(){
Application.UseWaitCursor = false;
System.Windows.Forms.Cursor.Current = Cursors.Default;
}
私はこのように両方を並べて使用し、いつも期待通りに動作するように縫い合わせています。特に、ワーカーの実行中に待機カーソルを表示したい場合。これがまだ探している他の人を助けることを願っています。
MSフォーラムスレッド seWaitCursor not working but Cursor = Cursors.WaitCursor does ../ & Cursor.Current vs. this.Cursor
wFのUseWaitCursorの実装が、砂時計カーソルを表示するために実際に機能する機会を逃し、「using」ブロックで使用できるHourGlassクラスを表示することが確認されました
using (new HourGlass()) {
// Do something that takes time...
System.Threading.Thread.Sleep(2000);
}
これが私が今やっていることです、この助けが欲しいです。
private void LoadWaitCursor()
{
this.Dispatcher.Invoke((Action)(() =>
{
Mouse.OverrideCursor = Cursors.Wait;
}));
}
private void LoadDefaultCursor()
{
this.Dispatcher.Invoke((Action)(() =>
{
Mouse.OverrideCursor = null;
}));
}
他の何かがカーソルを設定している必要があります。以下のコードは、タイマーの開始時に待機カーソルを設定し、タイマーの期限が切れるとカーソルを以前の値に戻します。これは期待どおりに機能します。待機カーソルは間隔全体に残ります。もちろん、フォームの外にカーソルを移動すると、マウスカーソルが置かれているウィンドウのカーソルが表示されますが、フォームに戻すと、待機カーソルが表示されます。
public partial class MyDialog : Form
{
private Timer myTimer;
public MyDialog()
{
InitializeComponent();
myTimer = new Timer();
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Interval = 5000;
myTimer.Enabled = false;
}
private Cursor SaveCursor;
private void button1_Click(object sender, EventArgs e)
{
Cursor = Cursors.WaitCursor;
myTimer.Enabled = true;
}
void myTimer_Tick(object sender, EventArgs e)
{
Cursor = SaveCursor;
myTimer.Enabled = false;
}
}
Microsoft Reference Source は、 Control.UseWaitCursor および Control.Cursor の実装を提供します。 Control.Cursorを調べると、UseWaitCursorがTrueに設定されている場合、Control.Cursorは、コントロールに設定されているカーソルに関係なくCursor.WaitCursorを返すことがわかります。この動作のため、Control.Cursorから返された値はキャッシュできません。
// DON'T DO THIS: THIS CODE WILL BREAK IF UseWaitCursor IS SET TO TRUE
// Store the original cursor
Cursor cachedCursor = this.Cursor;
// Set the cursor to a wait cursor.
this.Cursor = Cursors.WaitCursor;
// Perform some task
// Restore the original cursor
this.Cursor = cachedCursor;
上記は無害に見えますが、実行前に誰かがControl.UseWaitCursorをTrueに設定すると、すぐに問題が発生する可能性があります。その結果、上記の最初の行でControl.CursorがCursors.WaitCursorを返すため、スタックウェイトカーソルになります。したがって、カーソルを変更するためのより良い方法は次のとおりです。
// Change the cursor as needed
this.Cursor = Cursors.WaitCursor;
// Perform some task
// Restore the default cursor when finished.
this.Cursor = this.DefaultCursor;
ほとんどの場合、必要なときに待機カーソルを表示するには、上記で十分です。ただし、コントロールの子がカーソルも変更する場合、子によって設定されたカーソルは、親に設定されたカーソルをオーバーライドします。 IEカーソルのカーソルをCursors.WaitCursorに設定するフォームでラベルのカーソルをCursors.IBeamに設定すると、フォームにWaitCursorが表示されている間、ラベルにはIBeamが表示されます。この場合、Control.Cursorは、Control.DefaultCursorがフォームに設定されたWaitCursorを表示するのと同じ値を返します。ここにControl.UseWaitCursorが入ります。フォームにUseWaitCursorを設定すると、そのすべての子にもUseWaitCursorが設定されます。フォーム上のどのコントロールも、上記の壊れたコードを使用していません。DataGridViewは、上記の壊れたコードを使用した多くのコントロールの1つにすぎません。
しかし、WaitCursorが不要で、コントロールのユーザーが外部から設定したカーソルを維持したい場合はどうでしょうか。この場合、オプションは限られています。コントロールのユーザーが設定したカーソルを受け取るには、コントロールのCursorプロパティをオーバーライドする必要がありますORリフレクションを使用して内部カーソルにアクセスする必要がありますベースのControlクラスによって格納された値。その後、上記の最初のメソッドを使用して、カーソルのキャッシュと復元を行うことができます。*注:ベースの結果ではなく、コントロールのユーザーが設定した内部カーソル値をキャッシュする必要があります。カーソル!