c# add clickable images to gui using code and not the designer - c#

i have a folder full of images etc and i want to add them to my gui inside a tab once the program is ran.
steps:
read contents inside folder
add images to tabcontrol and assign a number to them according to in what order they were added (1) for the first picture added (2) for second etc
the images need to be added in rows of 3 with differend x values for every 3 pictures each and 1 y value change for each row of 3
[] [] []
[] [] []
[] []
doesnt need to be divideable in 3 ^ this is fine
my issue is that i didnt even find a way to add images to a gui without using the designer and im fairly new to c# so this is a huge challange for me :(
in AHK i would just gui,add,picture but it doesnt work that way in c#
help or some form of tips/guidance is very appreciated
the reason the pictures need to "have a value" on them is that once they are clicked i know which image was clicked because they should all have their click event be sent to the same function that checks what number that was and changes the value of variables accordingly
thanks for the help SO C# is overwhelming
public static void ProcessDirectory(string targetDirectory)
{
Console.WriteLine("Processed folder '{0}'.", targetDirectory);
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(targetDirectory);
foreach (string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach (string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
// Insert logic for processing found files here.
public static void ProcessFile(string path)
{
Console.WriteLine("Processed file '{0}'.", path);
if (!ImageExtensions.Contains(Path.GetExtension(path).ToUpperInvariant()))
{
Console.WriteLine("not image");
return;
}
FlowLayoutPanel flowLayoutPanel1 = new FlowLayoutPanel();
Image i = new Bitmap(path);
PictureBox p = new PictureBox();
p.Image = i;
p.Tag = "im1";
p.Click += OnImageClick; // this will let you have the same event for all of the pictures
flowLayoutPanel1.Controls.Add(p);
}
// this is what handles the clicks
private static void OnImageClick(object sender, EventArgs e)
{
MessageBox.Show("hey");
// I will leave this for you to implement... the 'sender' is the picturebox that was clicked.
// you can get it back to a PictureBox by casting, like (PictureBox)sender
// throw new NotImplementedException();
}

To add images, text, or anything else to a GUI programmatically in Winforms (which is sounds like you're using) you'll create an instance of something derived from Control and add it to the form's Controls ControlCollection. You can use a FLowLayoutPanel to give it a grid like view.
// get the list of paths to the files from your directory into an array
var fileList = Directory.GetFiles(#"C:\Images","*.jpg");
// create a flowlayout panel
FlowLayoutPanel f = new FlowLayoutPanel();
foreach (string path in fileList)
{
Image i = new Bitmap(path);
PictureBox p = new PictureBox();
p.Image = i;
p.Click += OnImageClick; // this will let you have the same event for all of the pictures
f.Controls.Add(p);
}
// add the panel to the form
this.Controls.Add(p);
// this is what handles the clicks
private void OnImageClick(object sender, EventArgs e)
{
// I will leave this for you to implement... the 'sender' is the picturebox that was clicked.
// you can get it back to a PictureBox by casting, like (PictureBox)sender
throw new NotImplementedException();
}
This implementation is quick and dirty: that is, it doesn't handle if the directory isn't found, if there aren't any files in there, etc). It should give you a good idea of where to go. I would recommend reading a lot more, getting a book about C# and walking through some examples/tutorials can be immensely helpful. You're right, C# can be overwhelming... that's why Google is your best friend! You don't need to immediately learn how to do everything; I find I learn well by choosing a small-in-scope project that I want to do and learning as I find things that I need.

This MSDN article talks about how to get all the filepaths of files in specific directory ("folder")
Their example:
// For Directory.GetFiles and Directory.GetDirectories
// For File.Exists, Directory.Exists
using System;
using System.IO;
using System.Collections;
public class RecursiveFileProcessor
{
public static void Main(string[] args)
{
foreach(string path in args)
{
if(File.Exists(path))
{
// This path is a file
ProcessFile(path);
}
else if(Directory.Exists(path))
{
// This path is a directory
ProcessDirectory(path);
}
else
{
Console.WriteLine("{0} is not a valid file or directory.", path);
}
}
}
// Process all files in the directory passed in, recurse on any directories
// that are found, and process the files they contain.
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
// Insert logic for processing found files here.
public static void ProcessFile(string path)
{
Console.WriteLine("Processed file '{0}'.", path);
}
}
This article (also MSDN) talks about adding control dynamically at run time, here is their example code:
// C#
private void button1_Click(object sender, System.EventArgs e)
{
TextBox myText = new TextBox();
myText.Location = new Point(25,25);
this.Controls.Add (myText);
}
Finally this article (again MSDN) article talks about how to set an image from a file, here is their example code:
// C#
// You should replace the bolded image
// in the sample below with an icon of your own choosing.
// Note the escape character used (#) when specifying the path.
pictureBox1.Image = Image.FromFile
(System.Environment.GetFolderPath
(System.Environment.SpecialFolder.MyPictures)
+ #"\Image.gif");
EDIT: In the comments it was asked how to wire up a control click event, since we are adding these controls programmatically we need to add the click event programmatically. For demo purposes assume there is a control with id Button1, to fire a function when it is clicked you would use code that goes something like this:
Button1.Click += new System.EventHandler(this.myEventHandler);
This will fire the function myEventHandler when Button1 is clicked
So thats a lot of code!
While it may not seem like it, if you look at each piece and consider how they all fit together, this should help you on the right path to (big hint), dynamically get a list of images, add an image control to your page, then set that image control to display a specific image, and finally wire up a click event on an image control

You can use Image.Tag property to add extra information to the image.

Related

Getting resources Image path from Picturebox [duplicate]

I have a program which has 16 grid tiles using picturebox but only uses 5 images, the rest of the tiles are just a black image.
I would like to be able to tell which image the 'user' clicks on.
I have a method called image_Click(object sender, EventArgs e)
I have an if statement inside this method that states:
if (peckedSquare.BackColor == Color.Black)
{
System.Diagnostics.Debug.WriteLine("Pecked a black square");
return;
}
This sends a String that lets me know when a black square has been clicked.
Is there an easy way to perhaps say:
//pseudo code:
if (peckedSquare.ImageName == pigeon1.png)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I have googled my query but I have not found any suitable answers.
//EDIT
I have just re-read my code.
I was assigning each picture to a picturebox square using a randomnumber.
I had this random number as a variable, so I can just use that variable to determine which image was clicked.
ie.
if (randomNumber == 1)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
or better than that
pigeonSelected = randomNumber + 1 //as I am using an array to store the images
System.Diagnostics.Debug.WriteLine("Pecked Pigeon Number {0}", pigeonSelected);
As quick & dirty solution I would use Tag property for that, null for black tiles and file path for the others (and it's always available, even if your image comes from resources), something like this:
if (peckedSquare.Tag == null)
{
Debug.WriteLine("Pecked a black square");
}
else
{
switch (Path.GetFileName(peckedSquare.Tag.ToString()))
{
case "pigeon1.png":
break;
}
}
Of course when you create tiles you have to store file path in Tag:
PictureBox tile = new PictureBox();
tile.Image = Image.FromFile(path); // Or another source, of course
tile.Tag = path;
As alternative you may even use Name property for this, each control is named (primary for designer-code integration) but if you create controls at run-time you can set that value to anything you want (not only valid identifiers). Same usage as above just no need to call ToString().
How to Improve?
Please let me say this solution is not very OOP. Even without a big refactoring we can do little bit better. Note that you can store whatever you want in Tag property. A number, a simple string unrelated to file name or even (maybe better) a class or an enum that represents that image (to delegate action to that object). This is a very raw example:
abstract class Tile {
public abstract void Activate();
}
sealed class EmptyTile : Tile {
public virtual void Activate() {
Debug.WriteLine("Pecked a black square");
}
}
sealed class ImageTile : Tile {
public ImageTile(string content) {
_content = content;
}
public virtual void Activate() {
Debug.WriteLine(_content);
}
private string _content;
}
In this way in your click event handler you can do this:
((Tile)peckedTile.Tag).Activate();
No need to check what's inside or to compare with null. No if and no switch, just don't forget to put proper object (ImageTile or BlackTile) when you create tiles.
Use PictureBox.Load(string) method to load images from file. Then the file path will be stored in the
PictureBox.ImageLocation property:
A call to the Load method will overwrite the ImageLocation property, setting ImageLocation to the URL value specified in the method call.
So you can write for example:
if (peckedSquare.ImageLocation.EndsWith("pigeon1.png"))
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I think you could do something like the following:
private List<PictureBox> pictures = null;
string[] ImageNames = new string[]
{
"images\\test_1.jpg",
"images\\test_2.jpg"
};
private void Form1_Load(object sender, EventArgs e)
{
pictures = new List<PictureBox>();
for (var idx = 0; idx < ImageNames.Length; idx++)
{
pictures.Add(new PictureBox());
pictures[idx].Image = new Bitmap(ImageNames[idx]);
pictures[idx].Click += OnClick;
// you'll want to set the offset and everything so it shows at the right place
Controls.Add(pictures[idx]);
}
}
private void OnClick(object sender, EventArgs eventArgs)
{
// you'll definitely want error handling here
var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
}
You can see that in the click method you will be able to get the image name, which is what you are looking for I believe.
As others have said, you can also use the "Tag" property assuming you weren't already using this for some other purpose. The nice thing about tag is you can probably also edit it through the form designer which allows you to lay things out a little more nicely than the automatic layout I used above. Good luck!
You can do something like this using the Tag property like #Adriano suggested:
public Form1()
{
InitializeComponent();
pictureBox1.Click += pictureBox_Click;
pictureBox2.Click += pictureBox_Click;
pictureBox3.Click += pictureBox_Click;
// ...
pictureBox1.Tag = "picture1.png";
pictureBox2.Tag = "picture2.png";
pictureBox3.Tag = "picture3.png";
}
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (pb.BackColor != Color.Black)
Debug.WriteLine(pb.Tag.ToString());
else
Debug.WriteLine("Black image");
}

How do you access the name of the image in a picturebox in Visual Studio using C#

I have a program which has 16 grid tiles using picturebox but only uses 5 images, the rest of the tiles are just a black image.
I would like to be able to tell which image the 'user' clicks on.
I have a method called image_Click(object sender, EventArgs e)
I have an if statement inside this method that states:
if (peckedSquare.BackColor == Color.Black)
{
System.Diagnostics.Debug.WriteLine("Pecked a black square");
return;
}
This sends a String that lets me know when a black square has been clicked.
Is there an easy way to perhaps say:
//pseudo code:
if (peckedSquare.ImageName == pigeon1.png)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I have googled my query but I have not found any suitable answers.
//EDIT
I have just re-read my code.
I was assigning each picture to a picturebox square using a randomnumber.
I had this random number as a variable, so I can just use that variable to determine which image was clicked.
ie.
if (randomNumber == 1)
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
or better than that
pigeonSelected = randomNumber + 1 //as I am using an array to store the images
System.Diagnostics.Debug.WriteLine("Pecked Pigeon Number {0}", pigeonSelected);
As quick & dirty solution I would use Tag property for that, null for black tiles and file path for the others (and it's always available, even if your image comes from resources), something like this:
if (peckedSquare.Tag == null)
{
Debug.WriteLine("Pecked a black square");
}
else
{
switch (Path.GetFileName(peckedSquare.Tag.ToString()))
{
case "pigeon1.png":
break;
}
}
Of course when you create tiles you have to store file path in Tag:
PictureBox tile = new PictureBox();
tile.Image = Image.FromFile(path); // Or another source, of course
tile.Tag = path;
As alternative you may even use Name property for this, each control is named (primary for designer-code integration) but if you create controls at run-time you can set that value to anything you want (not only valid identifiers). Same usage as above just no need to call ToString().
How to Improve?
Please let me say this solution is not very OOP. Even without a big refactoring we can do little bit better. Note that you can store whatever you want in Tag property. A number, a simple string unrelated to file name or even (maybe better) a class or an enum that represents that image (to delegate action to that object). This is a very raw example:
abstract class Tile {
public abstract void Activate();
}
sealed class EmptyTile : Tile {
public virtual void Activate() {
Debug.WriteLine("Pecked a black square");
}
}
sealed class ImageTile : Tile {
public ImageTile(string content) {
_content = content;
}
public virtual void Activate() {
Debug.WriteLine(_content);
}
private string _content;
}
In this way in your click event handler you can do this:
((Tile)peckedTile.Tag).Activate();
No need to check what's inside or to compare with null. No if and no switch, just don't forget to put proper object (ImageTile or BlackTile) when you create tiles.
Use PictureBox.Load(string) method to load images from file. Then the file path will be stored in the
PictureBox.ImageLocation property:
A call to the Load method will overwrite the ImageLocation property, setting ImageLocation to the URL value specified in the method call.
So you can write for example:
if (peckedSquare.ImageLocation.EndsWith("pigeon1.png"))
{
System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
I think you could do something like the following:
private List<PictureBox> pictures = null;
string[] ImageNames = new string[]
{
"images\\test_1.jpg",
"images\\test_2.jpg"
};
private void Form1_Load(object sender, EventArgs e)
{
pictures = new List<PictureBox>();
for (var idx = 0; idx < ImageNames.Length; idx++)
{
pictures.Add(new PictureBox());
pictures[idx].Image = new Bitmap(ImageNames[idx]);
pictures[idx].Click += OnClick;
// you'll want to set the offset and everything so it shows at the right place
Controls.Add(pictures[idx]);
}
}
private void OnClick(object sender, EventArgs eventArgs)
{
// you'll definitely want error handling here
var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
}
You can see that in the click method you will be able to get the image name, which is what you are looking for I believe.
As others have said, you can also use the "Tag" property assuming you weren't already using this for some other purpose. The nice thing about tag is you can probably also edit it through the form designer which allows you to lay things out a little more nicely than the automatic layout I used above. Good luck!
You can do something like this using the Tag property like #Adriano suggested:
public Form1()
{
InitializeComponent();
pictureBox1.Click += pictureBox_Click;
pictureBox2.Click += pictureBox_Click;
pictureBox3.Click += pictureBox_Click;
// ...
pictureBox1.Tag = "picture1.png";
pictureBox2.Tag = "picture2.png";
pictureBox3.Tag = "picture3.png";
}
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (pb.BackColor != Color.Black)
Debug.WriteLine(pb.Tag.ToString());
else
Debug.WriteLine("Black image");
}

Refresh C# listbox when change in Loaded Text file

Ok I know similar questions have been asked, But I am trying to have a Listbox monitor a text file that is changed by another program. I have it setup to select the top line in the file, and execute a command based off that line, then it deletes top line. I just need the listbox to refresh after deletion and read new top line and continue to read until null. I am also having it monitor if the serialPort is OPEN or not. ( I want it to only loop if the serial Port is closed). I am fairly new to C# so any help is appreciated. My current code:
public partial class Form1 : Form
{
List<string> myList = new List<string>();
public Form1()
{
InitializeComponent();
myList = System.IO.File.ReadLines("textfile").ToList();
this.GPSCOM.DataSource = myList;
GPSCOM.SelectionMode = SelectionMode.One;
myList.FirstOrDefault();
GPSCOM.SetSelected(0, true);
if (serialPort.IsOpen)
{
return;
}
else
{
for(;;)
{
switch ((string)GPSCOM.SelectedItem)
{
case "set1":
var lines = System.IO.File.ReadAllLines("textfile");
System.IO.File.WriteAllLines("textfile", lines.Skip(1).ToArray());
return;
case "set2":
var lines1 = System.IO.File.ReadAllLines("textfile");
System.IO.File.WriteAllLines("textfile", lines1.Skip(1).ToArray());
return;
case "set3":
var lines2 = System.IO.File.ReadAllLines("textfile");
System.IO.File.WriteAllLines("textfile", lines2.Skip(1).ToArray());
return;
}
}
}
}
A FileSystemWatcher would be your best bet.
I would like to ask however if it would be inconvenient to make the other program output to its standard output stream and use ProcessStartInfo in System.Diagnosics to redirect the output. If would be a faster and more direct solution as the data could be moved directly between the two programs instead of using the less indirect file storage method. Cut out the middle man as it were.
You would be better off using a FileSystemWatcher and catching the change notification than continuously polling the contents of the file.

how to burn the files selected from listview in a dvd using c#.net code?

can any expert help me out to solve a problem of burning a dvd using c#.net as a front end??
i need to select files from the listview in winform and then on button click i need to burn those multiple files in the dvd..
the concept is to select the multiple files from listview then on button click it should make a folder in some desired drive.. and then it should burn that complete folder in the dvd..this whole process should be performed during a single button click....
is there any way out??
the code should be compatible to use in .net2008 and windowsXP are the given codes compatible??
im using the componenet to get the dll/class lib. from (msdn.microsoft.com/en-au/vcsharp/aa336741.aspx) but its giving me error message "there are no components in d:\filepath\burncomponent.dll to be placed on the toolbox
private void button1_Click(object sender, EventArgs e)
{
XPBurnCD cd = new XPBurnCD();
cd.BurnComplete += new NotifyCompletionStatus(BurnComplete);
MessageBox.Show(cd.BurnerDrive);
DirectoryInfo dir = new DirectoryInfo(_burnFolder);
foreach (FileInfo file in dir.GetFiles())
{
cd.AddFile(file.FullName, file.Name);
}
cd.RecordDisc(false, false);
}
private void BurnComplete(uint status)
{
MessageBox.Show("Finished writing files to disc");
}
private void button2_Click_1(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.ShowNewFolderButton = false;
fbd.Description = "Please select a folder";
fbd.RootFolder = System.Environment.SpecialFolder.DesktopDirectory;
if (fbd.ShowDialog() == DialogResult.OK)
{
_burnFolder = fbd.SelectedPath;
}
else
{
_burnFolder = string.Empty;
}
}
Check out http://msdn.microsoft.com/en-au/vcsharp/aa336741.aspx
One simple approach could be to use the command line tools dvdburn and cdburn, which are belonging to XP. For example take a look at this site.
Update
Yes, it is a console application, but you can start it within a .Net Application by using the Process class. And here you should especially take a deeper look into the StartInfo property and its members, cause here you can set the parameters or redirect the output into your program to get informations about what the program is doing.

Getting filesize from OpenFileDialog?

How can I get the filesize of the currently-selected file in my Openfiledialog?
You can't directly get it from the OpenFieldDialog.
You need to take the file path and consturct a new FileInfo object from it like this:
var fileInfo = new FileInfo(path);
And from the FileInto you can get the size of the file like this
fileInfo.Length
For more info look at this msdn page.
Without interop and like the first comment, once the dialogue has been complete i.e. file/s have been selected this would give the size.
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (openFileDialog1.Multiselect)
{
long total = 0;
foreach (string s in openFileDialog1.FileNames)
total += new FileInfo(s).Length;
MessageBox.Show(total.ToString());
}
else
{
MessageBox.Show(new FileInfo(openFileDialog1.FileName).Length.ToString());
}
}
}
File size during dialogue I feel would need to use interop
Andrew
I think there is 3 way, creating your custom open dialog or setting by code the view as detail or asking the user to use detail view
If you mean when the dialog is running, I suspect you just change the file view to details. However if you mean programmatically I suspect that you'd have to hook a windows message when the file is selected.

Categories