C# 如何在加载表单后执行代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/218732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:37:19  来源:igfitidea点击:

How do I execute code AFTER a form has loaded?

c#.netwinformsevents

提问by adeel825

In .NET, Windows Forms have an event that fires before the Form is loaded (Form.Load), but there is no corresponding event that is fired AFTER the form has loaded. I would like to execute some logic after the form has loaded.

在 .NET 中,Windows 窗体有一个在窗体加载前触发的事件 (Form.Load),但在窗体加载后没有触发相应的事件。我想在表单加载后执行一些逻辑。

Can anyone advise on a solution?

任何人都可以就解决方案提出建议吗?

采纳答案by Matthias Schippling

You could use the "Shown" event: MSDN - Form.Shown

您可以使用“Shown”事件:MSDN - Form.Shown

"The Shown event is only raised the first time a form is displayed; subsequently minimizing, maximizing, restoring, hiding, showing, or invalidating and repainting will not raise this event."

“Shown 事件仅在第一次显示表单时引发;随后最小化、最大化、恢复、隐藏、显示或无效和重新绘制不会引发此事件。”

回答by Marc Gravell

I sometimes use (in Load)

我有时使用(在加载中)

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

or

或者

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

(change "this" to your form variable if you are handling the event on an instance other than "this").

(如果您在“this”以外的实例上处理事件,请将“this”更改为您的表单变量)。

This pushes the invoke onto the windows-forms loop, so it gets processed when the form is processing the message queue.

这将调用推送到 windows-forms 循环,因此它会在窗体处理消息队列时得到处理。

[updated on request]

[应要求更新]

The Control.Invoke/Control.BeginInvoke methods are intended for use with threading, and are a mechanism to push work onto the UI thread. Normally this is used by worker threads etc. Control.Invoke does a synchronous call, where-as Control.BeginInvoke does an asynchronous call.

Control.Invoke/Control.BeginInvoke 方法旨在与线程一起使用,并且是一种将工作推送到 UI 线程的机制。通常这由工作线程等使用。 Control.Invoke 执行同步调用,而 Control.BeginInvoke 执行异步调用。

Normally, these would be used as:

通常,这些将用作:

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;
  });
}

It does this by pushing a message onto the windows message queue; the UI thread (at some point) de-queues the message, processes the delegate, and signals the worker that it completed... so far so good ;-p

它通过将消息推送到 Windows 消息队列来做到这一点;UI 线程(在某些时候)使消息出队,处理委托,并通知工作人员它已完成......到目前为止一切顺利;-p

OK; so what happens if we use Control.Invoke / Control.BeginInvoke on the UI thread? It copes... if you call Control.Invoke, it is sensible enough to know that blocking on the message queue would cause an immediate deadlock - so if you are already on the UI thread it simply runs the code immediately... so that doesn't help us...

好的; 那么如果我们在 UI 线程上使用 Control.Invoke / Control.BeginInvoke 会发生什么?它可以应对...如果您调用 Control.Invoke,知道消息队列上的阻塞会导致立即死锁是足够明智的 - 因此,如果您已经在 UI 线程上,它只需立即运行代码...对我们没有帮助...

But Control.BeginInvoke works differently: it alwayspushes work onto the queue, even it we are already on the UI thread. This makes a really simply way of saying "in a moment", but without the inconvenience of timers etc (which would still have to do the same thing anyway!).

但是 Control.BeginInvoke 的工作方式不同:它总是将工作推入队列,即使我们已经在 UI 线程上。这是一种非常简单的说“一会儿”的方式,但没有计时器等的不便(无论如何仍然必须做同样的事情!)。

回答by Mitchel Sellers

You could also try putting your code in the Activated event of the form, if you want it to occur, just when the form is activated. You would need to put in a boolean "has executed" check though if it is only supposed to run on the first activation.

您也可以尝试将您的代码放在表单的 Activated 事件中,如果您希望它发生,就在表单被激活时。如果它只应该在第一次激活时运行,则需要进行布尔值“已执行”检查。

回答by Sharmila

I had the same problem, and solved it as follows:

我遇到了同样的问题,解决方法如下:

Actually I want to show Message and close it automatically after 2 second. For that I had to generate (dynamically) simple form and one label showing message, stop message for 1500 ms so user read it. And Close dynamically created form. Shown event occur After load event. So code is

实际上我想显示 Message 并在 2 秒后自动关闭它。为此,我必须生成(动态)简单的表单和一个显示消息的标签,停止消息 1500 毫秒,以便用户阅读。并关闭动态创建的表单。显示的事件发生在加载事件之后。所以代码是

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

回答by E Coder

You can close your form after some execution..

您可以在执行一些操作后关闭表单..

//YourForm.ActiveForm.Close();

//YourForm.ActiveForm.Close();

    LoadingForm.ActiveForm.Close();

回答by Ahmed Sabry

First time it WILL NOT start "AfterLoading",
It will just register it to start NEXT Load.

第一次它不会启动“AfterLoading”,
它只会注册它以启动 NEXT Load。

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.
}

回答by Jamie

This an old question and depends more upon when you need to start your routines. Since no one wants a null reference exception it is always best to check for null first then use as needed; that alone may save you a lot of grief.

这是一个老问题,更多地取决于您何时需要开始您的日常工作。由于没有人想要空引用异常,因此最好先检查空值,然后根据需要使用;仅此一项就可以为您省去很多悲伤。

The most common reason for this type of question is when a container or custom control type attempts to access properties initialized outside of a custom class where those properties have not yet been initialized thus potentially causing null values to populate and can even cause a null reference exceptions on object types. It means your class is running before it is fully initialized - before you have finished setting your properties etc. Another possible reason for this type of question is when to perform custom graphics.

此类问题的最常见原因是当容器或自定义控件类型尝试访问在自定义类之外初始化的属性时,这些属性尚未初始化,从而可能导致填充空值,甚至可能导致空引用异常关于对象类型。这意味着您的类在完全初始化之前正在运行 - 在您完成属性设置等之前。此类问题的另一个可能原因是何时执行自定义图形。

To best answer the question about when to start executing code following the form load event is to monitor the WM_Paint message or hook directly in to the paint event itself. Why? The paint event only fires when all modules have fully loaded with respect to your form load event. Note: This.visible == true is not always true when it is set true so it is not used at all for this purpose except to hide a form.

为了最好地回答有关何时在表单加载事件之后开始执行代码的问题是监视 WM_Paint 消息或直接挂钩到绘制事件本身。为什么?仅当所有模块都已针对您的表单加载事件完全加载时,才会触发绘制事件。注意: This.visible == true 当它被设置为 true 时并不总是 true 所以它根本不用于此目的,除了隐藏表单。

The following is a complete example of how to start executing you code following the form load event. It is recommended that you do not unnecessarily tie up the paint message loop so we'll create an event that will start executing your code outside that loop.

以下是如何在表单加载事件之后开始执行代码的完整示例。建议您不要不必要地占用绘制消息循环,因此我们将创建一个事件,该事件将开始在该循环外执行您的代码。

using System.Windows.Forms;

namespace MyProgramStartingPlaceExample {

命名空间 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

}

}

}

回答by J. Fischlein

I know this is an old post. But here is how I have done it:

我知道这是一个旧帖子。但这是我如何做到的:

    public Form1(string myFile)
    {
        InitializeComponent();
        this.Show();
        if (myFile != null)
        {
            OpenFile(myFile);
        }
    }

    private void OpenFile(string myFile = null)
    {
            MessageBox.Show(myFile);
    }