web-dev-qa-db-ja.com

フォームがロードされた後にコードを実行するにはどうすればよいですか?

.NETでは、Windowsフォームには、フォームが読み込まれる前に発生するイベント(Form.Load)がありますが、フォームが読み込まれた後に発生する対応するイベントはありません。フォームがロードされた後に、いくつかのロジックを実行したいと思います。

誰でも解決策についてアドバイスできますか?

117
adeel825

「表示」イベントを使用できます。 MSDN-Form.Shown

「Shownイベントは、フォームが最初に表示されたときにのみ発生します。その後、最小化、最大化、復元、非表示、表示、無効化および再描画してもこのイベントは発生しません。」

175

私は時々(負荷で)使用します

this.BeginInvoke((MethodInvoker) delegate {
  // some code
});

または

this.BeginInvoke((MethodInvoker) this.SomeMethod);

(「this」以外のインスタンスでイベントを処理している場合は、「this」をフォーム変数に変更します)。

これにより、呼び出しがwindows-formsループにプッシュされるため、フォームがメッセージキューを処理しているときに処理されます。

[リクエストに応じて更新]

Control.Invoke/Control.BeginInvokeメソッドは、スレッドでの使用を目的としており、UIスレッドに作業をプッシュするメカニズムです。通常、これはワーカースレッドなどで使用されます。Control.Invokeは同期呼び出しを行いますが、Control.BeginInvokeは非同期呼び出しを行います。

通常、これらは次のように使用されます。

SomeCodeOrEventHandlerOnAWorkerThread()
{
  // this code running on a worker thread...
  string newText = ExpensiveMethod(); // perhaps a DB/web call

  // now ask the UI thread to update itself
  this.Invoke((MethodInvoker) delegate {
      // this code runs on the UI thread!
      this.Text = newText;
  });
}

これを行うには、メッセージをWindowsメッセージキューにプッシュします。 UIスレッドは(ある時点で)メッセージをデキューし、デリゲートを処理し、完了したことをワーカーに通知します...これまでのところ良好です;-p

OK; UIスレッドでControl.Invoke/Control.BeginInvokeを使用するとどうなりますか?それに対処します... Control.Invokeを呼び出した場合、メッセージキューでのブロッキングが即座にデッドロックを引き起こすことを知っているのは十分賢明です。助けにならない...

ただし、Control.BeginInvokeの動作は異なります。italwaysは、UIスレッド上にすでにある場合でも、作業をキューにプッシュします。これは本当に簡単な「一瞬」の言い方をしますが、タイマーなどの不便はありません(とにかく同じことをしなければなりません!)。

45
Marc Gravell

初めて「AfterLoading」が開始されない場合、
次のロードを開始するために登録するだけです。

private void Main_Load(object sender, System.EventArgs e)
{
    //Register it to Start in Load 
    //Starting from the Next time.
    this.Activated += AfterLoading;
}

private void AfterLoading(object sender, EventArgs e)
{
    this.Activated -= AfterLoading;
    //Write your code here.
}
6
Ahmed Sabry

私は同じ問題を抱えていて、次のように解決しました:

実際には、メッセージを表示し、2秒後に自動的に閉じたいと思います。そのために、(動的に)単純なフォームとメッセージを表示する1つのラベルを生成する必要がありました。ユーザーがそれを読むために1500ミリ秒間メッセージを停止しました。そして、動的に作成されたフォームを閉じます。表示されたイベントは、ロードイベント後に発生します。だからコードは

Form MessageForm = new Form();
MessageForm.Shown += (s, e1) => { 
    Thread t = new Thread(() => Thread.Sleep(1500)); 
    t.Start(); 
    t.Join(); 
    MessageForm.Close(); 
};
5
Sharmila

フォームがアクティブ化されたときに、フォームのActivatedイベントにコードを挿入することもできます。最初のアクティベーションでのみ実行することになっている場合は、ブール値の「実行済み」チェックを入れる必要があります。

2
Mitchel Sellers

これは古い質問であり、ルーチンをいつ開始する必要があるかによります。誰もnull参照例外を必要としないため、最初にnullをチェックしてから必要に応じて使用することが常に最善です。それだけで多くの悲しみを救うことができます。

このタイプの質問の最も一般的な理由は、コンテナまたはカスタムコントロールタイプが、それらのプロパティがまだ初期化されていないカスタムクラスの外部で初期化されたプロパティにアクセスしようとするためです。オブジェクトタイプ。これは、クラスが完全に初期化される前-プロパティの設定などを完了する前に実行されていることを意味します。このタイプの質問のもう1つの考えられる理由は、カスタムグラフィックスを実行するタイミングです。

フォームロードイベントに続いてコードの実行を開始するタイミングに関する質問に最もよく答えるには、WM_Paintメッセージを監視するか、Paintイベント自体に直接フックします。どうして? Paintイベントは、フォームロードイベントに関してすべてのモジュールが完全にロードされたときにのみ発生します。注:This.visible == trueは、trueに設定されている場合は常にtrueとは限らないため、フォームを非表示にすることを除いて、この目的にはまったく使用されません。

以下は、フォームロードイベントに続くコードの実行を開始する方法の完全な例です。 Paintメッセージループを不必要に結び付けないことをお勧めします。そうすることで、ループの外側でコードの実行を開始するイベントを作成できます。

using System.Windows.Forms;

名前空間MyProgramStartingPlaceExample {

/// <summary>
/// Main UI form object
/// </summary>
public class Form1 : Form
{

    /// <summary>
    /// Main form load event handler
    /// </summary>
    public Form1()
    {
        // Initialize ONLY. Setup your controls and form parameters here. Custom controls should wait for "FormReady" before starting up too.
        this.Text = "My Program title before form loaded";
        // Size need to see text. lol
        this.Width = 420;

        // Setup the sub or fucntion that will handle your "start up" routine
        this.StartUpEvent += StartUPRoutine;

        // Optional: Custom control simulation startup sequence:
        // Define your class or control in variable. ie. var MyControlClass new CustomControl;
        // Setup your parameters only. ie. CustomControl.size = new size(420, 966); Do not validate during initialization wait until "FormReady" is set to avoid possible null values etc. 
        // Inside your control or class have a property and assign it as bool FormReady - do not validate anything until it is true and you'll be good! 
    }

    /// <summary>
    /// The main entry point for the application which sets security permissions when set.
    /// </summary>
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }


    #region "WM_Paint event hooking with StartUpEvent"            
    //
    // Create a delegate for our "StartUpEvent"
    public delegate void StartUpHandler();
    //
    // Create our event handle "StartUpEvent"
    public event StartUpHandler StartUpEvent;
    //
    // Our FormReady will only be set once just he way we intendded
    // Since it is a global variable we can poll it else where as well to determine if we should begin code execution !!
    bool FormReady;
    //
    // The WM_Paint message handler: Used mostly to Paint Nice things to controls and screen
    protected override void OnPaint(PaintEventArgs e)
    {
        // Check if Form is ready for our code ?
        if (FormReady == false) // Place a break point here to see the initialized version of the title on the form window
        {
            // We only want this to occur once for our purpose here.
            FormReady = true;
            //
            // Fire the start up event which then will call our "StartUPRoutine" below.
            StartUpEvent();
        }
        //
        // Always call base methods unless overriding the entire fucntion
        base.OnPaint(e);
    }
    #endregion


    #region "Your StartUp event Entry point"
    //
    // Begin executuing your code here to validate properties etc. and to run your program. Enjoy!
    // Entry point is just following the very first WM_Paint message - an ideal starting place following form load
    void StartUPRoutine()
    {
        // Replace the initialized text with the following
        this.Text = "Your Code has executed after the form's load event";
        //
        // Anyway this is the momment when the form is fully loaded and ready to go - you can also use these methods for your classes to synchronize excecution using easy modifications yet here is a good starting point. 
        // Option: Set FormReady to your controls manulaly ie. CustomControl.FormReady = true; or subscribe to the StartUpEvent event inside your class and use that as your entry point for validating and unleashing its code.
        //
        // Many options: The rest is up to you!
    }
    #endregion

}

}

1
Jamie