I want to show YesNoCancel button in the message box, but at the same time, I wanted to disable YesNo button and enable only Cancel button.
The reason I wanted to do like this is I am doing a demo application where I want to show users that particular feature is available but at the same time I don't want to give them save access.
Following is my code, now to how to Disable YesNo button.
DialogResult result = MessageBox.Show("Save changes to " + this.Text.Substring(0, this.Text.Length - 1) + "?",
"Save confirmation", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
Actually I want to show YesNo buttons but I wanted to disable click acess for it. I wanted to show users 3 buttons YES , No and Cancel but click acess should be given only to cancel button. Is that possible?
edit:
Thanks all for the answers.
I have found soultion for my question
My code for custom message box, I hope this might help someone
customMsgBox.cs
enter code here { public partial class CustomMsgBox : Form
{
static CustomMsgBox MsgBox;
static string Button_id;
public CustomMsgBox()
{
InitializeComponent();
}
internal static string ShowBox(string txtMessage, enumMessageIcon messageIcon)
{
MsgBox = new CustomMsgBox();
MsgBox.labelCustomMsg.Text = txtMessage;
MsgBox.addIconImage(messageIcon);
MsgBox.ShowDialog();
return Button_id;
}
/// <summary>
/// We can use this method to add image on message box.
/// I had taken all images in ImageList control so that
/// I can easily add images. Image is displayed in
/// PictureBox control.
/// </summary>
/// <param name="MessageIcon">Type of image to be displayed.</param>
private void addIconImage(enumMessageIcon MessageIcon)
{
switch (MessageIcon)
{
case enumMessageIcon.Error:
pictureBox1.Image = imageList1.Images["Error"]; //Error is key
//name in imagelist control which uniquely identified images
//in ImageList control.
break;
case enumMessageIcon.Information:
pictureBox1.Image = imageList1.Images["Information"];
break;
case enumMessageIcon.Question:
pictureBox1.Image = imageList1.Images["Question"];
break;
case enumMessageIcon.Warning:
pictureBox1.Image = imageList1.Images["Warning"];
break;
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
Button_id = "Cancel";
MsgBox.Dispose();
}
private void btnNo_Click(object sender, EventArgs e)
{
Button_id = "No";
MsgBox.Dispose();
}
private void btnYes_Click(object sender, EventArgs e)
{
Button_id = "Yes";
MsgBox.Dispose();
}
}
#region constant defiend in form of enumration which is used in showMessage class.
internal enum enumMessageIcon
{
Error,
Warning,
Information,
Question,
}
internal enum enumMessageButton
{
OK,
YesNo,
YesNoCancel,
OKCancel
}
#endregion
}
main.cs
String customResult = CustomMsgBox.ShowBox("Save changes to " + this.Text.Substring(0, this.Text.Length - 1) + "?", enumMessageIcon.Question);
The MessageBoxButtons Enumerations does not have such options, It contains the following members
So the better option for you is a custom message box, for this you can try this, this or this, Or simply follow the recipe,
Create a Form(let it be frmMessage) with a constructor accepts a string value that is the message that you wanted to display,
Give an appropriate title Text, let it be Save confirmation,
Place a Label to display the message in the label from the constructor.
Place Three buttons, Give name and Text for them,
Disable the Two(Yes/No), Your message box is ready
Usage Example:
Now you need to create an object of this message box and call them like the following:
frmMessage frmMessageInstance = new frmMessage("Save changes to " + this.Text.Substring(0, this.Text.Length - 1) + "?");
frmMessageInstance.ShowDialog();
As explained by Un-lucky, the only way you can do that is by creating your own custom messageBox. I would do something like this
/// <summary>
/// The form internally used by <see cref="CustomMessageBox"/> class.
/// </summary>
internal partial class CustomMessageForm : Form
{
/// <summary>
/// This constructor is required for designer support.
/// </summary>
public CustomMessageForm ()
{
InitializeComponent();
}
public CustomMessageForm (string title, string description)
{
InitializeComponent();
this.titleLabel.Text = title;
this.descriptionLabel.Text = description;
}
}
/// <summary>
/// Your custom message box helper.
/// </summary>
public static class CustomMessageBox
{
public static void Show (string title, string description)
{
// using construct ensures the resources are freed when form is closed
using (var form = new CustomMessageForm (title, description)) {
form.ShowDialog ();
}
}
}
Graciously copied from an answer by Dan Abramov for question How to create a custom MessageBox?
Related
Background
I'm currently working on an application in VSTO2015 and Excel 2016. The application manages a number of CustomTaskPanes in different windows. I am trying to get // some code to fire when the task pane is opened or closed. In order to handle the various windows, I've implemented a structure very similar to this;
CustomTaskPane in Excel doesn't appear in new Workbooks
ThisAddIn.cs contains the following class;
public class TaskPaneManager
{
static Dictionary<string, Microsoft.Office.Tools.CustomTaskPane> _createdPanes = new Dictionary<string, Microsoft.Office.Tools.CustomTaskPane>();
/// <summary>
/// Gets the taskpane by name (if exists for current excel window then returns existing instance, otherwise uses taskPaneCreatorFunc to create one).
/// </summary>
/// <param name="taskPaneId">Some string to identify the taskpane</param>
/// <param name="taskPaneTitle">Display title of the taskpane</param>
/// <param name="taskPaneCreatorFunc">The function that will construct the taskpane if one does not already exist in the current Excel window.</param>
public static Microsoft.Office.Tools.CustomTaskPane GetTaskPane(string taskPaneId, string taskPaneTitle, Func<UserControl> taskPaneCreatorFunc)
{
string key = string.Format("{0}({1})", taskPaneId, Globals.ThisAddIn.Application.Hwnd);
string title = taskPaneId;
string windowId = Globals.ThisAddIn.Application.Hwnd.ToString();
if (!_createdPanes.ContainsKey(key))
{
var customTaskPane = taskPaneCreatorFunc();
var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
_createdPanes[key] = pane;
//
// Set the task pane width as set in the App.Config
//
pane.Width = Convert.ToInt32(ConfigurationManager.AppSettings["TaskPaneWidth"]);
}
return _createdPanes[key];
}
....
My calls from Ribbon.cs;
private void btnUploadWizard_Click(object sender, RibbonControlEventArgs e)
{
// Check for configuration sheet first.
string title = "Upload Wizard";
TaskPaneManager.isConfigurationCreated();
var UploadWizardTaskpane = TaskPaneManager.GetTaskPane(title, title, () => new TaskPaneUploadWizard());
UploadWizardTaskpane.Visible = !UploadWizardTaskpane.Visible;
}
The Problem: Event Handlers
I'm having difficulty getting an event handler to fire. I can't tell what I'm doing wrong. In the TaskPaneDesigner I am attaching the event using this.VisibleChanged += new System.EventHandler(this.TaskPaneUploadWizard_VisibleChanged);, and then defining it in my TaskPaneUploadWizard class as follows;
public partial class TaskPaneUploadWizard : UserControl
{
...
public TaskPaneUploadWizard()
{
InitializeComponent();
}
private void TaskPaneUploadWizard_VisibleChanged(object sender, EventArgs e)
{
// Some code
}
My thoughts
It seems to me as though I am either attaching the eventHandler to something other than the CustomTaskPane object, or I am attaching it before the CustomTaskPane is created.
Help!
To detect if the task pane was opened or closed, you have to attach to the VisibleChanged event of pane.
So the simplest solution would be to add just one line of code to the GetTaskPane method:
var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
// This is the new line to be added.
pane.VisibleChanged += (s, e) => customTaskPane.Visible = pane.Visible;
_createdPanes[key] = pane;
Now the visibility of the whole task pane will be passed on to its content and // some code should be executed.
Alternatively, if you don't want to manually set customTaskPane.Visible for whatever reason, you could as well execute your code directly in this new event handler:
pane.VisibleChanged += (s, e) => { /* some code */ };
But personally I would rather recommend the first approach because it seems to fit a bit better into your existing code.
var UploadWizardTaskpane = TaskPaneManager.GetTaskPane(title, title, () => new TaskPaneUploadWizard());
This is creating a CustomTaskPane not a TaskPaneUploadWizard object
It seems like this.VisibleChanged += new System.EventHandler(this.TaskPaneUploadWizard_VisibleChanged); is acting on TaskPaneUploadWizard which is only the guest of CustomTaskPane
Note that The visibility of CustomTaskPane doesn't affect TaskPaneUploadWizard
My suggestion
You remove VisibleChanged from the designer, you will add it manually in your TaskPaneUploadWizard
public partial class TaskPaneUploadWizard : UserControl
{
//{---}
CustomTaskPane _HostPane;
public CustomTaskPane HostPane
{
get => _HostPane;
set
{
if(_HostPane == value)
return;
_HostPane?.VisibleChanged -= TaskPaneUploadWizard_VisibleChanged;
_HostPane = value;
_HostPane?.VisibleChanged += TaskPaneUploadWizard_VisibleChanged;
}
}
//{---}
private void TaskPaneUploadWizard_VisibleChanged(object sender, EventArgs e)
{
// Some code
}
//{---}
Then in GetTaskPane you say
//{---}
var pane = Globals.ThisAddIn.CustomTaskPanes.Add(customTaskPane, taskPaneTitle);
(customTaskPane as TaskPaneUploadWizard).HostPane = pane;
//{---}
I am creating an app with two forms.
On my main form1 I have a scanner that gets connected through a button.
I have a text box on my form2 and in this text box is where I want the information that gets scanned to go here.
there is no textbox on my form1.
I cant seem to figure out how to do this I was wondering if any one had any tips.
Thank you
This is the code in form 1 that allows me to set up the scanner
/// Event Handler for Scanner Setup Button
/// <param name="sender"></param>
/// <param name="e"></param>
private void scannerFormBTN_Click(object sender, EventArgs e)
{
try
{
//If the Button is yellow , disconnect the hand scanner
if (scannerBTN.BackColor == Color.LightGreen)
{
scanner.ReadStringArrived -= new ReadStringArrivedHandler(OnReadStringArrived);
scanner.Disconnect();
scanner = null;
scannerFormBTN.BackColor = Color.IndianRed;
this.scannerFormBTN.Text = "Setup Hand Scanner";
MessageBox.Show("Hand Scanner Disconnected.", "Alert");
}
//If scanner is not connected
else
{
Setupscanner scannerForm = new Setupscanner(); //Instantiate the Scanner Form
//Show the form. DialogResult = yes if Scanner is connected successfully.
DialogResult connection_successfull = scannerForm.ShowDialog();
if (connection_successfull == DialogResult.Yes)
{
this.scanner = scannerForm.sys; //Set the Local Hand Scanner variable to the successfully connected scanner
if (scanner.IsConnected)
{
scanner.ReadStringArrived += new ReadStringArrivedHandler(OnReadStringArrived); //Register Read String event.
scannerFormBTN.Text = "Hand Scanner Connected. Click to Disconnect";
scannerBTN.BackColor = Color.LightGreen; //Change the color of the Hand Scanner Button
}
}
}
}
catch (Exception ex) { MessageBox.Show("There was an error. Exception reads : \n\n " + ex.Message, "Error"); }
}
/// <summary>
/// Event that gets fired when string arrives from a connected hand scanner
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void OnReadStringArrived(Object sender, ReadStringArrivedEventArgs args)
{
SetSerNumber(args.ReadString);
}
/// <summary>
/// Used to set the Serial Number to the incoming Scanner String
/// </summary>
/// <param name="msg"></param>
private void SetSerNumber(string msg)
{
//If the event is fired on a different thread than the control was created
if (Part_Code_Text_Box.InvokeRequired)
{
SetSerialNumber S = new SetSerialNumber(SetSerNumber);
this.Invoke(S, new object[] { msg }); //Invoke the delegate S on the current thread
}
else
{
Part_Code_Text_Box.Text = msg.Trim();
}
}
Create a Property Or Field in Form 2 ..let's Call It StringFromScanner For Now .
When You Want To Show another From u will most likely Create an Object From it ...Set This Object's StringFromScanner To The String You Have ..and When You Open The Second Form Will Have The value of the string in this property and u can assign it to any control
In Form 1
Form2 objectfromform2 = new Form2();
objectfromform2.StringFromScanner = MyString;
objectfromform2.Show();
in Form 2
MytextBox.Text = StringFromScanner
You Can Also Forget About The Property and Use The Constructor To Achive The Same Result
In my main window, I create a thread, which is executing a while() loop. The main tasks have two parts: receive data from socket and show it on GUI.
Now I need to show the data on another window at the same time. So I create it first like below.
ShowForm showForm = new ShowForm();
public MainWindow()
{
InitializeComponent();
mainThread();
showForm.Show();
}
And send the data to the showForm like below: (coordinateValue is generated within main window)
showForm.setter(coordinateValue);
And in the code of ShowForm.Designer.cs:
int xValue;
public void setter(int val)
{
xValue = val;
}
Now I don't know how to show the xValue on the showForm repeatedly (needs to be updated timely), e.g. a textBox or convert the xValue to coordinate and show it on a pictureBox. And in the meanwhile, the main Window's while() loop should continue to receive data and show it on its GUI.
You can create an event in your MainWindow. And subscribe to that event in your ShowForm.
Than whenever your data changes MainWindow should raise that event. Just remember that if you get the data in another thread you can't just pass it to the GUI which runs on the main thread. In that case you will want to use a Dispatcher.
You might want to use the Timer class. It can execute methods (Tick event) in even intervals.
I have wrote a sample that explains how to transfer data from one form to another using an event. If it runs in another thread you should use Invoke method in your control to prevent errors.
public partial class AdditionalForm : Form
{
private Label l_dataToShow;
public Label DataToShow { get { return l_dataToShow; } }
public AdditionalForm()
{
InitializeComponent();
SuspendLayout();
l_dataToShow = new Label();
l_dataToShow.AutoSize = true;
l_dataToShow.Location = new Point(12, 9);
l_dataToShow.Size = new Size(40, 13);
l_dataToShow.TabIndex = 0;
l_dataToShow.Text = "Data will be shown here";
Controls.Add(l_dataToShow);
ResumeLayout();
}
}
public partial class MainForm : Form
{
private AdditionalForm af;
public MainForm()
{
InitializeComponent();
SuspendLayout();
txtbx_data = new TextBox();
txtbx_data.Location = new System.Drawing.Point(12, 12);
txtbx_data.Name = "txtbx_data";
txtbx_data.Size = new System.Drawing.Size(100, 20);
txtbx_data.TabIndex = 0;
Controls.Add(txtbx_data);
ResumeLayout();
txtbx_data.TextChanged += new EventHandler(txtbx_data_TextChanged);
af = new AdditionalForm();
af.Show();
}
/// <summary>
/// The data that contains textbox will be transfered to another form to a label when you will change text in a textbox. You must make here your own event that will transfer data.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtbx_data_TextChanged(object sender, EventArgs e)
{
af.DataToShow.Text = txtbx_data.Text;
}
}
With this code:
using (pbDialog = new pbDialogs())
{
ProgressBar = new frmProgress(this, false);
ProgressBar.SetProgressLabelText("Inventory Data");
MessageBox.Show("Set progress label text to Inventory data");
typeProgress = (int) ProgressStates.ProgressQRY;
ProgressBar.label1.Text += " (Receiving)";
if (pbDialog != null)
{
MessageBox.Show("pbDialog is not null");
//pbDialog.ShowDialog(ProgressBar, this);
}
else
{
MessageBox.Show("pbDialog IS null");
ProgressBar.ShowDialog();
}
ProgressBar = null;
MessageBox.Show("Made it to compressDB()");
compressDB();
. . .
}
I see "Set progress label text to Inventory data"
then "pbDialog is not null"
then "Made it to compressDB()"
Nothing too odd there; but if I uncomment the line that is commented above, I see only "pbDialog is not null"
It is hanging for some reason as a result to the call to ShowDialog(); what is really strange, though, is that this prevents "Set progress label text to Inventory data" from displaying. Why would that be the case?
Note: I think the "pb" in the code stands for "peanut brittle" or some such; I'm pretty sure about the "brittle" part, anyway.
UPDATE
Yeah, the use of ShowDialog() with pbDialog is one of scads of examples that the original coder was practicing job security by obscurity - but then he [un]fortunately skedaddled, leaving in his wake a cesspool of spaghetti/eggshell code with no comments, misleading names and every sort of bizarre and convoluted, counterintuitive practice imaginable in the witches brew he purportedly considered a masterpiece of elegant design and clever-clever tricks.
pbDialog is an instance of a class (pbDialogs). Just to give you a taste of how macabre and convoluted and tangled it all is, here is that class:
public class pbDialogs : IDisposable
{
private static Form m_top;
public pbDialogs()
{
} // pbDialogs Constructor
public static void Activate( Form form )
{
form.Capture = true;
IntPtr hwnd = OpenNETCF.Win32.Win32Window.GetCapture();
form.Capture = false;
OpenNETCF.Win32.Win32Window.SetForegroundWindow( hwnd );
} // Activate
/// <summary>
/// This method makes ShowDialog work the way I want, I think.
/// </summary>
/// <remarks>
/// Here is what it does:
/// 1. Sets the caption of the new window to the same as the caller's.
/// 2. Clears the caption of the parent so it won't show up in the task list.
/// 3. When the ShowDialog call returns, brings the previous window
/// back to the foreground.
/// </remarks>
/// <param name="dialog"></param>
/// <param name="parent"></param>
public void ShowDialog( Form dialog, Control parent )
{
Control top = parent.TopLevelControl;
string caption = top.Text;
dialog.Text = caption;
top.Text = "--pending--"; // Don't show parent in task list
dialog.Activated += new EventHandler( form_Activated );
dialog.Closed += new EventHandler( form_Closed );
m_top = dialog; // New top-most form
dialog.ShowDialog();
m_top = (Form)top; // The top dialog just changed
dialog.Activated -= new EventHandler( form_Activated );
dialog.Closed -= new EventHandler( form_Closed );
top.Text = caption; // Make visible in task list again
Activate( (Form)top ); // And make it the active window
} // ShowDialog
/// <summary>
/// If one of our other windows, such as the main window,
/// receives an activate event, it will activate the current
/// top-most window instead.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void form_Activated( object sender, EventArgs e )
{
if( (m_top != null) && !(sender == m_top) ) // Is this the top-most window?
Activate( m_top ); // No, activate the top dialog
} // form_Activated
private static void form_Closed( object sender, EventArgs e )
{
m_top = null; // When you close the top dialog, it's not top anymore
} // form_Closed
#region IDisposable Members
public void Dispose()
{
// TODO: Add pbDialogs.Dispose implementation
}
#endregion
} // class pbDialogs
There is also a "related" ProgressBar -- a form which shares a file with pbDialogs, and whose instance variable is defined in the file that contains the code above thusly:
public static frmProgress ProgressBar;
This is definitely "whack-a-mole" code - if I make one small, seemingly innocuous change, all Dallas breaks loose in what even a semi-sane person would consider a completely unrelated part of the code.
This may be an indication of just how squirrelly this code/project is: I will make a new build after commenting out a couple of lines, and the size of the file will change from 400KB to 408, or from 412 to 408, etc. It's not normal behavior for an .exe to change that much in size (in a relative sense) with such a small change, is it?
UPATE 2
This, in frmProgress (which has both "public class frmProgress : System.Windows.Forms.Form" and "public class pbDialogs : IDisposable") scares me:
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;
The second (OpenNETCF) is grayed out, indicating it's not really used, but it may be that it was previously used, and somehow that "Windows.Forms" code inadvertently got switched to "System" code, and that may be contributing to its current groundsquirellyness.
ShowDialog is generally a blocking call. The code will not continue past this until the dialog is closed.
I must say I am pretty stumped by this and I hope some of you have perhaps encountered the same issue. I have a HyperlinkButton, created like this:
var hb = new HyperlinkButton
{
Content = fooText,
ClickMode = ClickMode.Release,
NavigateUri = new Uri(fooLink.Value)
};
hb.Click += hb_Click;
static void hb_Click(object sender, RoutedEventArgs e)
{
var btn = (HyperlinkButton)sender;
HtmlPage.Window.Navigate(btn.NavigateUri, "_blank");
}
The link is an absolute URL to a website (http://...), not inside the application. Therefore, I want to open it in a new browser tab. Which is exactly what it does! The website opens in a new tab, but in the application tab I get this error:
If I change the event handler so that there's no target parameter, like this:
HtmlPage.Window.Navigate(btn.NavigateUri);
...the error appears as well, just before the browser navigates away from the application. But I want to open a new tab.
I am using the Silverlight Business Application template from Visual Studio 11 and I've already noticed it has a few mystery bugs, this might be one of them. All in all, it works, I just need to get rid of the error message. But there is no exception thrown in the event handler that I could swallow.
You could do just this:
var hb = new HyperlinkButton
{
Content = fooText,
ClickMode = ClickMode.Release,
NavigateUri = new Uri(fooLink.Value),
TargetName = "_blank"
};
without the Click event handler.
It should do exactly what you want, in a cleaner way too.
Try it with this:
/// <summary>
/// Hyperlink button - simulates hyperlink click
/// </summary>
private class HyperlinkButtonWrapper : HyperlinkButton
{
public void OpenURL(string navigateUri)
{
OpenURL(new Uri(navigateUri, UriKind.Absolute));
}
public void OpenURL(Uri navigateUri)
{
base.NavigateUri = navigateUri;
base.TargetName = "_blank";
base.OnClick();
}
}
/// <summary>
/// Method opens url
/// <para>Example: OpenURL("http://www.google.com")</para>
/// </summary>
/// <param name="navigateUri"></param>
public static void OpenURL(string navigateUri)
{
new HyperlinkButtonWrapper().OpenURL(navigateUri);
}