How to debug why a form can not obtain focus? - c#

Using Visual Studio 2019, with an old C# Winforms .NET 4.6.2 application: I have a situation where my main form is acting as if it is being blocked by a modal:
Makes a beeping sound and flashes when clicking anywhere
Will not accept focus
Timer and serial communication Events are still triggering
No grey screen overlay, or message about the application ever becoming unresponsive
However, I can see no modal form, and using Application.OpenForms doesn't show any of the modals that I have created and have closed a few seconds previously.
I can successfully attach and debug remotely, that is how I know the timer ticks are still firing.
How / Where can I place a breakpoint to troubleshoot why a form will not receive focus / denies click events / thinks it is being blocked by a modal of some kind?
It is too difficult to create a minimal example because the backgroundWorker and showDialog code all seems to work properly in other locations, but the gist of what is happening looks like:
Application.Run (new FormA)
...
FormA.showDialog(new FormB)
...
FormB.showDialog(new FormC)
...
FormC.timer_tick() { ...still running... }
FormC.onReceive_data() { ...still running... }
FormC.button_click(){
...
showDialog()
...
showDialog()
...
important.showDialog() { backgroundWorker...database stuff }
...
showDialog()
...
}
(known completion : back to FormC event-loop)
It always gets to "known completion" just fine, important.showDialog() seems to work fine, pops up an animating dialog with no buttons, auto closes when backgroundWorker completes, closes itself and moves on to the next dialogs or exits button click fine.
But once back in FormC-Event-loop, the form will not receive any input, as if it is still blocked by some modal somewhere...
If I change to important.show() FormC will not have a problem, but now there is code in the click event running before database activity is finished...
I am more interested in debugging technique in this case as to how I can figure out what windows is doing as I try to click on FormC. What kind of debugging module symbols need to be loaded? Where can I breakpoint to see windows deciding whether a form can receive focus/input?

"something has gone wonky with the re-enabling mechanism" made me go through with a fine tooth comb and check how the dialog is being closed off, and I found the original problem:
FormC starts a backgroundWorker and then waits on important.showDialog()
Inside the RunWorkerCompleted() or a timer_tick : "important" was FormC.BeginInvoke() .closed() and .disposed() . But apparently the .dispose() can (but not always) happen on the wrong thread or at the wrong time and then the parent form can never be enabled again. .close() and nulling the formDialog reference allows the parent to get re-Enabled.
Out of interest, I am still wondering how you would go about debugging such a situation?

Related

c# Label is "empty"/is a hole in the form

I have 2 windows. The main form and the Loading form. In the main form you send a request which will be executed. Because this takes some time, I made the Loading-form with a progress bar so that the user knows the program is working.
What I want to: The Loading-form should open itself when the process ist started and close itself when it's finished.
At the moment I have code that looks something like this:
Loading.Show();
Loading.MakeAStep(); //used for progressing the progress bar
//program is working
//finishes
Loading.Visible = false;
Loading.ResetProgress(); //Sets the value of the progress bar to 0
My problem is: The window with the progress bar opens, but there is also a label which shows "please wait". When the form opens, the progress bar works perfectly, but the label is just a hole (it really is you can look through it). When I use instead of visible = false form.Close, it works just fine with the label but I get an error when I try to start a progress in the same session.
What I want/need: Either a solution to the hole-problem, or an effective way to open and close a form several times during one session.
(Posted the solution on behalf of the question author).
The answer is in the comments: The UI blocks and I needed to Update the form with Loading.Update(); I put that between Show and MakeAStep.
As already mentioned by others, the problem is that you run your long running process in the UI thread. To avoid this, you should improve how the loading form receives the task and works on it:
The loading form should get the thing to run as a Task (maybe by a method Run(Task task). After getting this task the loading form can attach another action to it, what shall happen when the task is finished by using .ContinueWith() and simply closes itself when it reaches that point. After that it will Start() the task and call ShowDialog() on itself.

WaitDialogForm.ShowDialog() not processing other code

Pretty new to DevExpress, my company is stuck using 9.3
I've got this very small snippet of code:
wait = new DevExpress.Utils.WaitDialogForm("Please wait...", "Performing SVN check");
wait.Visible = false;
wait.ShowDialog();
ParseSVNResults(CheckSVN());
wait.Close();
My WaitDialog displays, but the code never continues. I put a breakpoint on ParseSVNResults and when I run the code it gets to that line.
It works properly if I just call Show() instead of ShowDialog(), but that gives poor behavior should the user click outside of the Wait form. The application "whites out" like it's stopped responding and the mouse changes into that little rotating circle icon. Also the hour glass that the dialog form shows doesn't rotate. Stupid minor detail, but it looks like the whole application crashed to end users.
ShowDialog, by design, "blocks" the code until you close the dialog. That is the entire purpose.
The reason that Show() is causing everything to white out is that your work is happening in the UI thread. The proper way to handle this would be to move your work (ParseSVNResults) into a background thread, via something like BackgroundWorker or a Task.

Visual C# Window Behaver

I have a form which instances a new form that I've already created using
statuswindow statwin = new statuswindow();
statwin.ShowDialog();
return statwin;
This code is in a function. The problem is when I run the function in other code the next line of code doesn't run until the newly instanced window is closed by the user, I'm guessing this is the side-effect of using ShowDialog(), is there a way to have it use the same behaver (being topmost, not being to select the other main window) while still letting the main form's code run?
Update: Although Show(); will work, I need to be able to make the window like a dialog by having it always on top of the other window and it always being the active selected window.
The ShowDialog method of showing a window shows it as a dialog, which is a blocking mechanism within C#/.net. If you want to simply display the window and not cause the running code to block until it is closed, you can use the window.Show() function.
In your code:
startwin.Show();
This will cause the startwin form to become visable to the user, and will fire the startwin.VisibleChanged event as well as the startwin.Load event to fire.
To make the new window always on top, you could set the Topmost window flag in the form properties.
To make the window run in a separate thread, first spawn the thread, then create the window from that thread.
There are also "application modal" and "system modal" Win32 window flags, but I don't know if those are exposed to WinForms or not -- go have a look on the form properties!

MessageBox doesn't show on mdi form after a long calculation

This is a very similar problem to This one, sadly that one was never answered either.
I have a MDI Main forum that hosts several children forms. One of them does a long calculation and throws an exception if an error occurs (all work is done on the same thread). I then try to inform the user of an error with an messagebox, however it doesn't appear (but steals focus from the MDI Main, so the application is completely unresponsive).
The beheviour changes slightly if I call Application.DoEvents() (evil I know, but this is a last resort thing). Then the forms remain completely active and the messagebox only appears after I change active application (Alt+Tab) to something else and then back again.
What can I do to make sure the messagebox will be visible? I have already tried passing both, active child and MDI Main as parameter to the MessageBox.Show method. It doesn't change the behaviour.
To clarify: the messagebox is a part of the child form, however at this point I am willing to show it in any way that doesn't break the application. The messagebox should be modal, but it should be visible so it can be acknowledged by the user.
I had the same issue. When pressed ALT the popup showed.
It turned out to be a LinkedLabel that had the AutoSize property to true. The LinkedLabel was inside a FlowLayoutPanel. When I set the LinkedLabel.Text property to String.Empty. The LinkedLabel constantly tried to resize, which was causing the GUI to be constantly busy.
When I turned off the AutoSize property and the GUI no longer had to recalculate the positions. The GUI was no free. And the popup showed.
There could be other controls that are behaving the same.
See also:
https://connect.microsoft.com/VisualStudio/feedback/details/116884
Is the MessageBox shown in the MainForm or as part of the ChildForms? If the MessageBox is in the child Forms maybe you could pass an event back to the MainForm and open the MessageBox there.
The problem is that messageboxes tend to be modal.
In this instance I think that you'd do far better to use a delegate or an event with a handler in your main MDI code. That way your main application displays the message boxes. You can easily redefined an EventArgsType if you wish to pass whatever information that you require.

Window is not maxinizing/being brought to front after being in tray, why?/help

I wrote an alarm app with some complex code i dont feel like breaking up right now to use as an example. I have a timer checking every 10 or so minutes about a state online and on certain conditions my app alerts me. On form_load i set the timer to 10mins and when it triggers and the condition is true i call a function with this in it.
{
this.WindowState = FormWindowState.Maximized;
this.TopMost = true;
this.Activate();
}
When i start the app i typically minimize it and do whatever. Today i notice it isnt working. On my initial test i call the code after pulling the states and calling the func on form_load which always brought it up but now that i am doing other things and the window has been minimized i notice it did not work. How do i fix this?
Are you hiding the form? In which case try this.Show() instead.
Additionally, form_load runs once (usually). You want form_activated. The form is in memory (loaded) whether or not it's minimized.
And, including a call to the activate event in your form_load event is redundant.

Categories

Resources