2

ハンス・パッサントはここで私に素晴らしい答えをくれたので、私はその仕組みを理解するためにもっと詳細を尋ねることを考えましたApplication.Run()

ドキュメントから理解できる限りApplication.Run()、現在のスレッドでメッセージループが開始され、ユーザー入力を処理できるようになっているようです(そうですか?)。オーバーロードされたバージョン Application.Run(Form)は基本的に同じことを行いますが、フォームが閉じたときにのみ存在し、デフォルトでフォームを表示します。

それはいくつかの質問を提起します:

  • Main()サブからユーザーと通信できる関数(メッセージボックスなど)を呼び出して、終了するのを待つにはどうすればよいでしょうか。
  • フォームなしでメッセージループが開始された場合、このループから新しいフォームを起動し、終了するのをどのように待ちますか?ShowDialog起動時にフォームをすぐに表示したくない場合を除いて、機能する可能性があります(たとえば、起動されたforがシステムトレイに最小化されている場合)
    • 基本的に、状況は次のようになります。サブ `Main`には、20分で実行するタスクのリストがあり、プログラムが20分で動作することをユーザーに通知するシステムトレイアイコンがあります。タイマーは20分後に刻み、約を実行する必要があります。進行状況ダイアログのインスタンスを作成するたびに、最初はタスクバーに非表示になっている15個のタスク。
    • `ShowDialog`は、不要なフォームを表示します。したがって、私が行う方法は、進行状況ダイアログに次のタスクを開始する関数へのコールバックを渡すことです。しかし、それは2番目の進行状況フォームが終了する前に、最初の進行状況フォームを終了しませんか?つまり、15のフォームが開かれることになります...
    • したがって、解決策は、メインアプリケーションループでコールバックを呼び出す(begininvoke?)ことです...ただ、コールバックを呼び出すためのループに関連付けられたフォームがないため、これを行う方法がわかりません。 ..。。

    私の質問が明確であることを願っています(私は多くのことを混乱させるかもしれません、ごめんなさい)、
    ありがとう、
    CFP。

    4

    1 に答える 1

    3

    フォームにTimer、ProgressBar、BackgroundWorkerをドロップします。最初にやりたいことは、プログラムの開始時にフォームが表示されないようにすることです。このコードをフォームクラスに貼り付けます。

    Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
        If Not Me.IsHandleCreated Then
            value = False
            Me.CreateHandle
        End If
        MyBase.SetVisibleCore(value)
    End Sub
    

    タイマーを使用してジョブを開始します。IntervalプロパティとEnabledプロパティを設定し、Tickイベントハンドラーを追加します。

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Show()
        ProgressBar1.Visible = True
        Me.Enabled = False
        BackgroundWorker1.RunWorkerAsync()
    End Sub
    

    これにより、ジョブの開始時にフォームが表示され、バックグラウンドワーカーが開始されます。BGWのWorkerReportsProgressプロパティをTrueに設定し、3つのイベントハンドラーを追加します。

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        '' Do stuff here, call BackgroundWorker1.ReportProgress to update the PB
    End Sub
    
    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
    End Sub
    
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        ProgressBar1.Visible = False
        Me.Enabled = True
        Me.Hide()
    End Sub
    

    DoWorkイベントハンドラーのコードを入力するのはあなた次第です。これらの15のジョブを実行してもらいます。プログレスバーが更新されるように、必ずBackgroundWorker1.ReportProgessを呼び出してください。これは、ProgressChangedイベントハンドラーが行うことです。RunWorkerCompletedイベントハンドラーはフォームを再び非表示にします。

    NotifyIconのコンテキストメニュー項目イベントでShow()メソッドを呼び出して、ユーザーがフォームを再び表示できるようにすることができます。ユーザーがアプリを終了できるようにするコンテキストメニュー項目でApplication.Exit()を呼び出します。BGWの実行中は、必ず無効にしてください。または、ジョブをきれいに停止する方法を実装します。

    于 2010-11-04T20:09:43.540 に答える