Close form on deactivate breaks click event - c#

I have a windows form in c# which should close when the user clicks anywhere outside of its bounds, eg:
form1.Deactivate += (o, e) => form1.Close();
My problem is, I would also like to catch the click event that caused the form to deactivate, but using the above code my mouse event handlers on the other forms in my application are never called.
For example, I have a click handler on a second visible form in my application:
form2.MouseClick += OnForm2Click
Normally OnForm2Click would get called fine if the user clicks on form2 when form1 is active, but with close-on-deactivate code above, OnForm2Click never gets called (this is a bit strange to me because double-click handlers are called just fine).
I cannot call form1.Close() from within OnForm2Click() as a solution because form2 has no reference to form1.
Thank you in advance for your solution.

You may solve your problem with a mouse hook. See:
Hooks Overview (Windows)

Related

Is there any case in which the Form's Activated event is not raised?

I don't understand why it could be that, I thought Activated should be raised when the form is shown. In fact my form has TopLevel set to false and it's added to another form. When the main form shows, it's also visible, and I can interact with its controls but I tested and saw that the Activated is not raised.
public MainForm(){
InitializeComponent();
Form child = new Form();
child.Activated += (s,e) => {
MessageBox.Show("Activated!");
};
child.Size = new Size(200,100);
child.TopLevel = false;
child.Show();
child.Parent = this;
}
After running the MainForm the child form is appeared inside the main one and there isn't any MessageBox displayed with the message "Activated!".
What is the additional job to do to make it raise?
If the second form comes to screen for the first time, you can use Shown event.
Activate event is only fired when a form gets focus, but that does not contain showing for the first time. But, if the previous form which is active is outside of your app, it will not raise activate event. I mean it is valid when only viewing forms of same project.
Here is my answer, I noticed that only Form has Activated event, other controls don't have and once the TopLevel of Form is set to false, I think it's treated as a normal control and in that case, Activate() method will do nothing and Activated event won't be raised in any case. I think this is the reason why Activated is not raised.
Thank Kuzgun for a suggestion of using Shown instead, but this is focused on explaining why the Activated is not raised!
This answer is just my guess, even the MSDN page about Form.Activated event doesn't mention this. It should not be missed that way especially in an official documentation page.
Once the TopLevel property of Form is set to false then the form becomes a normal control, hence Activated() event will not fire.

First key press lost when Windows Shell is replaced with Windows Forms application

I have succesfully replaced the Windows Shell following the approach given in this SO question.
However, I have detected that the first key press is lost and is a bit of an annoyance for the user. The solution we have tried is to activate the form in the OnShown event:
private void OnShownLoginForm(object z_sender, EventArgs z_e)
{
Activate();
m_loginTextBox.Focus();
}
But this hasn't solved the problem. Do you have any clue of what is happening?
You could try using the System.Windows.Forms.SendKeys Class (MSDN Documentation) to send a key press event to the form when in the Form Load event. If that doesn't help, try sending the keyboard events in the Form.Shown event since Form.Shown is the last event in the form start-up process.
Sounds like something caused by maybe another control getting focus first. Does the textbox have a taborder, and can you set it to 0? Focus should then be on it after the form loads.
Otherwise try creating a new form to test with, it really doesn't seem reproducible.
I do not know if it is related but I had a similar problem where the tabindex property of a webform did not work by pressing the TAB key, after focusing on the first input at page load, until the user first clicked on the form with the mouse.
I did not have access to the source code so I tried solving it with javascript.
Until the first mouse click, all keyboard strokes, including the TAB key, activated the keypress event, TAB key was undetected by keydown/keyup on page load.
I learned that the TAB key activated the keypress event and I could access the keycode through it. simply registering the keypress event and manually switching to the next input with jQuery worked.
after the first mouse click the form behaved as expected, TAB key was no longer caught by keypress event.
here is a code sample:
function tabNext(e){
if(e.keyCode == 9){
// do work
}
}
$('input').keypress(tabNext);

Order of events 'Form.Load', 'Form.Shown' and 'Form.Activated' in Windows Forms

What is the difference between form Form.Load, Form.Shown and Form.Activated events? What is the order in which they are fired?
See the Windows Forms Events Lifecycle:
Move: This event occurs when the form is moved. Although by default, when a form is instantiated and launched, the user does not move it, yet this event is triggered before the Load event occurs.
Load: This event occurs before a form is displayed for the first time.
VisibleChanged: This event occurs when the Visible property value changes.
Activated: This event occurs when the form is activated in code or by the user.
Shown: This event occurs whenever the form is first displayed.
Paint: This event occurs when the control is redrawn.
Deactivate: This event occurs when the form loses focus and is not the active form.
Closing: This event occurs when the form is closing.
Closed: This event occurs when the form is being closed.
The Load event fires when the form has been initialized, after its handle has been created but before it is shown.
The Shown event fires after the first time the form becomes visible, when you call form.Show() (or form.Visible = true).
If you hide your form, then show it again, Shown will fire again. (But Load won't)
The Activate event fires when the user switches to your form.
If the user switches to a different program (or form), then switches back to your form, Activate will fire again.
Moreover, Form.Activate event can be fired multiple times. For example, if you open a message box from your form, and when you click on the messagebox's any button, and return back to the form, Form.Activate is fired. The same is true for any other dialog box such as FileOpenDialog.
The Form and Control classes expose a set of events related to application startup and shutdown. When a Windows Forms application starts, the startup events of the main form are raised in the following order:
Control.HandleCreated
Control.BindingContextChanged
Form.Load
Control.VisibleChanged
Form.Activated
Form.Shown
When an application closes, the shutdown events of the main form are raised in the following order:
Form.Closing
Form.FormClosing
Form.Closed
Form.FormClosed
Form.Deactivate
Focus and Validation Events
When you change the focus by using the keyboard (TAB, SHIFT+TAB, and so on), by calling the Select or SelectNextControl methods, or by setting the ActiveControl property to the current form, focus events of the Control class occur in the following order:
Enter
GotFocus
Leave
Validating
Validated
LostFocus
When you change the focus by using the mouse or by calling the Focus method, focus events of the Control class occur in the following order:
Enter
GotFocus
LostFocus
Leave
Validating
Validated
The order would be Form.Load, which initializes the form and calls the controls, Form.Shown, which marks the frame as visible (even in C++, this is done after the form is created), and Form.Activated, which gives the forum focus.

How to dispose of variables in windows close button

I have a windows forms application, where I have declared some static variables.
On the click of exit button, I have disposed of some datatable which i have declared static.
Many a times the user instead of clicking the exit button, will just exit the windows application by clicking the X button on the left corner top.
What should be done to ensure that even if the user clicks the X button, everything is disposed of properly.
Thanks
Regards
Hema
This question has some good descriptions of events that you can hook into to detect when a application is exiting.
Does Application.ApplicationExit event work to be notified of exit in non-Winforms apps?
Just add a delegate function to the Closing event of the form.
this.Closing += this.MyForm_Closing;
You can also use the Closed event of the form if you'd prefer it gets called after the form is closed.
You can add an event handler to dispose your variables when the form is closing.
private: System::Void myDialog_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e) {
// Dispose your static variables here
}

How to do two things with one click in Windows Form

On my main form, there is another (floatable) window. This floatable window works sort of like a popupwindow in that it will close when the user clicks somewhere else outside of this window. This is handled by the Deactivate event. But what I want to do is, if the user clicks on a different control (say a button), I want to both close this float window and then activate that button with just one click. Currently, the user has to click twice (one to deactivate the window and once more to activate the desired button). Is there a way to do this with just one click?
foreach(Control c in parentForm.Controls)
{
c.Click += delegate(object sender, EventArgs e)
{
if(floatyWindow != null && floatyWindow.IsFloating)
{
floatyWindow.Close();
}
};
}
And then add your handlers as normal. This additional handler can close the floaty window.
Make sure you floaty window isn't a dialog too as this will not allow your parent form's controls to be clicked.
I had a slightly hacky solution. In your Deactivate event, fire another custom event to your main form. Then when you main form is handling the custom event, enumerate through your control(this.Controls) and locate the control under the mouse by checking all their bound then call Focus(). You might need to sort by the one with the smallest surface area, or you can have a separate list of "focus-able" control like button just for this purpose.
Another way might be to switch focus to your main form immediately after OnMouseLeave of the floatable window, or OnMouseHover of your main window, but keep the floatable windows on top, just no focus. Handle the global mouse down of your main form, and close the floatable window by then.
These are just theories, not tested.
I had an issue like this once too, when a customer wanted "floaty" windows all over there application. I used used an approach similar to the one described in this article:
http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp
Code sample available here:
http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/Popup_Form_Demonstration.asp
By extending this a bit we created "floaty" windows similar to the ones VS uses when you get a runtime error while debugging code.
At the very least reading the code may give you some insight, however, quarrelsome's response may be the more simple solution.

Categories