Load vs. Shown events in Windows Forms

2020-02-23 06:06发布

Hopefully I'm just missing something obvious, but I'm trying to get my head around the differences between the Load and the Shown events in Windows Forms.

Traditionally, I've only used Load (or actually OnLoad, since I think it's cleaner to override a method than to rely on the designer to hook up an event on yourself), since that is available in all versions of .NET. With .NET 2.0 the Shown event was introduced.

Now, if you look at the descriptions for these in the MSDN documentation ("Load: Occurs before a form is displayed for the first time.", "Shown: Occurs whenever the form is first displayed.") it sounds like the Load event should occur, then the form should become visible, then the Shown event should occur; the combination of the two thereby letting you carry out some tasks both before and after the form is visible. Makes sense, right?

However, experimentation has shown that the Shown event invariably occurs before the Load event, whenever I try it (and both occur before the form becomes visible). And yet, when I google around whenever I discover a page that talks about the order these events are fired in, they always list the Load event being fired first.

Am I just going crazy, or have I missed something? (And if they do occur at about the same time, then why was the Shown event added in the first place?)

(My current solution for doing something both before and after showing the form is to use OnLoad for the "before showing" stuff and start a short-duration one-shot timer for the "after showing" stuff. Which works OK and reliably, but it's a bit ugly and I was hoping there was a cleaner solution. But it looks like the Shown event isn't it.)

6条回答
欢心
2楼-- · 2020-02-23 06:13

I just checked and load fires before Shown as it should.

There's obviously something wrong in your approach.

查看更多
在下西门庆
3楼-- · 2020-02-23 06:27

The Shown event occurs after the Load event. The main difference is not in the visibility of the form but in its state (width, height, etc.).

To clarify, here is an example. Consider a form that has a default size of 100, 200 and a WindowState that is Maximized. In the Load event handler, the size will be 100, 200. But in the Shown event handler, the size will be your screen size.

查看更多
家丑人穷心不美
4楼-- · 2020-02-23 06:28

Here's the sequence of event I traced. May this will help others to decide how they would like to call or set their custom event handling

Events traced

Form - Client Size Changed : 8/14/2010 10:40:28 AM
Form - Control Added - button1 : 8/14/2010 10:40:29 AM
Form - Constructor : 8/14/2010 10:40:29 AM
Form - Handle Created : 8/14/2010 10:40:29 AM
Form - Invalidated : 8/14/2010 10:40:29 AM
Form - Form Load event : 8/14/2010 10:40:29 AM
Form - Loaded : 8/14/2010 10:40:29 AM
Form - Create Control : 8/14/2010 10:40:29 AM
Form - OnActivated : 8/14/2010 10:40:29 AM
Form - Shown : 8/14/2010 10:40:29 AM
Form - OnPaint : 8/14/2010 10:40:29 AM
Form - Invalidated : 8/14/2010 10:40:29 AM
Form - OnPaint : 8/14/2010 10:40:29 AM

查看更多
SAY GOODBYE
5楼-- · 2020-02-23 06:32

one thing I know for sure is the shown event is executed after everything on the InitializeComponent is done and the form is showing up and it's in the shown that you should put the code that move object on the form based on the location of other object

do a quick test with an empty project:

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    MsgBox("load") 'form is still visible = false
End Sub

Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
    MsgBox("shown") ' form is now visible = true
End Sub
End Class
查看更多
欢心
6楼-- · 2020-02-23 06:33

Avoid using MessageBox.Show() to debug this. It pumps a message loop, disturbing the normal flow of events. The Load event is triggered by Windows sending the WM_SHOWWINDOW message, just before the window becomes visible. There is no Windows notification for "your window is now fully shown", so the WF designers came up with a trick to generate the Shown event. They use Control.BeginInvoke(), ensuring the OnShown() method gets called as soon as the program goes idle again and re-enters the message loop.

This trick has lots of other uses, particularly when you have to delay the execution of code started by an event. However, in your case it falls apart because you use MessageBox.Show(). Its message loop dispatches the delegate registered with BeginInvoke(), causing the Shown event to run before the window is shown.

There are lots of other ways to get diagnostics beyond MessageBox. Debug.Print() and Console.WriteLine() are handy, their output goes to the Visual Studio Output Window without having any detrimental effects on the normal event firing sequence. A simple breakpoint can do wonders too.

查看更多
孤傲高冷的网名
7楼-- · 2020-02-23 06:40

Ok, I think I've worked out what's really going on now, and where my confusion was coming from (although not why it behaves that way). It looks like the Shown event actually occurs inside the Load event.

Given this code:

 protected override OnLoad(EventArgs e)
{
    MessageBox.Show("Enter Load");
    base.OnLoad(e);
    MessageBox.Show("Exit Load");
}

protected override OnShown(EventArgs e)
{
    MessageBox.Show("Enter Shown");
    base.OnShown(e);
    MessageBox.Show("Exit Shown");
}

then the messages are shown in this order:

  1. Enter Load
  2. Enter Shown
  3. Exit Shown
  4. Exit Load

The Visible property is True in all four cases yet in none of these cases is the form actually visible on screen (painted).

The really weird thing though is that if I comment out the "Exit Load" messagebox then the form does appear on screen before the "Enter Shown" message appears. It seems to be code executed after the base OnLoad call that it's really objecting to somehow.

查看更多
登录 后发表回答