I'm having two forms namely One and Two , and the title text of both are same as their names.
One is having a button and the click event of it contains,
Two l_objTwo = new Two();
l_objTwo.Show();
MessageBox.Show("Two Closed");
It opens the Two and after that the "Two Closed" message will be popped up.
My scenerio is, that Two should be opened in a Modeless way i.e i need the control of One and at the same time i need to execute some functionality after Two got closed. As of now I'm using like,
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
Two l_objTwo = new Two();
l_objTwo.Show();
IntPtr l_objHandle = FindWindow(null, "Two");
while ((int)l_objHandle > 0)
{
l_objHandle = FindWindow(null, "Two");
Application.DoEvents();
}
MessageBox.Show("Two Closed");
Its working fine, but is this the only way to achieve this?
No, it's not the only way.
Your first form will attach a handler to either FormClosed or FormClosing public events of the second form.
When your second form closes it will raise the event and the first form will know that your second form is closed.
Just use this snippet:
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.FormClosed += new FormClosedEventHandler(FormClosedHandler);
f.Show();
}
void FormClosedHandler(object sender, FormClosedEventArgs e)
{
MessageBox.Show("Second form has closed.");
}
Use an event handler
var two = new Two();
two.Closed += OnTwoClosed;
two.Show();
private void OnTwoClosed(object sender, EventArgs e)
{
MessageBox.Show("Two Closed")
}
Haven't tested this code on a winforms Form but the principal is the same, and easier than using the Windows API with all its inherent pitfalls.
Another benefit is, the titles of the windows can be whatever you like.
After checking here it appears both Closed and FormClosed are valid events.
This looks all around messy. Not sure what you want to achieve here. Just open form two in One's event handler and hook two's onclose-event to your MessageBox.
Related
Hey there StackOverflow community!
So I've been working on an application that checks if the user has entered valid credentials in a Login() form, then it switches over to an Intro_Sequence() form (where a .mp4 file is played in fullscreen mode) as a sort of aesthetic addition to the app. So far so good, no problems whatsoever.
The problem comes right after the Intro ends, where supposedly the application should switch over to a third form, called Main().
I have implemented a check whenever Windows Media Player (aka axWMPLib) changes its PlayState to see whether it has finished the playback.
If it has, then the Hide() event is called to conceal the current Form's window, then main.ShowDialog() should open the third form.
Afterwards, I call the Close() event to close the previous Form's window entirely.
Here is the code so far:
public partial class Intro_Sequence : Form
{
public static string Username;
public Intro_Sequence(string username)
{
InitializeComponent();
Username = username;
FormBorderStyle = FormBorderStyle.None;
Bounds = Screen.PrimaryScreen.Bounds;
TopMost = true;
intro.uiMode = "none";
intro.URL = AppDomain.CurrentDomain.BaseDirectory + "\\Intro.mp4";
intro.enableContextMenu = false;
DisableMouseClicks();
}
private void DisableMouseClicks()
{
if (this.Filter == null)
{
this.Filter = new MouseClickMessageFilter();
Application.AddMessageFilter(this.Filter);
}
}
private MouseClickMessageFilter Filter;
private const int LButtonDown = 0x201;
private const int LButtonUp = 0x202;
private const int LButtonDoubleClick = 0x203;
public class MouseClickMessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case LButtonDown:
case LButtonUp:
case LButtonDoubleClick:
return true;
}
return false;
}
}
private void Intro_Sequence_Load(object sender, EventArgs e)
{
}
private void intro_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if(intro.playState == WMPLib.WMPPlayState.wmppsMediaEnded)
{
Main main = new Main(Username);
this.Hide();
main.ShowDialog();
this.Close();
}
}
}
As you can see I have also added a filter to block clicks during playback, so as not to allow the user to pause it.
However, when I execute this code, it works perfectly fine until it finishes the video and then closes abruptly.
I tried putting breakpoints and everything seems to be fine.
It does call everything I tell it to call, yet the form doesn't even appear.
I have also tried several other alternatives, like not closing the Form at all, calling Show() instead of ShowDialog() and even not Hiding it at all.
It is as if it either freezes there or closes instantly without any sign of the Main form showing.
I also tried calling the Main() form from the Login() and it works perfectly from there.
I really don't know what is going on.
Any help would be appreciated.
How about something like this?
There are three forms. There's a Login form (in this case, it's just an empty form - you close it by clicking on the red X). It is popped up modally from within the Main form (while the main form is hidden).
There's a Splash screen on which your video is to play. I fake out the video by using await Task.Delay(4000); to get a pause. After the 4 second delay, I raise an event (equivalent to your media player event). What I do is show this modally from the main form. I put the event handler in this form; when the event is raised, I close the splash screen modal. The entire (non-designer) code for that form looks like (and, since there are no controls on this form, the designer code is pretty lean):
public partial class SplashScreen : Form
{
public event EventHandler SplashFinished;
public SplashScreen()
{
InitializeComponent();
this.SplashFinished += SplashScreen_SplashFinished;
}
private async void SplashScreen_Load(object sender, EventArgs e)
{
await Task.Delay(4000);
SplashFinished?.Invoke(this, new EventArgs());
}
private void SplashScreen_SplashFinished(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
Then there's the Main form. It gets fired up in the normal way from Program.cs:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
The only thing that I added to that form (from the out-of-the-box code) is:
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
var login = new LoginForm();
//should really check this, but for now
login.ShowDialog(this);
var splash = new SplashScreen();
splash.ShowDialog(this);
this.Show();
}
So, when the app starts, the user is shown the login form (the main form is hidden). He does what is needed to do (and the result is checked in the main form's Form1_Load handler.
If everything is cool, a new SplashScreen form is created and shown modally. When it pops up, the video starts (in this case, the video is simply an asynchronous timer). When the video ends, the SplashScreen handles the finished event, and uses it to close itself.
Once control returns to the main form, it displays itself.
Hi I'm relatively new to C# and completely new to windows form and basically trying to create a subliminal messaging program that at timed intervals will quickly display a message for it to then be hidden again.
I've managed to by looking through various other posts created another form that will pop up and then hide very quickly using
msgObject.Activate();
that brings the form to the front. However it is stopping me from being able to type when I'm working and I basically wanting to know if it is possible to make some kind of message or form appear at the front of all my other programs without it interrupting my current work or opening or closing of other windows and tasks if that makes sense. As currently it brings the form to the front of everything but will also stop me from being able to type etc.
I'm not sure if this is possible with my current method of using a form but if there is a way of achieving the result I'm after I'd be very grateful to find out
Thanks.
Here is more of my code to clarify
public partial class FormHomePage : Form
{
private bool startSubliminal = false;
msg msgObject = new msg();
List<string> subliminalMessages = new List<string>();
public FormHomePage()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
if (startSubliminal)
{
msgObject.Show();
msgObject.BringToFront();
msgObject.Activate();
}
}
private void button1_Click(object sender, EventArgs e)
{
subliminalMessages.Add(txtBox1.Text);
msgObject.LabelText = txtBox1.Text;
txtBox1.Text = string.Empty;
startSubliminal = true;
msgObject.Show();
msgObject.BringToFront();
}
private void timer2_Tick(object sender, EventArgs e)
{
msgObject.Hide();
}
}
How are you showing the second form (the message form) in the first place? You're probably using .Show() (right?), which will make the form "steal" the focus anyway. The same applies to .Activate() and .BringToFront().
Instead, what you can do is to show the message form and make sure it stays on top the current form, and then activate the current/main form once again.
Something like this should work:
var frm = new YourMsgForm();
frm.Show(this);
this.Activate();
Here's a demonstration:
Note that I used .Show(this) instead of .Show(), that's in order to set the current form as the Owner of the new one, that way we guarantee that the new form will stay on top of the current one. This is equivalent to calling frm.Owner = this; then frm.Show();.
Another way to make sure the form stays on top is by setting the TopMost property instead of the Owner property. However, doing so will make the new form on top of the other windows as well (not just your application).
If I programatically minimize the application's form while a modal dialog is open, that modal dialog gets closed.
However, if I programatically minimize the application's form while a MessageBox is open, the MessageBox is not closed (i.e. when I restore the application to normal window state, the message box is still showing).
Here's my sample code demonstrating the difference:
public partial class Form1 : Form
{
// ...
private void showMessageBoxBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This MessageBox does *not* get closed when the WindowState of Form1 is set to minimized in timer1_Tick
MessageBox.Show(this, "MessageBox");
}
private void formShowDialogBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
Form2 form2 = new Form2();
form2.ShowDialog();
}
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
timer1.Stop();
}
}
Question:
Is there a way to get the Form to behave like the MessageBox?
What you are seeing is the side-effect of countermeasures built in to Winforms to deal with dialog usability problems, countermeasures that the MessageBox() function doesn't have. They were probably more relevant to Windows 98, originally an important target operating system for Winforms, too long ago for me to remember accurately.
An important usability problem is what happens when you show a dialog and it gets minimized. A dialog disables all other windows in the app so you can no longer activate them. The dialog should have its ShowInTaskbar property set to false. The user now has a problem, there is no simple way to get back to the dialog. Nothing to click on.
Winforms avoids this trap by automatically closing the dialog. As you can tell, MessageBox doesn't do this. It can not reasonably do this either, it doesn't have a good way to return a "dialog was canceled" status code.
Notable is that this trap still partially exists. On my Win8 machine, I can click the disabled form's taskbar button and get it to move back in the foreground. But that activates the disabled form instead of the message box. Major UI blooper there and nasty if the message box is behind that form.
So to answer your question: no. Feature, not a bug.
First, declare the Form2 form variable outside the method's scope, so it could be reachable from the timer1_tick method. Then, when the Timer ticks, minimize the main form, but show the modal dialog and then minimize it.
Try this:
Form2 form2;
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
form2.Show();
form2.WindowState = FormWindowState.Minimized;
timer1.Stop();
}
Matt,
Try changing:
form2.ShowDialog();
to
form2.Show(this);
Is this the behavior you are looking for?
You can try something like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication37
{
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
Form2 form2 = null;
IntPtr parent = IntPtr.Zero;
public Form1()
{
InitializeComponent();
}
private void formShowDialogBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
form2 = new Form2();
form2.ShowDialog();
}
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
timer1.Stop();
}
private void Form1_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.parent = GetParent(form2.Handle);
SetParent(form2.Handle, IntPtr.Zero);
form2.Hide();
}
else
{
SetParent(form2.Handle, this.parent);
form2.ShowDialog();
}
}
}
}
Please note that this is somewhat an hack, I'm not totally sure about consequences. Criticism is acceptable :)
If you set
Visible = true;
on the modal form immediately after programmatically minimizing the owner from, the modal form does not get killed by the OS.
So
ownerForm.WindowState = FormWindowState.Minimized;
will kill the modal form. But
ownerForm.WindowState = FormWindowState.Minimized;
modalForm.Visible = true;
will not kill it.
This question already has answers here:
Disabling the Close-Button temporarily
(7 answers)
Closed 6 years ago.
How can I disable the close button of a form like in the image below? (the image below show a MessageBox window)
The MessageBox above was generated by me! I want to disable the close button of a normal form.
Right click on the window in question, then click Properties. Under Properties click Events. Double click on the FormClosing event.
The following code will be generated by Windows Form Designer:
private void myWindow_FormClosing(object sender, FormClosingEventArgs e)
{
}
Simply update the code to look like this (add e.Cancel = true;):
private void myWindow_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
You're done!
Alternatively, if you want to disable the close, maximize, and minimize buttons of the window:
You can right click the window in question, then click Properties. Under Properties set the ControlBox property to false.
If you are working with an MDI child window and disabling the close button during creation of the window is ruled out (i.e. you want to disable it at certain times during the form's life) none of the previously proposed solutions will work¹.
Instead we must use the following code:
[DllImport("user32")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32")]
public static extern bool EnableMenuItem(IntPtr hMenu, uint itemId, uint uEnable);
public static void DisableCloseButton(this Form form)
{
// The 1 parameter means to gray out. 0xF060 is SC_CLOSE.
EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 1);
}
public static void EnableCloseButton(this Form form)
{
// The zero parameter means to enable. 0xF060 is SC_CLOSE.
EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 0);
}
¹ You can set ControlBox = false if you do not want any buttons, but that is not what the question is asking.
You handle the Closing event (and not the Closed event) of the Form.
And then you use e.CloseReason to decide if you really want to block it (UserClose) or not (TaskManager Close).
Also, there is small example Disabling Close Button on Forms on codeproject.
You should override the CreateParams function derived from System.Windows.Forms.Form
And change the Class Style
myCp.ClassStyle = 0x200;
Closing += (s, eventArgs) =>
{
DialogResult = DialogResult.None; //means that dialog would continue running
};
I am working on a personal project in winforms just to gain some experience in it since I've never had the chance to work with it before. So, I'm quite the n00b when it comes to Winforms. This is the error I'm encountering:
In form BudgetTracker, I have a button called 'AddCat'. Below is the form's constructor and the button's click eventHandler:
public form_BudgetTracker()
{
InitializeComponent();
setEvents();
}
public void setEvents()
{
this.btn_AddCat.Click += new System.EventHandler(this.btn_AddCat_Click);
}
private void btn_AddCat_Click(object sender, EventArgs e)
{
form_NewCat NewCatForm = new form_NewCat();
var NewCatFormResult = NewCatForm.ShowDialog();
NewCatForm.Show();
}
In the NewCat form that comes up, I have a Cancel button. Code:
public form_NewCat()
{
InitializeComponent();
SetEvents();
}
private void SetEvents()
{
this.btn_Add.Click += new System.EventHandler(this.btn_Add_Click);
this.btn_Cancel.Click += new System.EventHandler(this.btn_Cancel_Click);
}
private void btn_Cancel_Click(object sender, EventArgs e)
{
this.Close();
}
The problem I'm facing is, when I click Add, the new form comes up. At this point, if I click Cancel, the form disappears but instantly a new instance of the form appears. I then click cancel again, and the form disappears.
What part of my code is making the form appear twice. I checked the contructors etc, but couldn't figure it out. Any help or pointers would be appreciated.
PS - As I mentioned, I'm new to winforms programming, so any cues or pointers would be appreciated as well.
private void btn_AddCat_Click(object sender, EventArgs e)
{
form_NewCat NewCatForm = new form_NewCat();
var NewCatFormResult = NewCatForm.ShowDialog(); // <-- opens the first time
NewCatForm.Show(); // <-- opens the second time
}
Judging from your code, you're simply showing the form twice!!!
form_NewCat NewCatForm = new form_NewCat();
var NewCatFormResult = NewCatForm.ShowDialog();
NewCatForm.Show();
The second line shows the form and blocks the method until DialogResult is set, then the third line shows the form without blocking the method.
Simply remove the third line!
Try stepping through the code using the F8 key instead of running it, or hitting F5. It will show you line by line what it's about to execute.
delete NewCatForm.Show();