양식이로드 된 후 코드를 어떻게 실행합니까?


126

.NET에서 Windows Forms에는 Form이로드되기 전에 발생하는 이벤트 (Form.Load)가 있지만 폼이로드 된 후에 발생하는 해당 이벤트는 없습니다. 양식이로드 된 후 몇 가지 논리를 실행하고 싶습니다.

누구든지 해결책에 대해 조언 할 수 있습니까?


이 질문에 매우 좋은 답변이 있지만 다음과 같이 언급 할 가치가 있습니다. docs.microsoft.com/en-us/dotnet/framework/winforms/…
Rishav

답변:


192

"Shown"이벤트를 사용할 수 있습니다. MSDN-Form.Shown

"Shown 이벤트는 양식이 처음 표시 될 때만 발생합니다. 이후에 최소화, 최대화, 복원, 숨기기, 표시 또는 무효화 및 다시 그리기는이 이벤트를 발생시키지 않습니다."


10
나에게 양식이로드되는 동안 표시된 처리기가 실행되는 것처럼 보입니다 ... 내가 틀렸습니까?
ckonig

3
오래되었지만 금은 ... 네, 틀 렸습니다. GUI는 병렬 작업을 실행할 수 없으며 다른 실행이 수행되는 동안 중요한 작업을 수행합니다.
Dennis Ziolkowski 2011

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 2016-08-11

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 스레드 (언젠가는)는 메시지를 대기열에서 빼고 델리게이트를 처리하고 작업자에게 완료되었음을 알립니다.

확인; 그래서 UI 스레드에서 Control.Invoke / Control.BeginInvoke를 사용하면 어떻게 될까요? 대처할 수 있습니다 ... Control.Invoke를 호출하면 메시지 큐를 차단하면 즉시 교착 상태가 발생한다는 것을 알 수 있습니다. 따라서 이미 UI 스레드에있는 경우 코드를 즉시 실행하기 만하면됩니다. 우리를 돕지 않는다 ...

그러나 Control.BeginInvoke는 다르게 작동 합니다. 우리가 이미 UI 스레드에 있더라도 항상 작업을 대기열에 푸시합니다. 이것은 "순간에"라고 말하는 아주 간단한 방법이지만, 타이머 등의 불편 함은 없습니다 (어쨌든 같은 일을해야합니다!).


1
그것을 완전히 이해하지 못했습니다. 좀 더 설명해 주시겠습니까?
Torbjørn

안녕 마크, BeginInvoke에서 호출되는 프로세스가 완료되는 동안 응답 양식을 만들 수 있습니까?
huMpty duMpty

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

나는 같은 문제가 있었고 다음과 같이 해결했습니다.

사실 메시지를 보여주고 2 초 후에 자동으로 닫고 싶습니다. 이를 위해 (동적으로) 간단한 양식과 메시지를 표시하는 하나의 레이블을 생성해야했으며 사용자가 읽을 수 있도록 1500ms 동안 메시지를 중지해야했습니다. 그리고 동적으로 생성 된 양식을 닫습니다. 표시된 이벤트는로드 이벤트 후 발생합니다. 그래서 코드는

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을 먼저 확인한 다음 필요에 따라 사용하는 것이 가장 좋습니다. 그것만으로도 많은 슬픔을 구할 수 있습니다.

이러한 유형의 질문에 대한 가장 일반적인 이유는 컨테이너 또는 사용자 지정 컨트롤 형식이 해당 속성이 아직 초기화되지 않은 사용자 지정 클래스 외부에서 초기화 된 속성에 액세스하려고 시도 할 때 잠재적으로 null 값이 채워지고 null 참조 예외가 발생할 수도 있습니다. 개체 유형에. 이는 클래스가 완전히 초기화되기 전에 실행되고 있음을 의미합니다.-속성 설정을 마치기 전에. 이러한 유형의 질문에 대한 또 다른 가능한 이유는 사용자 정의 그래픽을 수행 할시기입니다.

폼로드 이벤트 이후에 코드 실행을 시작하는시기에 대한 질문에 가장 잘 대답하려면 WM_Paint 메시지를 모니터링하거나 페인트 이벤트 자체에 직접 연결해야합니다. 왜? paint 이벤트는 양식로드 이벤트와 관련하여 모든 모듈이 완전히로드 된 경우에만 발생합니다. 참고 : This.visible == true는 true로 설정된 경우 항상 true가 아니므로 양식을 숨기는 경우를 제외하고는이 용도로 전혀 사용되지 않습니다.

다음은 양식로드 이벤트 이후에 코드 실행을 시작하는 방법의 완전한 예입니다. 페인트 메시지 루프를 불필요하게 묶지 않는 것이 좋습니다. 그러면 해당 루프 외부에서 코드 실행을 시작하는 이벤트를 만들 것입니다.

using System.Windows.Forms;

namespace 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 이벤트를 잡는 것보다 이점이 있습니까?
Steve Smith

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();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.