I want to show messagebox to the user, such that the user cannot refuse to confirm the message box. User should not be allowed to do anything else in the screen until he confirms the messagebox.
This is a windows based c# application.
The main thing is, even if i use windows message box. Some times it is hiding behind some screen. But for my case, i want message box to be on top most whenever it appears.
I am using some other third party applications, which over rides my message box. I want to overcome this.
How to do this...
You will have to create your own form, make it modal, change the z-order to make it always on top, and capture all keystrokes and mouse clicks.
Always on top: http://www.codeguru.com/cpp/w-d/dislog/article.php/c1857
Take a look at this article
MessageBox.Show Examples in Windows Forms C#
Edit:
You can also use the topmost property of a form to make it on top of all windows in a given application.
How to: Keep a Windows Form on Top
To display a form as a modal dialog call the ShowDialog method.
Form frmAbout = new Form();
frmAbout.ShowDialog();
If standard implementation of MessageBox doesn't do what you need, you will have to create your own form and use ShowDialog() method.
It sounds like the messagebox is being displayed on another thread. You need to make sure that you call MessageBox.Show on the main UI thread. Below is a code snippet that illustrates a way to achieve this:
public class FooForm: Form
{
//This is just a button click handler that calls ShowMessage from another thread.
private void ButtonShowMessage_Click(object sender,EventArgs e)
{
//Use this to see that you can't interact with FooForm before closing the messagebox.
ThreadPool.QueueUserWorkItem(delegate{ ShowMessage("Hello World!");});
//Use this (uncomment) to see that you can interact with FooForm even though there is a messagebox.
//ThreadPool.QueueUserWorkItem(delegate{ MessageBox.Show("Hello World!");});
}
private void ShowMessage(string message)
{
if( InvokeRequire)
{
BeginInvoke(new MethodInvoker( () => MessageBox.Show(message)));
}
else
{
MessageBox.Show(message);
}
}
}
I am assuming that you don't have a scenario where you have multiple UI threads and when one of them pops a messagebox, you want that messagebox to be modal for the entire UI. That's a more complicated scenario.
Related
I'm fairly new to Visual Studio in C#.
I was wondering how to pop up a message box when the user clicks anywhere within the form window.
Basically, I don't want them accessing and interacting with the program unless they have a password.
Code for the Form1() is really simple right now:
public Form1()
{
InitializeComponent();
}
The actual interface has a bunch of buttons and settings (buttons and settings I don't want the user to be able to interact with unless they have verified themselves).
regarding the 1st questions.
You usually create a second model form , that is transparent and is on top of your form.
Handle the on-click event of the transparent form .
Regarding the second questions- you should rethink your design , maybe do not show the sensitive form at all untill a user has typed the password.
By the way , you have not specified what tech do you use?
is it desktop (winforms / wpf , other)/ web (web forms, asp mvc, other) ?
recommended reading for client side windows programming.
http://msdn.microsoft.com/en-us/library/dd492132.aspx
Edit:
In order to put a form on top of another form , you use a model dialog.
http://msdn.microsoft.com/en-us/library/39wcs2dh(v=vs.110).aspx
In order to create a form transparent
http://msdn.microsoft.com/en-us/library/czke9azk(v=vs.110).aspx
Also , it still depends on your UI technology.
Provided links are form winforms, other technology may require a different approach.
Edit:
As another answer pointed out , you could also bind to the original forms click event , but you will also have to bind to every child control click event recursively.
Click on form and press F4 key that show property window then click on event button there you click on click event that show in .cs file of form .
Make function like
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("Click");
}
Should sound weird, but this is just for my hobby. I would want a (custom) messagebox to pop up with a YesNo buttons which should ideally block the code. But I should be able to click on the parent form so that I can dismiss the message box without having to specifically click on the messagebox buttons (equivalent to clicking No on the message box)..
something like this:
void Foo()
{
CustomMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block the code here, but user should be able to click on form, so that its equivalent to have clicked No;
//if clicked No, return;
//delete.
}
So the solution I thought was make the custom message box non modal - so that user can click on form, but I'm not able to block code.. How can i do that?
It would look like this:
void Foo()
{
NonModalMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block thread till user clicks on form or messagebox buttons.
//unblock when user clicks.
//if No, return;
//delete.
}
Edit: I know this is not a standard practice and I know non modal forms do not block, while modal forms do. So please do not recommend to be content with either modal form's or non-modal form's behavior. My question would be is there any way to simulate the behaviour of ContextMenu with windows forms.
You can solve this quite easily. Create and use a modal dialog but override the WndProc of the dialog and process the WM_MOUSEDOWN event. Check the position of the mouse down and if it is over the parent window but not over the dialog itself then simply dismiss the dialog.
Essentially you can't do this in a 'blocking' call easily. What you could do easily enough is to either pass the information required to perform the delete, or a delegate to perform the operation, to the form. When they click Ok you simply perform the operation. If they activate the parent form, then just close the child.
You want the user to be able to click the background window to cancel the dialog box? Add a handler to the background window so that when the user clicks on it you check to see if the non-modal window is displayed, if so close it.
Sounds easy, but you will need to be careful to handle every possible click on the background window and child windows. That sounds like a can of worms I wouldn't want to go down.
Perhaps instead you could detect if the non-modal dialog box loses focus and automatically close it. I can see this behavior making sense for a simple "confirm delete" dialog box, but as a user my first reaction is going to be to spam the ESC key to close the dialog box.
Another way of handling this is by manually enabling the parent form when calling ShowDialog, from here
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool enable);
internal static DialogResult ShowDialogSpecial(this Form formToBeShown, Form parent)
{
parent.BeginInvoke(new Action(() => EnableWindow(parent.Handle, true)));
formToBeShown.ShowDialog(parent);
return formToBeShown.DialogResult;
}
Just call the extension method from any parent form like this:
var f = new Form();
f.ShowDialogSpecial(this);
//blocks but parent window will be active.
Of course you need to handle the clicks on parent form to close child form.
You could do something like:
public void ShowMe() {
Show();
while (!_receivedDeactivateEvent)
Application.DoEvents();
}
I'm not sure I'd recommend it, though -- I'm not sure how stable it would be, nor am I sure whether it would behave the way you want if you click the Delete button on the parent form while the 'dialog' is up (would it close the first dialog first, or leave it up? might be the latter, which could get messy).
An easier way: set form's "TopMost" property to be True. Then it will act like blocking
I'm using c# to make a mobile 6 application. I created another windows form in the project. This is the form that I would like to load first. This is what have tried:
MainMenu gameMenu = new MainMenu();
private void MainForm_Load(object sender, EventArgs e)
{
this.Hide();
gameMenu.ShowDialog();
.....
}
When I run this the emulator comes up but it just stays as the default windows screen. And I don't get any of my forms.
GameMenu's parent is MainForm, which is now hidden, so the Dialog isn't going to be visible. You need to adjust your logic to do one of the following:
show the GameMenu first (i.e. Application.Run(new GameMenu))
Don't hide MainForm
Use gameMenu.Show() instead of ShowDialog()
You may need to get rid of this.Hide() or use gameMenu.Show() instead of gameMenu.ShowDialog() or you may need to do both.
If you have to use gameMenu.Show() instead of gameMenu.ShowDialog(), you may also want to do the following:
Subscribe to MainForm's GotFocus event and call gameMenu.Show() again whenever the other form gains focus unintentionally. Set MainForm's Enabled property to false while the gameMenu is shown if you want to prevent any accidental interaction with the MainForm while the gameMenu is supposed to be shown.
I have a WPF window that is run on a background thread as a sort of "notifier window"... when an event is raised, it displays a message... a user clicks the "Snooze" button and I call this.Visibility = Visibility.Collapsed
The very moment that I hide the window (either by calling this.Hide() or setting the Visibility as mentioned above)... the "ShowDialog()" code releases the window and closes it.
This is absolutely a bug in the WPF code (which I've identified via reflector)... but my question remains. Has anyone been able to come up with a work-around for this issue?
I've tried many things and am now reaching out to ya'll smart people :)
You can't hide a modal dialog. That's like asking, "How do I get to 100mph in reverse?" You don't, you drive the car forwards.
Use Show, not ShowDialog. Alternately you can simply re-ShowDialog when it needs to become visible again.
Timothy's Answer is good. I just needed for my scenerio to add the following
window.Closed += new EventHandler(window_Closed);
window.Show();
System.Windows.Threading.Dispatcher.Run();
and then in the event...
void window_Closed(object sender, EventArgs e)
{
System.Windows.Threading.Dispatcher.ExitAllFrames();
}
I needed to do this because it was hanging on the Run after the form was really closed.
In order to show modal window always use ShowDialog().
Use Close() instead of Hide().
Handle the FormClosing event like that:
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Visible = false;
}
OK, and as quickly as that - my boss (old C++ goofy guy that he is) figured out the answer.
Here was the code inside of my background thread (which is set to STA mode):
// Show dialog - keeps the thread open and shows the window! Yay!!!
new BeamUI.Notifier.NotifierWindow().ShowDialog();
And here is the modification, that strangely enough works perfectly :)
// Show... hmm, that shows the window... but how do I keep this thread open?
new BeamUI.Notifier.NotifierWindow().Show();
// ZOMG - a line of code that JUST keeps the thread (and msgpump) going!!!
System.Windows.Threading.Dispatcher.Run();
And that's it.
This kinda thing makes me hate C++ people though, and makes me want to just say "if you just built it right in the first place I wouldn't have to look for a work-around!" (j/k)
I have a problem with modality of the forms under C#.NET. Let's say I have main form #0 (see the image below). This form represents main application form, where user can perform various operations. However, from time to time, there is a need to open additional non-modal form to perform additional main application functionality supporting tasks. Let's say this is form #1 in the image. On this #1 form there might be opened few additional modal forms on top of each other (#2 form in the image), and at the end, there is a progress dialog showing a long operation progress and status, which might take from few minutes up to few hours. The problem is that the main form #0 is not responsive until you close all modal forms (#2 in the image). I need that the main form #0 would be operational in this situation. However, if you open a non-modal form in form #2, you can operate with both modal #2 form and newly created non modal form. I need the same behavior between the main form #0 and form #1 with all its child forms. Is it possible? Or am I doing something wrong? Maybe there is some kind of workaround, I really would not like to change all ShowDialog calls to Show...
Image http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png
Modal forms do exactly what "modal" means, they disable all other windows in the app. That's rather important, your program is in a somewhat perilous state. You've got a chunk of code that is waiting for the dialog to close. Really Bad Things could happen if those other windows were not disabled. Like the user could start the modal dialog again, now your code is nested twice. Or she could close the owner window of the dialog, now it suddenly disappears.
These are the exact kind of problems you'd run into if you call Application.DoEvents() inside a loop. Which is one way to get a form to behave modal without disabling other windows. For example:
Form2 mDialog;
private void button1_Click(object sender, EventArgs e) {
mDialog = new Form2();
mDialog.FormClosed += (o, ea) => mDialog = null;
mDialog.Show(this);
while (mDialog != null) Application.DoEvents();
}
This is dangerous.
It is certainly best to use modal forms the way they were designed to stay out of trouble. If you don't want a modal form then simply don't make it modal, use the Show() method. Subscribe to its FormClosing event to know that it is about to close:
private void button1_Click(object sender, EventArgs e) {
var frm = new Form2();
frm.FormClosing += new FormClosingEventHandler(frm_FormClosing);
frm.Show();
}
void frm_FormClosing(object sender, FormClosingEventArgs e) {
var frm = sender as Form2;
// Do something with <frm>
//...
}
The first thing that comes to mind would be something like this. You could disable form 1 when you launch form 2 and then have form 1 handle the closed event of the second form to re-enable itself. You would NOT open modal 2 using show dialog.
Now keep in mind, from a user perspective this is going to be quite cumbersome, you might look at doing a MDI application to get all windows inside of a single container.
Your main form will not be responsive until any modal dialogs that are in the same process space are closed. There is not work around for that.
It looks to me like you could use an MDI application setting the Form #0 IsMdiContainer property to true.
Then, you could do something alike:
public partial class Form0 {
public Form0 {
InitializeComponent();
this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened.
}
private void button1_Click(object sender, EventArgs e) {
Form1 newForm1 = new Form1();
newForm1.Parent = this;
newForm1.Show();
}
}
Using the ShowDialog() as you stated in your question will make all of the forms Modal = true.
By definition, a modal form is:
When a form is displayed modally, no input (keyboard or mouse click) can occur except to objects on the modal form. The program must hide or close a modal form (usually in response to some user action) before input to another form can occur. Forms that are displayed modally are typically used as dialog boxes in an application.
You can use this property [(Modal)] to determine whether a form that you have obtained from a method or property has been displayed modally.
So, a modal form shall be used only when you require immediate assistance/interaction from the user. Using modal forms otherwise makes believe that you're perhaps running into a wrong direction.
If you do not want your main form to be an MDI container, then perhaps using multithreading is one solution through a simple BackgroundWorker class is the key to what you want to achieve. Thus, it looks to me like a design smell...
What is it you want to do, apart of making your main form responsive, etc.
What is it you have to do?
Explaining what you have to do, we might be able to guide you altogether into the right, or at least perhaps better, direction.
Actually the answer is very simple. Try
newForm.showDialog();
This will open a new form, while the parent one is inaccessible.