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
Related
I am showing some database records in a Dialog. When I click any particular record that record fills to Active Form. But I want to focus to a button when my dialog close. So I have written the following code on form closing evennt.
private void frmDG_RecordSelection_FormClosing(object sender, FormClosingEventArgs e)
{
RecordSelectionStatus.Text = "False";
Form TargetForm = Home.ActiveMdiChild;
Button SelectRefConsultant = (Button)TargetForm.Controls.Find("btnSelectRefConsultant_NI", true).SingleOrDefault();
SelectRefConsultant.Focus();
TargetForm.ActiveControl = SelectRefConsultant;
}
But it's not working. Focus still remain to it's previous place. What am I missing ?
I am assuming that the dialog is modal... Instead of doing this in FormClosing do it, after calling ShowDialog(). If not, try using the FormClosed event instead.
I think your code is not working because, while the Form is closing, it still has modal focus.
If frmDG_RecordSelection is also MDIChild, then Home.ActiveMDIChild is this form. That is being closed.
But if frmDG is just a Dialog, the problem is different.
This dialog is Closing. But it's still visible. You cannot set focus to control that is not visible.
So you will have to set focus after this frmDG is completely closed, and invisible... To be more specific, when your MDI form is visible.
It's far more easier to do this from your MDI Form. I don't know how you have programmmed it, but I suppose it's something like that:
//this is in your MDI form
void OnRecordSelected(...)
{
frmDG yourDialog = new frmDG();
frmDG.ShowModal();
frmDG.Dispose();
}
In this case, you will have to set focus after frmDG is disposed.
I have a form, wherein I prohibit the user from closing it when the user clicks the Close (X) button. Is it possible to show a tooltip on the Close (X) button whenever it is clicked? I want to do it to notify the user why the form would not close.
I thought of a messagebox but then I thought it would be too annoying to close the messagebox every time you click the Close (X) button.
Is there a better way to notify the user, than what I'm trying to do?
EDIT:
This is my code for the FormClosing event
private void InputForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
if (!mCloseReason)
{
e.Cancel = false;
}
}
}
I have a method that will save the inputs in the form. Once that method is finished, I need to automatically close the form. The if-statement will be true once I call this.Close(), this means I can't close the form. That's why I used a variable called mCloseReason to be able to close the form automatically. Now, that's why I was asking if I can notify the user through a tooltip once the Close (X) button is clicked.
I believe the default tooltip for the close(X) button is not editable without some hacking (and it is not practical).
Maybe what you could do is have a status field below your form, so when the user clicks the close button, it says in the status field "cannot close form (...)"
Or another idea is to have a message pop up somewhere on the form and go away after a little, indicating the form cannot be closed.
Another good idea was mentioned by Roger... just have a Close button somewhere on the form with a tooltip coded to it, and hide the forms' title bar?
I currently have a problem with forms here.
Whenever some process is ongoing, I have a progress dialog that should popup, but when I click the "X" button of the window/form behind my progress dialog, it will be dismissed and the ongoing operation is cancelled.
How can I prevent that from happening? Should I have to disable my whole form behind my progress bar? and how can I do it?
p.s.
I have tried this and this and this but NONE of them seems to work in my application. T__T
Start the form using Form.ShowDialog() instead of Form.Show(). That will disable the background form (actually any other form in the process) until the form you are showing closes. As an added benefit you can have the form return a value (e.g. Cancel, OK, Yes, No, etc.) in case any action needs to be taken as a result.
Not actually the answer you might be expecting, but you could handle the Form.FormClosing event, setting e.Cancel = True
This won't disable the Close button, but will make your form remain open in this case.
See more at: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosing.aspx
You should show the progress bar as modal dialog, please check whether this answer work for you javasript like model window on winform
HTH.
Within the application I am writing for testing/learning C#, I use the hidden/visible property to open and close windows.
It is a WPF application.
In the main window, I have a "close" button that triggers this method:
public void buttonQuit_Click(object sender, RoutedEventArgs e)
{
var message = exitmessage;
var title = exitTitle;
var result = MessageBox.Show(
message, // the message to show
title, // the title for the dialog box
MessageBoxButton.YesNo, // show two buttons: Yes and No
MessageBoxImage.Question); // show a question mark icon
// lets see what has been pressed
switch (result)
{
case System.Windows.MessageBoxResult.Yes: // Yes button pressed
CloseAllWindows();
break;
case System.Windows.MessageBoxResult.No: // No button pressed
break;
default: // Neither Yes nor No pressed (just in case)
MessageBox.Show("Oh noes! What did you press?!?!");
break;
}
}
This way I make sure that all windows get closed, including the hidden ones.
But now is the catch; when the user presses (in the main window) the top right red X in toolbar to close, only that main window gets closed, but in the background the hidden ones are still there.
So in fact it is 2 questions:
Is CloseAllWindows(); really sufficient to get the app 100% closed down?
How do I "catch" the event when the user presses that red X in the toolbar, and make this also trigger the right closing event?
You should be handling either the Closing or Closed event for your window(s). The former allows you to cancel the close, while the latter just allows you to perform necessary cleanup in response to the window being closed.
So, in this case, you should place the code from your buttonQuit_Click method into a handler method attached to the Closing event so that it gets triggered regardless of how the window is closed.
Then, your buttonQuit_Click method can simply call the window's Close method. That will close the window, in turn raising the Closing event, and running your code in the attached handler method.
As far as your other question, CloseAllWindows will do exactly what it says: it will close all of the windows that your application has opened. In most cases, that should be sufficient to close the application, but it might not be, especially if you've created non-background threads or depending on the ShutdownMode setting.
App.Current.Shutdown will work unconditionally.
You could use the Closing event of the window for that.
Some more info
http://msdn.microsoft.com/en-us/library/system.windows.window.closing.aspx
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.