The proper way to check if a form is already shown? - c#

I have created a task managment application and I wanted to implement the ability for 2-users to chat about specific task.
In Form1 I have a timer that check on the database for any new message sent. When a new message found, the chat form appear showing the message.
Till now, everything is working as expected but I have only one problem.
The problem :
Once a new message found for the first time, the chat window appear, but when another new message is found, another window appear, and for each new message I have a new instance of the chat window created.
The code I'm using :
List<string> tasksToDiscuss = checkForTasksToDiscuss(fullname);
if (tasksToDiscuss.Count > 0) {
// open the chat window directly minimized
Form14 frm14 = new Form14();
frm14.get_from = fullname;
frm14.get_to = tasksToDiscuss[1];
frm14.get_task_id = int.Parse(tasksToDiscuss[3]);
// set message as read
if (setMessageAsRead(tasksToDiscuss[1], fullname, int.Parse(tasksToDiscuss[3])))
{
// now show the chat window minimized
frm14.Show();
}
}
I tried to replace the line: frm14.Show(); with frm14.ShowDialog();
I noticed that when the new message is received, the chat window (form14) is shown, and when another message is received from the same user, no new chat window appear, but the problem is that after i close the chat window, it doesn't appear anymore even when i receive new messages.
What I think to do is to change the chat window (Form14.Text) to the user fullname, and the next time a message is received, I check whether the specific window is already open, then don't open it otherwise i show the form using the .Show() method.
Is this the proper way to make the window doesn't appear if a new message is received and it is aloready opened ? and How to check wether a window is opened according to it's Text (title bar text) ?
Thank's for taking time reading my question. Any help would be highly appreciated

Firstly you are creating a new instance of Form14 every time you have a new message.
Secondly Show and ShowDialog do two very different things:
Show just displays the form, whereas ShowDialog displays the form as a modal dialog. This means the user can't do anything else until they dismiss the form.
You need to have a single instance of the form and you can use the Visible property to determine whether it's shown or not. So you would have:
private Form14 frm14;
Then in the constructor:
frm14 = new Form14();
Then in your code:
if (!frm14.Visible)
{
// Add the message
frm14.Show();
} else{
// Top
frm14.BringToFront();
}

Try making form14 a member of form1.
When you get a new message check the Visible property of forom14
to know if it is already showing.

Related

C# ChromiumWebBrowser: Prevent control from stealing focus

I'm making a program that has a Form with a ChromiumWebBrowser in it. The navigation is done automatically. When webbrowser complete it's task, I'll dispose it, create a new webbrowser, add it to form, and load a new address.
But, when the new webbrowser was created and added to form, the program jumps in front of what ever other program is in the top with focus. Example: I start my program, press the button to start its task, open notepad to type some text and my program jumps in front of it when navigating to a new site.
Even when the window is minimized, it still steals focus from other open programs.
How do I prevent it stealing focus after it is created?
As #amaitland said, this looks like a bug.
Workarounds I've used are:
1) disable the browser. This will prevent the browser from receiving mouse/keyboard input, but it won't "grey-out" the control.
Browser1 = New CefSharp.WinForms.ChromiumWebBrowser(url)
Browser1.Enabled = False
2) Pass a callback .net function for when the page loads where you simply put the focus back to winforms by focusing on a label of your choice.
Label1.Focus()
Your Form need set: this.Topmost = false;
AND just set: this.BringToFront();
Add new browser to the form just like the function as follow:
private ChromiumWebBrowser AddNewBrowser(FATabStripItem tabStrip, String url)
{
if (url == "")
{
url = OpenUrl;
txtUrl.Select();
txtUrl.Focus();
}
else
{
tabStrip.Select();
tabStrip.Focus();
}
// ...
}
Hope has help to you. Thanks !

C# child form not returning to expected point in program (parent form)

I am writing a simple game, this is my first foray into Visual Studio forms and my program is not behaving as expected. I have a main form (game board) that opens a new form allowing the user to select players. When the players are selected and the user clicks OK, the form closes and returns to the main form - except that it does not return to the line after the gp.Show() call.
Here is the code that is not behaving as I expect:
GetPlayers gp = new GetPlayers(); // Form that allows the user to select players
gp.Show(); // Display form
Console.WriteLine("Form Closed"); // This is not getting displayed when gp calls this.close()
As I mentioned, I am completely new to forms so I may be doing something stupid here.
Any help would be appreciated, thanks.
Showis non-blocking and does not wait for the form to close. Use ShowDialog for that behavior.

c# second form closing after initialisation

I am trying to create a simple c# application (my first attempt at c# so please be kind). I've created a form with a textbox to capture an "auth code", which is then validated and then a webclient fetches an xml file passing this auth code in to the request. The data sent back is parsed e.c.t.
What i want to do is once the xml comes back and ive done my checks to valid it is all fine. I want to close the first form and load up a second form where i will programmatically add the form components needed to display the xml data in a pretty format.
My problem is that im unable to get the second form to stay open (im no doubt invoking the second form in the wrong manner). Here's what i have:
// close current form
this.Close();
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
I'm sure you've spotted the mistake im making by now. but just to state the obvious for the sake of completeness, it closes the first form, opens the second, and then immediately the program exits (the second form flashes up for a second obviously).
I've tried a few things but none of them work (including using Application.Run(new xmlViewForm()); instead of instantiating the class and using the show() method. Obviously you know that doesn't work, and now i do too, although i dont understand c# even remotely enough to work out why.
Thanks for any help :)
The first thing that came to mind is that you are closing the form that you opened by calling Application.Run(new MyForm()) or something similar. This form has special significance; it is the "main form" of the application, and when closed, it signals to the application that the user wants to close the entire program, no matter how many other windows are open.
There are two possible fixes. First, and easiest, is simply to Hide() the form you don't want visible instead of calling Close() on it. Though invisible, it's still running, so the application doesn't close.
The second solution is to define a custom "application context" that should be run instead of the "default context" that is created by specifying a main form to watch. You do this by deriving a custom class from System.Windows.Forms.ApplicationContext. With this context specified, you can use it to control termination of the application based on something other than closure of the main form. Example code that launches two "main forms" and keeps track of whether both are still active can be found at the MSDN page for the class. You can do something similar by specifying Load and Close handlers for the main form, then passing them to the child form when the main form instantiates it, thus keeping a count of "open" forms, and closing out the full application when that number is zero. Just make sure the child form loads before closing the main form by calling childForm.Show() before this.Close().
You can not open the second form after closing the main form.
Do this:
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
// hide current form
this.Hide();
Main form can not be closed because it's the parent form. The child form will never show up if you close the main form.
Or change the xmlViewForm to main form by editing Program.cs file
Application.Run(new XmlViewForm());
Then you can easily call the other form first at the time of loading and close it as you please:
private void XmlViewForm_Load(o, s)
{
// hide current form, and this will remain hidden until the other form is done with it's work
this.Hide();
//open the other form
TheOtherForm _theOtherForm = new TheOtherForm();
_theOtherForm.Show();
}
private void TheOtherForm_Closed(o, s)
{
// show current form
this.Show;
}

How can I transfer information to another form without using static forms?

I have a Windows form that's generated using code (including buttons and what not). On it, amongst other things, there is a text box and a button. Clicking the button opens a new Windows form which resembles an Outlook contact list. It's basically a data grid view with a few options for filtering. The idea is that the user selects a row in this home-made contact book and hits a button. After hitting that button, the (second) form should close and the email address the user selects should be displayed in the text box on the first form.
I cannot use static forms for this purpose, so is there any way to let the first form know the user has selected something on the second firm? Can you do this with events, or is there another way? Mind that I hardly know anything about delegates and forms yet.
Please advise.
Edit 1 = SOLVED
I can return the email address from the second form to the first form now, but that brings me to another question. I am generating controls and in that process I'm also generating the MouseClick eventhandler, in which the previous procedure for selecting a contact is put.
But how do I, after returning the email address in the MouseClick eventhandler, insert that information into a generated text box? Code to illustrate:
btn.MouseClick += new MouseEventHandler(btn_MouseClick);
That line is put somewhere in the GenerateControls() method.
void btnContacts_MouseClick(object sender, MouseEventArgs e)
{
using (frmContactList f = new frmContactList())
{
if (f.ShowDialog(fPrompt) == DialogResult.Cancel)
{
var address = f.ContactItem;
MessageBox.Show(address.Email1Address.ToString());
}
}
}
That appears separately in the class. So how do I put the email address into a text box I previously generated?
Forms in .Net are normal classes that inherit from a Form class.
You should add a property to the second (popup) form that gets the selected email address.
You should show the popup by calling ShowDialog.
This is a blocking call that will show the second form as a modal dialog.
The call only finishes after the second form closes, so the next line of code will run after the user closes the popup.
You can then check the property in the second form to find out what the user selected.
For example: (In the first form)
using(ContactSelector popup = new ContactSelector(...)) {
if (popup.ShowDialog(this) == DialogResult.Cancel)
return;
var selectedAddress = popup.SelectedAddress;
//Do something
}
In response to my first edit, this is how I solved it. If anyone knows how to make it more elegant, please let me know.
void btnContacts_MouseClick(object sender, MouseEventArgs e)
{
using (frmContactList f = new frmContactList())
{
if (f.ShowDialog(fPrompt) == DialogResult.Cancel)
{
var contact = f.ContactItem;
TextBox tbx = ((Button)sender).Parent.Controls[0] as TextBox;
tbx.Text = contact.Email1Address;
}
}
}
You should keep a reference to your generated TextBox in a variable (private field in your class) and use this instead of looking it up in the Controls array. This way your code would still work even if you some time in the future change the location it has in the array, and you would get a compiler message if you removed that field, but forgot to remove the code that used it.
If the second form is modal, I would recommend that rather than having the first form create an instance of the second form and use ShowModal on it, you should have a Shared/static function in the second form's class which will create an instance of the second form, ShowModal it, copy the appropriate data somewhere, dispose the form, and finally return the appropriate data. If you use that approach, make the second form's constructor Protected, since the form should only be created using the shared function.

C# close Outlook "Outbox is not empty" dialog programmatically

I have a program that sends information in the background using Outlook. I want to avoid having the user deal with the "Outbox is not empty" message that appears when a user tries to close Outlook when an email is in the outbox. because in most cases the email in the outbox will not be an email they sent themselves. I am able to get a handle to the dialog, but I don't know which command to send to make it close. The only close command I know about will not work for a dialog box.
I must use Outlook to send the email due to security constraints.
I got the code from here which shows you how to trap the window events and sort through the window you want. I have found the window, and it helped me to stop the threads that might be sending email, but the dialog is still hanging there when I'm done.
The following code executes whenever an Explorer window is deactivated (i.e. loses focus)
void ExplorerWrapper_Deactivate()
{
IntPtr hBuiltInDialog = WinApiProvider.FindWindow("#32770", "Microsoft Office Outlook");
if (hBuiltInDialog != IntPtr.Zero)
{
// ok, found one
// let's see what childwindows are there
List<IntPtr> childWindows = WinApiProvider.EnumChildWindows(hBuiltInDialog);
// Let's get a list of captions for the child windows
List<string> childWindowNames = WinApiProvider.GetWindowNames(childWindows);
// now check some criteria to identify the build in dialog..
// here are the three child window names as cut and pasted from the code when debugging
// [0] = "There are unsent messages in your Outbox. To send messages, Outlook must remain running and connected to your e-mail server. Do you want to exit anyway?\r\n\r\nExiting in <0d> seconds"
// [1] = "Exit Without Sending"
// [2] = "Don't Exit"
if ((childWindowNames.Contains("There are unsent messages in your Outbox. To send messages, Outlook must remain running and connected to your e-mail server. Do you want to exit anyway?\r\n\r\nExiting in <0d> seconds")) &&
(childWindowNames.Contains("Exit Without Sending")) &&
(childWindowNames.Contains("Don't Exit")))
{
// at this point, we need to empty the outbox of any IkeNet email, and if the outbox is then empty, close the dialog
// and let outlook close as well
NotifyAdmin.SetShutdownRequested();
/// this close command does not seem to work for this window. supposedly it acts just like pressing
/// the <esc> key, which does nothing to the window when the program is running.
WinApiProvider.SendMessage(hBuiltInDialog,
WinApiProvider.WM_SYSCOMMAND, WinApiProvider.SC_CLOSE, 0);
}
}
}
The WinApiProvider.SC_CLOSE command will not work for this kind of window.
Any suggestions will be appreciated.
You could try using SendKeys to [tab][tab][enter] (or whatever the keystrokes are). I know it's not an elegant solution, but is this solution really elegant to begin with?
I would try sending a mouse click event to the Cancel button (or Close button -- I'm not familiar with the dialog box in question).

Categories