I have two forms, mainForm and subForm. When mainForm loses focus I want subForm to disappear and then reappear as mainForm regains focus. I'm using the Activated and Deactivate events on the mainForm to keep track of whether mainForm has focus or not. When the Activated is fired I do subForm.Show() and the opposite for Deactivate. The problem I have is that when subForm gains focus mainForm disappear because I don't know how to say programmatically "make subForm disappear when the mainForm's Deactivate event fires except if it's because the subForm gained focus. The whole point of what I'm doing is to make both windows disappear when the mainForm loses focus because the user clicked on another application or use ALT+TAB to switch. I don't want to leave the subForm behind. Is there any way of checking as the Deactive fires whether it was because another form belonging to the application gained focus as opposed to some other application?
class MainForm : Form
{
SubForm subForm = new SubForm();
private void mainForm_Activated(object sender, EventArgs e)
{
this.subForm.Show();
}
private void mainForm_Deactivate(object sender, EventArgs e)
{
this.subForm.Hide()
// I need some logic to make sure that it is only hidden
// when the mainForm loses focus because the user clicked
// some other application in the taskbar and not when the
// subForm itself gains the focus.
}
}
This works on my machine.
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private Form2 _form2;
private void Form1_Load(object sender, EventArgs e) {
_form2 = new Form2();
_form2.Show();
HandleFocusEvents();
}
private void HandleFocusEvents() {
this.LostFocus += Form_LostFocus;
_form2.LostFocus += Form_LostFocus;
this.GotFocus += Form_GotFocus;
}
private void Form_LostFocus(object sender, EventArgs e) {
if (!_form2.ContainsFocus && !this.ContainsFocus) {
_form2.Hide();
}
}
private void Form_GotFocus(object sender, EventArgs e) {
if (!_form2.Visible) {
_form2.Show();
}
}
}
In your main forms code, where you create an new instance of the sub form, add an event that is fired whenever the instance of the sub form form is activated. In the event handler for it set a bool variable to true. Now, do the same, for the deactivate event of the sub forms instance, except set the bool variable to false.
Now in the event for the main form loosing focus, before hiding it check that bool variable and make sure it is false "the sub form doesn't have focus" and only then would you hide the main form.
I could provide code if I could see what you have so far. There are a lot of different ways you could to this.
Hope this helps you!
If I understand it correctly, this sounds like just a normal MDI application. Can you make your main form the MDI Parent and set the sub form MDI parent to the main form? Most of these activation stuff that you are talking about should then be look after automatically? Or at most just trap the minimize event in the subform to then also minimize mdi parent form
Related
I am having a bit of a head scratch moment at the moment.
I have 2 Forms one being a Parent form and other being the child form.
Inside the Parent form am trying to detect the FormClosed event which I have subscribed to a event inside the Parent form to handle some behaviour.
However the FormClosed event never gets subscribed or triggered when I close the child Form? I am not really sure what am doing wrong? I have even tried FormClosing and nothing gets triggered?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (var frm2 = new Form2())
{
frm2.ShowDialog();
frm2.FormClosed += Frm2OnFormClosed;
}
}
private void Frm2OnFormClosed(object sender, FormClosedEventArgs e)
{
// Implement further behaviour handling.
}
}
ShowDialog() will block execution of code in the calling method until the new form is closed. So you are opening and closing frm2 before you've ever even assigned the EventHandler. Switch your two lines around like so and you should be good to go:
frm2.FormClosed += Frm2OnFormClosed;
frm2.ShowDialog();
I have a button and hidden textbox on my main form. When I press the button it will hide the main form and show the second form. When I press the button on the second form I want to show the main form again but this time I need to show the hidden textbox. I know how to pass the text from a textbox to another form but not just the reference of the textbox.
You better pass the complete main form instance for the second form, and create a public function to set the textbox to visible, or create a property around it.
Something like:
//form1
Form2 second = new Form2(this);
}....
public void ShowTextBox()
{
textbox1.Visible=true;
}
//form2
Form parent;
public Form2(Form _parent)
{
parent=_parent;
}
///later
parent.Show();
parent.ShowTextBox();
Sounds to me like a custom event would be a better approach. Have the secondary form expose an event, which is raised at whatever appropriate time (your button press). In your main form, when you create your instance of your second form, subscribe to that event. Then run your "unhide" code from within the mainform's event subscription.
This keeps the coupling down on the two forms and results in much more easily maintainable and extensible code (for best effect, use interfaces, but events are a good middle ground for learning).
Something like this:
(it's been a long time since I worked with winforms, or events even, so if this needs refining let me know)
// your secondary/popup form's class
public partial class Form2 : Form
{
// add a custom event
public EventHandler<EventArgs> MyCustomEvent;
// link up your button click event
void InitializeComponent() {
myButton.Click += myButtonClick;
}
// when your button is clicked, raise your custom event
void myButtonClick(object sender, EventArgs, e) {
onMyCustomEvent();
}
// this "broadcasts" the event
void onMyCustomEvent() {
EventHandler<EventArgs> h = MyCustomEvent;
if (h != null) {
h(this, new EventArgs());
}
}
}
// your main form's class
public partial class MainForm
{
void InitializeComponent() {
// ...
}
void showForm2() {
var form2 = new Form2();
form2.MyCustomEvent += form2CustomEvent;
form2.Show();
}
void form2CustomEvent(object sender, EventArgs e) {
myHiddenTextBox.Visible = true;
}
}
All in all this is a much better approach in terms of code architecture. Now the popup doesn't care who opens it (it has no reference to the main form), and the custom event (which is really what you're after) can be managed to any level of control you need, without interfering how other thing work (for example, perhaps later you may want to have a different action that fires this same custom event...)
Food for thought.
When I click on About, a new form opens and the main form hides. I have a close button on the About button, that closes the About form, and it shows up the Main form. However, when I close the main form with the 'X' close button on top, the Main form closes, but the process is still running in the background. Everything is okay when I dont click on the About button. It kills the process.
In your Form2, you need to bring up the existing Form1 instance rather than creating a new one (that's why closing this newly created Form1 won't exit the application, as your old Form1 instance is still hiding...).
So you could get reference passed when creating aboutdialog, and show that instead when closing aboutdialog:
Form1:
private void AboutButton_Click(object sender, EventArgs e)
{
var aboutdialog = new Form2(this);
aboutdialog.Show();
this.Hide();
}
Form2:
Form1 _parentform;
public Form2(Form1 parent)
{
_parentform=parent;
InitializeComponent();
}
private void CloseButton_Click(object sender, EventArgs e)
{
_parentform.Show();
this.Close();
}
In your "AboutButton_Click" method you hide the Form1. But when closing the About dialog, you do not show back the Form1, but create a new one. The original Form1 stays hidden and prevents your application from closing.
better to use showdialog.
private void AboutButton_Click(object sender, EventArgs e)
{
var aboutdialog = new Form2();
aboutdialog.ShowDialog();
}
When form2 is closed a new instance of form1 is opened, instead of the original one. You could include a reference to Form1 inside of Form2, or use the default Ownerof a form, by showing the dialog with Form1 as its owner:
aboutdialog.Show(this);
in the about...click
and closing
private void CloseButton_Click(object sender, EventArgs e)
{
Owner.Show();
this.Close();
}
I have a MDI form. Within this MDI there is multiple button to open new forms. Let buttons are btn1, btn2, btn3, btn4.... When I press btn1, form1 is load. when I press btn2, form2 is load... Now I press btn1, And form1 is loaded. If I press again btn1 then another form1 is open. Simultaneously let form1 is open, if I press btn2 form2 is open. But I want to open a form at a time. How I prevent this?
all the answers you got are good so i'm not going to repeat them, just give you an example of the member and method you can use to prevent that from happening:
private Form frm;
private void button1_Clicked(object sender, EventArgs e)
{
if (frm != null)
{
frm.Close();
frm.Dispose();
}
frm = new Form1();
frm.Show();
}
private void button2_Clicked(object sender, EventArgs e)
{
if (frm != null)
{
frm.Close();
frm.Dispose();
}
frm = new Form2();
frm.Show();
}
You can read up about mutual exclusion http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
It is a general solution to make sure you only have 1 thing (thread, process, form, whatever) of something at the same time. You can even use it inter application.
An example is shown here: http://www.dotnetperls.com/mutex
You can create multiple mutexes, one for each form. Or one for a set of forms, in what ever combination suits you.
Example Scenario:
Form1 creates a mutex with name X
Form2 is being loaded checks whether mutex X is created, if so it closes itself.
Of course you will need to make sure the mutex is Disposed / released when the creator (Form1 in this example) closes, to allow other forms to show.
You can use some flag for this purpose OK, like this:
bool formOpened;
private void buttons_Click(object sender, EventArgs e){
if(!formOpened){
//Show your form
//..............
formOpened = true;
}
}
//This is the FormClosed event handler used for all your child forms
private void formsClosed(object sender, FormClosedEventArgs e){
formOpened = false;
}
At least this is a simple solution which works.
In general case, you need a int variable to count the opened forms, like this:
int openedForms = 0;
//suppose we allow maximum 3 forms opened at a time.
private void buttons_Click(object sender, EventArgs e){
if(openedForms < 3){
//Show your form
//..............
openedForms++;
}
}
private void formsClosed(object sender, FormClosedEventArgs e){
openedForms--;
}
Does this mean while you have Form1 open, you want to still be able to open a Form2 and 3 and etc?
It you don't want that, you can use the form1Instance.SHowDialog() instead of Show()...
But that generally means you can't access the parent form while form1 is open...
But King King's anwser might be more useable to you.
I tried everything I know. The trouble must be that my textbox is in a groupbox. I have a Mainform from which I move to another form. When I return to Mainform, I want a particular object to be focused. How is this done?
Here's my code in my Mainform.
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
frm.ShowDialog();
}
now this is how i return back to my Mainform from Form1.
private void button3_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
}
I have textBox1 in Mainform. How to set focus to textBox1 when quitting Form1 and entering Mainform. I tried textBox1.Focus(); and this.ActiveControl = this.textBox1; under Mainform Load, Show, Activated and Enter events. Still didn't work. I tried creating a public method and call it under the exit button of Form1. Like this.
In Mainform,
public void textBox1Focus()
{
textBox1.Focus();
}
And then in Form1,
private void button3_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
Mainform frm = new Mainform();
frm.textBox1Focus();
}
Which still didn't work. My textBox1 is in a groupbox. Could that be the reason?
Thanks.
I don't understand how the code that you've shown even compiles. You're calling textBox1Focus() from inside a method that's defined in the Form1 class, which as best I can understand, doesn't include a definition for textBox1Focus. That method is only defined in the Mainform class.
And no, the text box being placed in a group box is not preventing it from getting the focus. There's something else wrong with your code. It's hard to tell; I feel like I'm looking at a sunset through Venetian blinds, rather than through a large picture window.
Anyway, I suspect there's a simpler solution. Just set the focus to the textbox control at the end of the button1_Click method. The ShowDialog method is a blocking call, which means execution won't continue until after the user closes the second form. When that happens, execution will continue with the next line of code, which will set the focus to the textbox control.
Try changing your code to the following:
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
frm.ShowDialog();
this.textBox1.Select();
}