2008-10-20 79 views
96

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

任何人都可以建议一个解决方案吗?

回答

149

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

“所示时,只有提出的第一个时间显示的格式;随后最小化,最大化,恢复,隐藏,显示或无效,并重新粉刷不会提出这个事件。“

43

我有时(在负载)

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

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

(其他城市“这个”你的表单变量,如果你正在处理上比其它实例的事件“本”)的使用。

这会将调用推送到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; 
    }); 
} 

它通过推动一个消息到所述窗口的消息队列执行此; UI线程(在某些时候)将队列中的消息出队,处理委托并向工作人员表明它已完成......这样好; -p

OK;那么如果我们在U​​I线程上使用Control.Invoke/Control.BeginInvoke会发生什么?它应付......如果你调用Control.Invoke,足够明智地知道在消息队列上的阻塞会导致立即死锁 - 所以如果你已经在UI线程上,它就会立即运行代码......这样并不能帮助我们...

但是Control.BeginInvoke的工作方式不同:它总是将工作推到队列上,即使它已经在UI线程上。这是一种非常简单的方式,可以说“暂时”,但没有定时器等的不便(它仍然必须做同样的事情!)。

+2

尼斯一个马克Gravell。还有一个诀窍袋子) – 2008-10-20 15:09:22

+1

还没有完全明白这一点。你能多解释一下吗? – 2008-10-20 15:56:17

+0

嗨马克,是否有可能使表单响应,而在BeginInvoke中调用的过程完成? – 2012-07-12 12:12:26

2

你也可以尝试把你的代码放在窗体的Activated事件中,如果你希望它发生的话,就在窗体被激活的时候。你将需要放入一个布尔型“已执行”检查,尽管它只应该在第一次激活时运行。

6

我有同样的问题,并解决它,如下所示:

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

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

您可以将部分执行后,关闭您的形式..

//YourForm.ActiveForm.Close();

LoadingForm.ActiveForm.Close(); 
2

第一次也不会启动“后装”,
它只是将它注册开始下一次装载。

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

这是一个老问题,更多依赖于何时需要启动例程。由于没有人需要空引用异常,因此最好先检查null,然后根据需要使用;只有这一点可以为你节省很多的痛苦。

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

为了最好地回答关于在表单加载事件之后何时开始执行代码的问题,需要监视WM_Paint消息或直接挂接到绘制事件本身。为什么?当所有模块已完全加载相对于表单加载事件时,绘制事件才会触发。注意:当它被设置为true时,This.visible == 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 

} 

}