///<summary></summary> public static void Open(Claim claim, Action actionOkClick = null) { //Show a dialog if the user tries to open more than one claim at a time if (_threadFormClaimAttach != null) { MsgBox.Show("A claim attachment window is already open."); return; } _threadFormClaimAttach = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { FormClaimAttachment formCA = new FormClaimAttachment(claim); if (formCA.ShowDialog() == DialogResult.OK) { actionOkClick?.Invoke(); } })); //This thread needs to be STA because FormClaimAttachment will have the ability to open child forms, //which will need to block FormClaimAttachment while it is open. //STA mode is the only way to have ShowDialog() behavior in a non-main thread, //without throwing an exception (the exception literally says change the thread to STA) _threadFormClaimAttach.SetApartmentState(System.Threading.ApartmentState.STA); _threadFormClaimAttach.AddExitHandler(new ODThread.WorkerDelegate((ODThread o) => { _threadFormClaimAttach = null; })); _threadFormClaimAttach.Start(true); }
///<summary>Launches a splash screen with a progressbar that will listen specifically for ODEvents with the passed in name. ///Returns an ODProgressWindow that has a Close method that should be invoked whenever the progress window should close. ///eventName should be set to the name of the ODEvents that this specific progress window should be processing.</summary> ///<param name="currentForm">The form to activate once the progress is done. If you cannot possibly pass in a form, it is okay to pass in null. ///</param> public static ODProgressWindow ShowProgressSplash(string eventName, Form currentForm) { //Create a splash form with a progress bar on a separate thread to avoid UI lockups bool isFormClosed = false; FormSplash FormS = new FormSplash(eventName); FormS.FormClosed += new FormClosedEventHandler((obj, e) => { isFormClosed = true; }); ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //From this point forward, the only way to kill FormSplash is with a DEFCON 1 message via an ODEvent with the corresponding eventName. FormS.ShowDialog(); })); odThread.SetApartmentState(ApartmentState.STA); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing. odThread.Name = "ProgressSplashThread_" + eventName; odThread.Start(true); return(new ODProgressWindow(new Action(() => { //For progress threads, there is a race condition where the DEFCON 1 event will not get processed. //This is due to the fact that it took the thread longer to instantiate FormProgressStatus than it took the calling method to invoke this action. //Since we don't have access to FormProgressStatus within the thread from here, we simply flag odThread's Tag so that it knows to die. if (odThread != null) { odThread.Tag = true; } //Send the phrase that closes the window in case it is processing events. SplashProgressEvent.Fire(new ODEventArgs(eventName, "DEFCON 1")); if (currentForm != null) { //When the form closed on the other thread it was sometimes causing the application to go behind other applications. Calling Activate() //brings the application back to the front or causes it to flash in the taskbar. DateTime start = DateTime.Now; while (!isFormClosed && (DateTime.Now - start).TotalSeconds < 1) //Wait till the form is closed or for one second { Thread.Sleep(1); } if (!currentForm.IsDisposed) { currentForm.Activate(); } } }))); }
///<summary>FormProgressExtended is extremely tailored to monitoring the progress of FormBilling. ///Much will need to change about this to make it generic. ///Launches a progress window that will listen specifically for ODEvents with the passed in name. ///Returns an action that should be invoked whenever the long computations have finished which will close the progress window. ///eventName should be set to the name of the ODEvents that this specific progress window should be processing. ///eventType must be a Type that contains an event called "Fired" and a method called "Fire". ///Optionally set tag to an object that should be sent as the first "event arg" to the new progress window. /// This will typically be a ProgressBarHelper.</summary> ///<param name="currentForm">The form to activate once the progress is done. If you cannot possibly pass in a form, it is okay to pass in null. ///</param> public static Action ShowProgressExtended(string eventName, Type eventType, Form currentForm, object tag = null, ProgressCanceledHandler progCanceled = null, ProgressPausedHandler progPaused = null, EventHandler formShown = null) { bool isFormClosed = false; ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { FormProgressExtended FormPE = new FormProgressExtended(eventName, eventType); FormPE.FormClosed += new FormClosedEventHandler((obj, e) => { isFormClosed = true; }); if (progCanceled != null) { FormPE.ProgressCanceled += progCanceled; } if (progPaused != null) { FormPE.ProgressPaused += progPaused; } if (formShown != null) { FormPE.Shown += formShown; } //FormProgressExtended should NOT be the top most form. Other windows might be popping up requiring attention from the user. //FormPE.TopMost=true;//Make this window show on top of ALL other windows. if (tag != null) { FormPE.ODEvent_Fired(new ODEventArgs(eventName, tag)); } //Check to make sure that the calling method hasn't already finished its long computations. //odThread's tag will be set to "true" if all computations have already finished and thus we do not need to show any progress window. if (o.Tag != null && o.Tag.GetType() == typeof(bool) && (bool)o.Tag) { try { FormPE.Close(); //Causes FormProgressStatus_FormClosing to get called which deregisters the ODEvent handler it currently has. } catch (Exception ex) { ex.DoNothing(); } return; } FormPE.BringToFront(); //From this point forward, the only way to kill FormProgressStatus is with a DEFCON 1 message via an ODEvent with the corresponding eventName. FormPE.ShowDialog(); })); odThread.SetApartmentState(ApartmentState.STA); //This is required for ReportComplex due to the history UI elements. odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing. odThread.Name = "ProgressStatusThread_" + eventName; odThread.Start(true); return(new Action(() => { //For progress threads, there is a race condition where the DEFCON 1 event will not get processed. //This is due to the fact that it took the thread longer to instantiate FormProgressStatus than it took the calling method to invoke this action. //Since we don't have access to FormProgressStatus within the thread from here, we simply flag odThread's Tag so that it knows to die. if (odThread != null) { odThread.Tag = true; } //Send the phrase that closes the window in case it is processing events. eventType.GetMethod("Fire").Invoke(eventType, new object[] { new ODEventArgs(eventName, "DEFCON 1") }); if (currentForm != null) { //When the form closed on the other thread it was sometimes causing the application to go behind other applications. Calling Activate() //brings the application back to the front or causes it to flash in the taskbar. DateTime start = DateTime.Now; while (!isFormClosed && (DateTime.Now - start).TotalSeconds < 1) //Wait till the form is closed or for one second { Thread.Sleep(1); } if (!currentForm.IsDisposed) { currentForm.Activate(); } } })); }