C# edit property of panel using run-time generated button - c#

I'm a complete noob in C# programming. This is my problem: I have a form with a panel that is generated upon clicking button 1, the panel also containes a button (btnColor1) to change the backcolor of the panel. I would like to refer to the panel's backcolor in btnColor1, but I get the error "The name 'btnColor1' does not exist in the current context". How can I fix this?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TEST_APP_1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Panel myPanel1 = new Panel();
myPanel1.Location = new System.Drawing.Point(100, 50);
myPanel1.Name = "Panel 1";
myPanel1.Size = new System.Drawing.Size(200, 100);
myPanel1.BackColor = Color.Red;
TextBox textBox1 = new TextBox();
textBox1.Location = new Point(10, 50);
textBox1.Text = "empty field";
textBox1.Size = new Size(150, 30);
Button btnColor1 = new Button();
btnColor1.Location = new Point(10, 10);
btnColor1.Text = "GOLD";
btnColor1.Size = new Size(100, 30);
btnColor1.Click += myButton1_Click;
myPanel1.Controls.Add(textBox1);
myPanel1.Controls.Add(btnColor1);
Controls.Add(myPanel1);
}
private void myButton1_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
btnColor1.BackColor = Color.Gold;
}
}
}

btnColor1 is declared in the scope of the button1_Click method so does not exist as a variable to reference in your event handler. Change the event handler to this:
private void myButton1_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
(sender as Button).BackColor = Color.Gold;
}

You can try to use the parent property of the button to access the panel and the form:
private void myButton1_Click(object sender, EventArgs e)
{
Button but = (sender as Button);
but.BackColor = Color.Gold;
// this changes the color of the panel
but.Parent.BackColor = Color.Gold;
// this changes the color of the form containing the panel
if (but.Parent.Parent != null)
{
but.Parent.Parent.BackColor = Color.Gold;
}
}

Related

How to disable the automatic selection of the first item in ComboBox?

I have a form with a ComboBox, which is populated with 3 items.
When I add the statements: comboBox1.Text = "A"; and comboBox1.DroppedDown = true;
the first item of the drop-down list is automatically selected: the comboBox1.Text shows "Abc" in stead of "A".
Here is the code:
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;
namespace testComboBox
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1 = new ComboBox();
PopulateComboBox();
comboBox1.Location = new Point((this.Width - comboBox1.Width) / 2, 80);
this.Controls.Add(comboBox1);
comboBox1.Text = "A";
comboBox1.DroppedDown = true;
}
ComboBox comboBox1;
private void PopulateComboBox()
{
comboBox1.Items.Add("Abc");
comboBox1.Items.Add("Abcd");
comboBox1.Items.Add("Abcde");
}
private void button_Exit_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
How can I disable the automatic selection of the first item in the Items collection of the ComboBox, so that the comboBox1.Text will show "A" and not "Abc"?
I am not looking for a one-time work-around. I need a GENERAL SOLUTION.
set this code comboBox1.SelectedText = null;
public Form1()
{
InitializeComponent();
comboBox1 = new ComboBox();
PopulateComboBox();
comboBox1.Location = new Point((this.Width - comboBox1.Width) / 2, 80);
this.Controls.Add(comboBox1);
comboBox1.SelectedText = "A";
comboBox1.DroppedDown = true;
comboBox1.SelectedText = null;
}
With the help of the thread that Loathing pointed to, I copied the extension Class ComboBoxAutoSelectExtension and in the form I just added the line of code: ComboBoxAutoSelectExtension.AutoSelectOff(comboBox1);
If you copy the ComboBoxAutoSelectEx from the link in the comment, then the only thing you should have to do in your own Form1 code is:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1 = new ComboBox();
String text = "A";
comboBox1.Text = text;
comboBox1.Select(text.Length,1); // put cursor at the end of text
ComboBoxAutoSelectEx.AutoSelectOff(comboBox1); // Added
PopulateComboBox();
comboBox1.Location = new Point((this.Width - comboBox1.Width) / 2, 80);
this.Controls.Add(comboBox1);
}
protected override void OnLoad(EventArgs e) { // Added
base.OnLoad(e);
comboBox1.DroppedDown = true;
}
ComboBox comboBox1;
private void PopulateComboBox()
{
comboBox1.Items.Add("Abc");
comboBox1.Items.Add("Abcd");
comboBox1.Items.Add("Abcde");
}
private void button_Exit_Click(object sender, EventArgs e)
{
this.Close();
}
}
I see no way to disable auto selection of an item. I can only replace the wrong selection with the input text that was previously known. This bug occurs on both opening or closing the dropdown. Here is an example code when opening the dropdown.
// record
box_txt = comboBox1.Text;
box_pos = comboBox1.SelectionStart;
// drop down
comboBox1.DroppedDown = true;
// replace
comboBox1.Text = box_txt;
comboBox1.SelectionStart = box_pos;

why can't I add a new List object in button event

why can't I add a new item/object to my list in button (or combobox etc.) events? I mean, the events don't see my list if it's outside of the brackets...it's underlined in red... can you help me?
long story short: i want to add a new object by clicking the button
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
namespace Samochody
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
List<Samochod> ListaSamochodow = new List<Samochod>();
comboBox1.DataSource = ListaSamochodow;
comboBox1.DisplayMember = "Marka";
XmlRootAttribute oRootAttr = new XmlRootAttribute();
XmlSerializer oSerializer = new XmlSerializer(typeof(List<Samochod>), oRootAttr);
StreamWriter oStreamWriter = null;
oStreamWriter = new StreamWriter("samochody.xml");
oSerializer.Serialize(oStreamWriter, ListaSamochodow);
}
private void button1_Click(object sender, EventArgs e)
{
try
{
ListaSamochodow.Add(new Samochod(textBox1.Text, textBox2.Text, Convert.ToInt32(textBox3.Text)));
}
catch (Exception oException)
{
Console.WriteLine("Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
}
}
I think you should instantiate your list globally and not under Form1_Load event.
that way it will be accessible all around your class (the window in this case).
This seems to work fine. You might need to set your textboxes to contain valid values when you start the form. also make sure that you make the list visible throughout your form1 class.
namespace Samochody
{
public partial class Form1 : Form
{
// make sure your list looks like this, created outside your functions.
List<Samochod> ListaSamochodow = new List<Samochod>();
public Form1()
{
InitializeComponent();
label1.Text = "the amount in your list is " + ListaSamochodow.Count.ToString();
textBox1.Text = "string here";
textBox2.Text = "string here";
textBox3.Text = "100";
}
private void Form1_Load(object sender, EventArgs e)
{
XmlRootAttribute oRootAttr = new XmlRootAttribute();
XmlSerializer oSerializer = new XmlSerializer(typeof(List<Samochod>), oRootAttr);
StreamWriter oStreamWriter = null;
oStreamWriter = new StreamWriter("samochody.xml");
oSerializer.Serialize(oStreamWriter, ListaSamochodow);
}
private void button1_Click_1(object sender, EventArgs e)
{
Samochod s = new Samochod(textBox1.Text, textBox2.Text, Convert.ToInt32(textBox3.Text));
ListaSamochodow.Add(s);
label1.Text = "the amount in your list is " + ListaSamochodow.Count.ToString();
}
}
}

c# how to add text line to Textboxes created dynamically on every text change

I'm using a FileSystemWatcher to watch file text for any changes and display its data in a text box and alert the user when changes are done by changing the form color to red and play a beep sound; the color turns to normal when the user clicks inside the Textbox.
This is my first attempt and it worked fine:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Media;
namespace Breacking_News
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
{
string file_name = ("\\\\172.200.10.5\\txt\\عاجل.txt");
FileStream logFileStream = new FileStream(file_name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader logFileReader = new StreamReader(logFileStream);
while (!logFileReader.EndOfStream)
{
string news = logFileReader.ReadToEnd();
textBox1.Text = news.Replace(System.Environment.NewLine, "\r\n ************************************************ \r\n");
infoText.Text = ("Last update at : " + DateTime.Now);
}
// Clean up
logFileReader.Close();
logFileStream.Close();
}
private void textBox1_Click(object sender, EventArgs e)
{
this.BackColor = DefaultBackColor;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Normal;
//FormWindowState.Normal = true;
this.BackColor = System.Drawing.Color.Red;
System.Media.SystemSounds.Beep.Play();
}
}
}
Now I would like to improve on that so each line will be displayed in a separate Textbox. Knowing that I don't know how many lines the text file contains, I will create the TextBoxes dynamically using this code.
I tested this code alone and it worked fine. Each line is displayed in a single Textbox:
string file_name = ("\\\\172.200.10.5\\txt\\عاجل.txt");
var linecount = File.ReadLines(file_name).Count();
TextBox[] txtBoxes = new TextBox[linecount];
for (int i = 0; i < txtBoxes.Length; i++)
{
string[] lines = File.ReadAllLines(file_name);
var txt = new TextBox();
txtBoxes[i] = txt;
txt.Name = ("TextBox" + i);
txt.Text = lines.ElementAtOrDefault(i);
txt.Location = new Point(50, 32 + (i * 110));
txt.Visible = true;
txt.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
txt.Multiline = true;
txt.ReadOnly = true;
txt.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
txt.Size = new System.Drawing.Size(440, 100);
this.Controls.Add(txt);
}
The problem is that when I insert the second method into the while loop from the first code:
while (!logFileReader.EndOfStream)
When I run the program, the text boxes are created dynamically for the first text change. But when there is new change on a text file, the text boxes created do not take changes.

Variable not updating on closing a new pop up form after clicking button

I am trying to make a button that when clicked pops up a new form with a yes and no button and then make an if statement based on what button is pressed. Here is my current code:
private YesNoMessageBoxResized newBoxResized;
private string buttonClickResult;
public void YesNoNewMessageBox(string title, string message,string buttonYes, string buttonNo)
{
YesNoMessageBoxResized msgResized = new YesNoMessageBoxResized(title, message, buttonYes, buttonNo);
msgResized.StartPosition = FormStartPosition.CenterScreen;
msgResized.TopMost = true;
Button yesButtonResize = new Button();
Button noButtonResize = new Button();
//yes button
yesButtonResize.Text = buttonYes;
yesButtonResize.Size = new Size(150, 80);
yesButtonResize.Font = new Font("Arial", 26);
yesButtonResize.Location = new Point(100, 150);
//no button
noButtonResize.Text = buttonNo;
noButtonResize.Size = new Size(150, 80);
noButtonResize.Font = new Font("Arial", 26);
noButtonResize.Location = new Point(300, 150);
//make a copy of the current form
newBoxResized = msgResized;
//eventhandlers
yesButtonResize.Click += YesButtonResizeClicked;
noButtonResize.Click += noButtonResizeClicked;
newBoxResized.Controls.Add(yesButtonResize);
newBoxResized.Controls.Add(noButtonResize);
msgResized.Show();
}
private void YesButtonResizeClicked(object o, EventArgs sEA)
{
this.buttonClickResult = "true";
this.newBoxResized.Close();
}
private void noButtonResizeClicked(object o, EventArgs sEA)
{
this.buttonClickResult = "false";
this.newBoxResized.Close();
}
private void buttonRestoreDefaults_Click(object sender, EventArgs e)
{
YesNoNewMessageBox("Restore Defaults?", "Restore Defaults?", "Yes", "No");
if (this.buttonClickResult == "true")
this.restoreDefaults();
}
My problem is that after hitting yes and closing the form that pops up, buttonClickResult is not seen as true and therefore the restore default function I am calling is not called. Only when clicking on the "RestoreDefaults" button again is the function called. So, it seems that the onclick event for buttonRestoreDefaults_Click isn't reconizing the onclick for the yes or no buttons in the form that popups until clicking on it again. Is there a way around this or some sort of implementation to fix this? Thank you.
Also, here is the code for the class. I was thinking about using delegates and event handlers, but I am not sure if I actually need that since what I have works, but just doesn't update the variable on closing correctly:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class YesNoMessageBoxResized : Form
{
private Label labelMessage;
//no default button specified
public YesNoMessageBoxResized(string title, string message, string buttonYes, string buttonNo)
{
InitializeComponent();
this.Text = title;
this.labelMessage.Text = message;
this.Deactivate += MyDeactivateHandler;
}
public YesNoMessageBoxResized()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.labelMessage = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// labelMessage
//
this.labelMessage.AutoSize = true;
this.labelMessage.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelMessage.Location = new System.Drawing.Point(12, 31);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(165, 29);
this.labelMessage.TabIndex = 3;
this.labelMessage.Text = "labelMessage";
//
// YesNoMessageBoxResized
//
this.ClientSize = new System.Drawing.Size(572, 268);
this.Controls.Add(this.labelMessage);
this.Name = "YesNoMessageBoxResized";
this.ResumeLayout(false);
this.PerformLayout();
}
protected void MyDeactivateHandler(object sender, EventArgs e)
{
this.Close();
}
public delegate void buttonYes_ClickResultEvent(object o, EventArgs sEA);
public event buttonYes_ClickResultEvent choiceResult;
}
public class buttonYes_ClickResultEvent : EventArgs
{
public buttonYes_ClickResultEvent(bool choice)
{
this.buttonResult = choice;
}
public bool buttonResult;
}
**I posted this on codereview, but then they told me to post it here since it deals with solving a problem.
just for a test, try using a global variable and set that to true within your yesbuttonresizedclicked event.
something like
public static bool yestest = false;
private void YesButtonResizeClicked(object o, EventArgs sEA)
{
yestest = true;
}
I sort of fixed it by adding a function that had the if statement withing the other button events. I am open to other solutions though:
private YesNoMessageBoxResized newBoxResized;
private string buttonClickResult;
public void YesNoNewMessageBox(string title, string message,string buttonYes, string buttonNo)
{
YesNoMessageBoxResized msgResized = new YesNoMessageBoxResized(title, message, buttonYes, buttonNo);
msgResized.StartPosition = FormStartPosition.CenterScreen;
msgResized.TopMost = true;
Button yesButtonResize = new Button();
Button noButtonResize = new Button();
//yes button
yesButtonResize.Text = buttonYes;
yesButtonResize.Size = new Size(150, 80);
yesButtonResize.Font = new Font("Arial", 26);
yesButtonResize.Location = new Point(100, 150);
//no button
noButtonResize.Text = buttonNo;
noButtonResize.Size = new Size(150, 80);
noButtonResize.Font = new Font("Arial", 26);
noButtonResize.Location = new Point(300, 150);
//make a copy of the current form
newBoxResized = msgResized;
//eventhandlers
yesButtonResize.Click += YesButtonResizeClicked;
noButtonResize.Click += noButtonResizeClicked;
newBoxResized.Controls.Add(yesButtonResize);
newBoxResized.Controls.Add(noButtonResize);
newBoxResized.Show();
}
private void YesButtonResizeClicked(object o, EventArgs sEA)
{
this.buttonClickResult = "true";
this.DoIfStatement();
this.newBoxResized.Close();
}
private void noButtonResizeClicked(object o, EventArgs sEA)
{
this.buttonClickResult = "false";
this.DoIfStatement();
this.newBoxResized.Close();
}
private void DoIfStatement()
{
if (buttonClickResult == "true")
this.restoreDefaults();
}
private void buttonRestoreDefaults_Click(object sender, EventArgs e)
{
YesNoNewMessageBox("Restore Defaults?", "Restore Defaults?", "Yes", "No");
}
I think I need it to be more modular though. I don't always want the same if statement there. So, I don't always want to be a yes and no with regards to restore defaults. I may want it to do something else with another function call and have yes and no buttons do something else.
You can just use MessageBox to do this for you:
if (MessageBox.Show("Yes or no?", "", MessageBoxButtons.YesNo)
== DialogResult.Yes)
You could change the form to a modal dialog form. Make the Accept and Cancel buttons properties equal the appropriate button. Then change the dialog result of each button to the appropriate value. Now when you use the ShowDialog the form will return the appropriate DialogResult.

C# Embed Image in New Outlook Mail Item from Standalone Application

What is the best way of embedding an image into a new outlook mail item from a Stand Alone application. Not building an add-in for outlook.
Trying to embed or attach an existing picture to a new email item. I have read and looked at a lot of sources but most of these are tied into exchange or by using AddIn methods in Outlook.
User would see the image embedded into the new email and would just need to fill out the "To:" field. Would like to make the subject pre-populated in new email message as well from application.
Code Below: (I am trying to attach the picture that I capture below to an outlook email!
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.IO;
using System.Net.Mail;
using System.Net.Mime;
namespace While_You_Were_Out
{
public partial class main : Form
{
public main()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WindowState = FormWindowState.Normal;
Show();
Rectangle l = Screen.PrimaryScreen.WorkingArea;
//Sets Position Manual all other Dialogs are set within parent center area.
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - this.Width, Screen.PrimaryScreen.WorkingArea.Height - this.Height);
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
new AboutDialog().ShowDialog(this);
}
private void trayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
WindowState = FormWindowState.Normal;
Show();
Rectangle l = Screen.PrimaryScreen.WorkingArea;
//Sets Position Manual all other Dialogs are set within parent center area.
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - this.Width, Screen.PrimaryScreen.WorkingArea.Height - this.Height);
}
private void trayRightClickMenu2_Opening(object sender, CancelEventArgs e)
{
}
private void toolStripMenuExit_Click(object sender, EventArgs e)
{
//Exit Application
Application.Exit();
}
private void toolStripMenuOpen1_Click(object sender, EventArgs e)
{
WindowState = FormWindowState.Normal;
Show();
Rectangle l = Screen.PrimaryScreen.WorkingArea;
//Sets Position Manual all other Dialogs are set within parent center area.
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - this.Width, Screen.PrimaryScreen.WorkingArea.Height - this.Height);
}
private void button1_Click(object sender, EventArgs e)
{
//Hides to System Tray
this.Hide();
trayIcon.Visible = true;
//Dispose();
}
private void button2_Click(object sender, EventArgs e)
{
}
private void sendNotificationToolStripMenuItem_Click(object sender, EventArgs e)
{
/* Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
bmp.Save(#"C:\Razor\wywo_notification.jpg");
bmp.Dispose();*/
SaveAsBitmap(panel1, #"C:\Users\Razor\wywo_notification.jpg");
}
private void clearFormToolStripMenuItem_Click(object sender, EventArgs e)
{
txtBox6.Text = string.Empty;
txtBox8.Text = string.Empty;
txtBox9.Text = string.Empty;
}
public void SaveAsBitmap(Control control, string fileName)
{
//get the instance of the graphics from the control
Graphics g = control.CreateGraphics();
//new bitmap object to save the image
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
//Drawing control to the bitmap
panel1.DrawToBitmap(bmp, new Rectangle(0, 0, control.Width, control.Height));
bmp.Save(fileName);
bmp.Dispose();
}
private void sendToOutlook_Click(object sender, EventArgs e)
{
}
}
}
I was able to perform the function with VBS Script:
Set olApp = CreateObject("Outlook.Application")
Set olMsg = olApp.CreateItem(0)
With olMsg
.To = "test#test.com"
'.CC = "cc#test.com"
'.BCC = "bcc#test.com"
.Subject = "Subject"
.HTMLBody = "<html><p>This is a picture.</p>" & _
"<img src='cid:wywo_notification.jpg'>"
'.Body = "<IMG align=baseline border=0 hspace=0 src=cid:myident>"
'.Attachments.Add "C:\users\doej\wywo_notification.jpg"
'.Attachments.Add "C:\users\doej\wywo_notification.jpg"
.Display
End With
I was able to solve my problem by relying on an VBS script called from within the application it was simple and solved my issue.
Create an attachment and set the PR_ATTACH_CONTENT_ID property (DASL name "http://schemas.microsoft.com/mapi/proptag/0x3712001F") using Attachment.PropertyAccessor.
Your HTML body would then need to reference that image attachment through the cid:
img src="cid:xyz"
where xyz is the value of the PR_ATTACH_CONTENT_ID property.
Look at an existing message with OutlookSpy (I am its author - click IMessage button).

Categories