I have 4 Picture box loading images. I want to select these images based on mouse click. For example If I click images from picturebox 1 and 2, I want to get images from these picturebox 1 and 2 only.The function look like Gallery in Android phones.
it is not very difficult. create pictureBoxes dynamically, add them the same Click handler and store images from selected pictureBox
e.g. gallery form (last picture is selected)
public partial class GalleryForm : Form
{
// stores selected images in order of adding
private readonly List<Image> _gallery = new List<Image>();
private readonly Random _rnd = new Random();
// handle pics layout on form
private readonly FlowLayoutPanel flowPanel;
public GalleryForm()
{
InitializeComponent();
Name = "GalleryForm";
Text = "Gallery";
ClientSize = new Size(276, 274);
// flowPanel will contain picture boxes with images
flowPanel = new FlowLayoutPanel();
flowPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left| AnchorStyles.Right;
flowPanel.Location = new Point(12, 12);
flowPanel.Name = "flowPanel";
flowPanel.Size = new Size(252, 250);
int picsCount = 4;
var picSize = new Size(100, 100);
var imSize = new Size(50, 50);
// creates required number of picture boxes with simple images
for (int p = 0; p < picsCount; p++)
{
var picBox = new PictureBox();
picBox.Name = "pic" + (p+1).ToString();
picBox.Size = picSize;
picBox.SizeMode = PictureBoxSizeMode.Zoom;
picBox.Image = GetImage(p, imSize);
picBox.Click += ClickOnImage;
flowPanel.Controls.Add(picBox);
}
Controls.Add(flowPanel);
}
// click handler
private void ClickOnImage(object sender, EventArgs eventArgs)
{
var picBox = (PictureBox) sender;
if (_gallery.Remove(picBox.Image))
// if _gallery contained image, remove selection
picBox.BorderStyle = BorderStyle.None;
else
{
// add selection
picBox.BorderStyle = BorderStyle.Fixed3D;
// add image to _gallery
_gallery.Add(picBox.Image);
}
}
// creates image with solid background
private Bitmap GetImage(int p, Size s)
{
var bmp = new Bitmap(s.Width, s.Height);
using (Graphics gr = Graphics.FromImage(bmp))
gr.Clear(Color.FromArgb(_rnd.Next(255), _rnd.Next(255), _rnd.Next(255)));
return bmp;
}
}
Related
I have some pictures in a database which I retrieve them . To load these pictures, I made a "Tab Control" in Windows Form, which has a "Tab page1". when the program runs, a group box, containing a PictureBox (and some other text boxes), will be created for each picture. my pictures can be load in these picture boxes, and I will have a list of group boxes(gbList). However, I can not select these pictures during the run. Can anybody suggest a solution?
private void Form2_Load(object sender, EventArgs e)
{
tabPage1.Controls.Clear();
int x = 0, y = 0;
int j = 0;
for (int i = 0; i < output.Count - 1; i++)
{
PictureBox pic = new PictureBox();
pic.SizeMode = PictureBoxSizeMode.StretchImage;
SelectablegroupBox gb = new SelectablegroupBox();
gb.Controls.Add(pic);
gbList.Add(gb);
//to retrieve the images from the database in ProductImages class: (output is the result of a query of database)
ProductImages pI = output[i];
imgbyte = pI.Pic;
using (MemoryStream ms = new MemoryStream(imgbyte))
{
Image img = Image.FromStream(ms);
pic.Image = img;
}
//to add the group box list o the tabpage:
tabPage1.Controls.Add(gbList[j]);
gbList[j].Location = new Point(x, y);
y += gbList[i].Height;
j++;
}
here is my problem. I want the user to be able to select the images (Then I want to save these selected Items). But the "result" is always empty:
var result = from s in gbList
where s.Focused ==true
select s;
foreach (var s in result)
{ //save the selected images}
As I learned from another post, I defined SelectablegroupBox" as:
class SelectablegroupBox : GroupBox
{
public SelectablegroupBox()
{
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
}
protected override void OnEnter(EventArgs e)
{
this.Focus();
this.Invalidate();
base.OnEnter(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (this.Focused)
{
var rc = this.ClientRectangle;
rc.Inflate(-2, -2);
ControlPaint.DrawFocusRectangle(pe.Graphics, rc);
}
}
}
thanks in advance
Your class SelectableGroupBox is not suitable to let the user select one or more images. There can be at most one focused control in your app - this will be probably a button on your form which the user clicks to save the selected images.
One simple solution would be to use CheckBox controls with the Appearance property set to Button. Also, you don't have to layout the images manually, let a FlowLayoutPanel do the job.
First, add a FlowLayoutPanel named flowLayoutPanel to your tabPage2 and set the following Properties:
flowLayoutPanel.AutoScroll = true;
flowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
Then change the appropriate code in Form2 to:
private const int imageWidth = 128;
private const int imageHeight = 128;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
for (int i = 0; i < output.Count; i++)
{
CheckBox cb = new CheckBox();
cb.Appearance = Appearance.Button;
cb.Size = new Size(imageWidth, imageHeight);
cb.BackgroundImageLayout = ImageLayout.Zoom;
ProductImages pI = output[i];
//Don't dispose the MemoryStream, the Image class will need it!
var ms = new MemoryStream(pI.Pic);
cb.BackgroundImage = Image.FromStream(ms);
flowLayoutPanel.Controls.Add(cb);
}
}
This is how you get your selected pictures:
private void SaveButton_Click(object sender, EventArgs e)
{
var selected = flowLayoutPanel.Controls.OfType<CheckBox>().Where(x => x.Checked);
Debug.Print("Selected images: {0}", selected.Count());
foreach (var item in selected)
{
//Save the picture from item.BackgroundImage.
}
}
I'm using a FlowLayoutPanel to dynamically display an array of PictureBoxes and Labels. They're going in the order: PictureBox-Label-PictureBox-Label and so on. I need those labels to appear above each picture so they'll match, basically layring them ontop of picturebox margins. I tried using Controls.SetChildIndex(temp, 2); but it seem to just swap the postion of the picturebox. I also tried using temp.BringToFront(); but then all the pictureboxes being displayed at the top of the panel and all the labels are below (I need each label to match each picturebox above them). Here's the code:
public void RunMeta()
{
Label mostPickedLabel = new Label();
mostPickedLabel.Text = "Most picked heroes";
flowLayoutPanel1.Controls.Add(mostPickedLabel);
mostPickedLabel.Margin = new Padding(15, 0, 1000, 0);
mostPickedLabel.Font = new Font("Lucida Sans Unicode", 15);
mostPickedLabel.ForeColor = Color.DarkCyan;
mostPickedLabel.Size = new Size(200, 30);
foreach (var mostPickedHero in FetchDataFromDota2Site.MostUsedHeroesAndImages)
{
PictureBox temp = new PictureBox();
temp.ImageLocation = mostPickedHero.ImageSource;
temp.SizeMode = PictureBoxSizeMode.StretchImage;
temp.Left = temp.Width * flowLayoutPanel1.Controls.Count;
temp.Margin = new Padding(15, 30, 15, 30);
flowLayoutPanel1.Controls.Add(temp);
flowLayoutPanel1.AutoScroll = true;
Label heroName = new Label();
heroName.Text = mostPickedHero.MostPickedHeroName;
heroName.Font = new Font("Lucida Sans Unicode", 8);
heroName.ForeColor = Color.White;
flowLayoutPanel1.Controls.Add(heroName);
}
}
List<PictureBox> PictureList = new List<PictureBox>();
for(int i = 0; i < 10; i++)
{
var pic = new PictureBox
{
Parent = pictureBox1,
Name = rdr["num"].ToString(),
Location = new Point(50, 50),
Size = new Size(25, 25),
BackColor = Color.Transparent,
Image = Properties.Resources.budea,
SizeMode = PictureBoxSizeMode.StretchImage,
}
PictureList.Add(pic);
}
After I made List<PictureBox> global, I create another PictureBox.
I want to implement an event of one of the List<PictureBox> to another PictureBox Click event.
In order to do it, one of the List should be placed in a new PictureBox, but I don't know how to do this.
I'm working on C# windows form. I have an array of picturebox, displayed on the form. The array has the size of 13, and they're all side by side. How can I make it so that when I click on a picturebox, it is moved up by let's say +20 on y.
My code to make the picture boxes. The pb1 and p1 are declared above
void print_Deck(int x, int y, double[] a){
double n;
for (int i = 0; i < 13; i++)
{
pb1[i] = new PictureBox();
// pb1[1].Image = Properties.Resources.img1;
pb1[i].Visible = true;
pb1[i].Location = new Point(0, 0);
this.Size = new Size(800, 600);
pb1[i].Size = new Size(46, 65);
pb1[i].SizeMode = PictureBoxSizeMode.StretchImage;
pb1[i].Location = new Point(x, y);
n= a[i];
im = face(n);
pb1[i].Image = im;
this.Controls.Add(pb1[i]);
x = x + 20;
}
}
You can try adding Click event on your Picturebox then you can try this code on the Click function.
You can manipulate the location by using Top propery.
Picturebox.Top -= 20; // move the picture box upward
or
Picturebox.Top += 20; // move the picture box downward
or use the .Location = New Point(X,Y)
Picturebox.Location = new Point(Picturebox.Location.X, Picturebox.Location.Y + 20);
Here's how you add the EventHandler to your picturebox.
Picturebox.Click += new System.EventHandler(this.Picturebox_ClickFunction);
then create a fucntion with the name Picturebox_ClickFunction
private void Picturebox_ClickFunction(object sender, EventArgs e)
{
PictureBox pb1 = (PictureBox)sender; // you need to cast(convert) the sende to a picturebox object so you can access the picturebox properties
}
then you can use the code I provided above.
You can try PictureBox.Top property with Anchor property
or use PictureBox.Location.
You could register the PictureBox's 'Click' event to adjust the 'Margin' property by the required amount
I load dinamically multiple images in flowLayoutPanel...and I wanna scroll the panel if necessary.
Here is my code:
private void carregarImagensToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog d = new OpenFileDialog();
// allow multiple selection
d.Multiselect = true;
// filter the desired file types
d.Filter = "JPG |*.jpg|PNG|*.png|BMP|*.bmp";
// show the dialog and check if the selection was made
if (d.ShowDialog() == DialogResult.OK)
{
foreach (string image in d.FileNames)
{
// create a new control
PictureBox pb = new PictureBox();
pb.Tag = tag;
btn.Tag = tag;
pb.MouseDown += pictureBox_MouseDown;
// assign the image
pb.Image = new Bitmap(image);
listaImagens.Add(new Bitmap(image));
// stretch the image
pb.SizeMode = PictureBoxSizeMode.StretchImage;
// set the size of the picture box
pb.Height = pb.Image.Height / 10;
pb.Width = pb.Image.Width / 10;
// add the control to the container
flowLayoutPanel1.Controls.Add(pb);
listaPicBoxes.Add(pb);
tag++;
}
}
}
You could always use the AutoScroll property:
flowLayoutPanel1.AutoScroll = true;
Set the FlowLayoutPanel's AutoScroll property to true