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


Answers:


192

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

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


10
在我看来,显示的处理程序是在表单加载时执行的...我错了吗?
ckonig 2013年

3
古老但黄金...是的,你错了。GUI无法运行并行任务,在执行另一次执行时执行某项操作很重要。
丹尼斯·齐奥尔科夫斯基

2
如果在Load事件处理程序中有一个调用Application.DoEvents()的代码,则会在Load事件处理程序完成执行之前触发Shown事件。这是因为Shown事件实际上是使用Form.BeginInvoke(ShownEvent)和DoEvents()放入消息队列的,它在加载完成之前将其触发。
Artemix 2014年

1
在C#中,这还不足以对我不起作用。我必须Shown += Form1_Shown;按照另一个线程的
ocramot

11
您应该添加This.Refresh(); 首先在您的逻辑之前进入Shown事件,它将在逻辑开始运行之前保存并刷新表单以使其完全加载
Aylian Craspa

49

我有时使用(在加载中)

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

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

但是Control.BeginInvoke的工作方式有所不同:即使我们已经在UI线程上,它也总是将工作推送到队列中。这是说“片刻”的一种非常简单的方式,但是不会给计时器等带来麻烦(无论如何,它们仍然必须做同样的事情!)。


1
并不完全了解那个。你能解释更多吗?
Torbjørn

嗨,在BeginInvoke中调用的过程完成后,可以使表单响应吗?
humpty duMpty 2012年

WPF中有什么等效功能?
MRID

6

第一次它将不会启动“ 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.
}

5

我遇到了同样的问题,并按以下步骤解决了它:

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

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

2

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


1

这是一个古老的问题,更多地取决于您何时需要启动例程。由于没有人想要null引用异常,因此始终最好先检查null,然后根据需要使用。仅此一项就可以为您节省很多痛苦。

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

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

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

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

}

}


这似乎难以置信,并且比仅捕获Shown事件有任何优势吗?
史蒂夫·史密斯,

0

我知道这是旧帖子。但是,这是我的操作方式:

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

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

-9

您可以在执行某些命令后关闭表单。

//YourForm.ActiveForm.Close();

    LoadingForm.ActiveForm.Close();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.