I create a dialog program, when I crete a picturebox for any picture of one folder, and, when I close this dialog, I whant to delete the picture box, but, I recive an exception, and this exception tell me that: The file 0.jpg is used by another process
But, so, I have tried to dispose all the picturebox ... I have tried all possible things, in my knowledge, of course...
So, my sample code is that:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace delFolder
{
public partial class FormPictureView : Form
{
private PictureBox pbSel = null;
public FormPictureView()
{
InitializeComponent();
AddPictureBox();
}
private void AddPictureBox()
{
int linha = 0;
int x = 10, y = 10;
string pngOutputPath = #"images\";
string[] files = Directory.GetFiles(pngOutputPath);
for (int i = 0; i < files.Length; i++)
{
if (linha == 2)
{
x = 10;
y += 360;
linha = 0;
}
PictureBox pb = new PictureBox();
pb.Name = string.Format("pb{0}", i);
pb.Size = new Size(236, 321);
pb.SizeMode = PictureBoxSizeMode.Zoom;
pb.Image = Image.FromFile(string.Format("{0}{1}.jpg", pngOutputPath, i));
pb.BackColor = Color.White;
pb.Click += new EventHandler(pb_Click);
pb.Tag = string.Format("{0}{1}.jpg", pngOutputPath, i);
pb.Location = new System.Drawing.Point(x, y);
panel1.Controls.Add(pb);
x += 280;
linha++;
}
}
private void pb_Click(object sender, EventArgs e)
{
if (pbSel != null)
pbSel.BorderStyle = BorderStyle.None;
PictureBox pb = (PictureBox)sender;
pb.BorderStyle = BorderStyle.FixedSingle;
pbSel = pb;
MessageBox.Show(pb.Tag.ToString());
}
}
}
and, this dialog is a MDIParent of Main form..., and, when I close this dialog, I try to delete the picture box, but, it's impossible :(
How I can solve this ?
You need to Dispose() the Image in the PictureBox.
If you set the ImageLocation property instead of the Image property no lock on the file will be aquired and you will be able to delete the file. However the image will not be available to the PictureBox any more and a "no image" icon will be displayed.
To solve this you could copy the image into memory before deleting it:
string imgPath = string.Format("{0}{1}.jpg", pngOutputPath, i);
// Retrieve image from file
Image img = Image.FromFile(imgPath);
// Create new canvas to paint the picture in
Bitmap tempImg = new Bitmap(img.Width, img.Height);
// Paint image in memory
using (Graphics g = Graphics.FromImage(tempImg))
{
g.DrawImage(img, 0, 0);
}
// Assign image to PictureBox
pb.Image = tempImg;
// Dispose original image and free handles
img.Dispose();
// Delete the original file
File.Delete(imgPath);
Set your yourPictureBox.image to null before deleting the image
Related
I want to get database images show in listview but it does not work . I tried but can't any one can help .
ListViewItem liv = new ListViewItem(read[0].ToString());
liv.SubItems.Add(read[1].ToString());
liv.SubItems.Add(read[2].ToString());
liv.SubItems.Add(read[3].ToString());
listView1.Items.Add(liv);
Here on index[3] in database the images stored .
The error show in image
For what I can see, your image is stored in a Database and retrieved in ByteArray format. You need to convert the ByteArray stream to a Bitmap Image:
Image _image = new Bitmap(new MemoryStream((Byte[])read[3]));
Since this image has to be referenced in more than one method, define it at Class level.
using System.Drawing;
using System.Drawing.Text;
Image _image;
To let a SubItem display the image, you need to Paint the items yourselft, so set the OwnerDraw property of your ListView:
listView1.OwnerDraw = true;
Get the items from your Data source:
(... LOOP ...)
//Define a new ListView Item...
ListViewItem _LVItem = new ListViewItem(read[0].ToString());
ListViewItem.ListViewSubItemCollection _ItemsCollection =
new ListViewItem.ListViewSubItemCollection(_LVItem);
//... and SubItems
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, read[1].ToString()));
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, read[2].ToString()));
//No text here, this is where the image will be drawn
_ItemsCollection.Add(new ListViewItem.ListViewSubItem(_LVItem, ""));
//Create a new Bitmap using a MemoryStream
_image = new Bitmap(new MemoryStream((Byte[])read[3]));
listView1.Items.Add(_LVItem);
(... LOOP ...)
Create EventHandlers for listView1.DrawColumnHeader and listView1.DrawSubItem
//You need to draw both Headers...
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//Let the system draw these headers, nothing to do here
e.DrawDefault = true;
}
//... and SubItems
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
//If this is the column where the image is shown, draw it
if (e.ColumnIndex == 3)
{
//Position the image in the middle of its Column
//This will be re-calculated when the Column is resized
int _XLocation = (e.SubItem.Bounds.X +
(e.SubItem.Bounds.Width / 2) -
(e.SubItem.Bounds.Height / 2));
//Draw the Image resized to the Height of the row
e.Graphics.DrawImage(_image, new Rectangle(_XLocation, e.SubItem.Bounds.Y, e.SubItem.Bounds.Height, e.SubItem.Bounds.Height));
}
//Draw the other columns using their pre-defined values
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
e.Graphics.DrawString(e.SubItem.Text,
e.SubItem.Font,
new SolidBrush(e.SubItem.ForeColor),
e.SubItem.Bounds.Location.X,
e.SubItem.Bounds.Location.Y);
}
And this is the result:
// To Convert you byte array to Images you need to convert it to a memory stream first
// You will need to add:
// using System.IO;
// And you need to add an ImageList named "imageList1" to your form.
// Then Initialize the ImageList object with images.
for (int i = 0; i < read.Length; i++)
{
try
{
MemoryStream memStream = new MemoryStream(read[i]);
this.imageList1.Images.Add(Image.FromStream(memStream));
}
catch
{ MessageBox.Show( "Image at index ( " + i.ToString() + " ) is not an image file"); }
}
//Now You can assign the ImageList objects to your ListView.
this.listView1.View = View.SmallIcon;
this.listView1.SmallImageList = this.imageList1;
for (int j = 0; j < this.imageList1.Images.Count; j++)
{
ListViewItem liv = new ListViewItem();
liv.ImageIndex = j;
this.listView1.Items.Add(liv);
}
I created around 12 picbox and label dynamically im able to retrieve data in the picbox and label from SQL. the picbox image in binary format and the row where imagestore in table also contain image title's in database.
The problem is that I want to add a click_event on picbox. ASAP I click on picbox a textbox1. text which I created must show the title of the image which is store in the SQL.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace library
{
public partial class showingmore : Form
{
private string passvalue;
public string passval
{
get { return passvalue; }
set { passvalue = value; }
}
public showingmore()
{
InitializeComponent();
}
MemoryStream ms;
byte[] photo_aray;
private void showingmore_Load_1(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection("Provider=SQLOLEDB;User ID=sa;Password =12345678; Initial Catalog=library; server=raj; TRUSTED_CONNECTION=true;");
OleDbDataAdapter Adap = new OleDbDataAdapter("select * from movie ", con);
textBox1.Text = passvalue;
DataSet ds = new DataSet();
Adap.Fill(ds);
//textBox1.Text = ds.Tables[0].Rows[15][0].ToString(); // the working way to use ds to fill data
//textBox1.Text = ds.Tables[0].Rows[1];
//int icount = ds.Tables[0].Rows.Count;
//textBox1.Text = icount.ToString();
/**** Creating Label's and Picture Box ****/
int n = 12; // total time for running loop.
int j = 14; // y-axis co-ordinate label
int k = 479; // x-axis co-ordinate label
int l = 18; // y-axis co-ordinate label
// Creating label through loop's.
for (int i = 0; i < n; i++)
{
//Create label
Label labels = new Label();
PictureBox picbox = new PictureBox();
labels.Text = ds.Tables[0].Rows[i][0].ToString();
if (i <= 5)
{
//Position label on screen
labels.Location = new Point(j, k);
j = j + 228;
// Label text color
labels.ForeColor = Color.Gainsboro;
}
else
{
k = 782; // x-axis co-ordinate
labels.Location = new Point(l, k);
l = l + 228;
labels.ForeColor = Color.Gainsboro;
}
this.Controls.Add(labels);
}
n = 12; // total time for running loop.
j = 18; // y-axis co-ordinate
k = 246; // x-axis co-ordinate
l = 18; // y-axis co-ordinate
// Creating PictureBox through loop's.
for (int i = 0; i < n; i++)
{
//Create PictureBox
PictureBox picbox = new PictureBox();
picbox.Image = null;
if (ds.Tables[0].Rows[i][14] != System.DBNull.Value)
{
photo_aray = (byte[])ds.Tables[0].Rows[i][14];
MemoryStream ms = new MemoryStream(photo_aray);
picbox.Image = Image.FromStream(ms);
}
if (i <= 5)
{
//Position PictureBox on screen
picbox.Location = new Point(j, k);
picbox.Size = new Size(161, 220);
picbox.BackColor = Color.Gainsboro;
j = j + 228;
}
else
{
k = 543; // y-axis co-ordinate
picbox.Location = new Point(l, k);
picbox.Size = new Size(161, 220);
picbox.BackColor = Color.Gainsboro;
l = l + 228;
}
this.Controls.Add(picbox);
}
}
}
}
To get the click event for your dynamically created PictureBox, you can simple subscribe to the click event when you create it;
private void createPicBoxes()
{
for (int i = 0; i <= 12; i++)
{
PictureBox picBox = new PictureBox();
picBox.Click += picBox_Click;
}
}
static void picBox_Click(object sender, EventArgs e)
{
//do your stuff here which handles generically all of your picture boxes clicks.
}
In short, subscribing to the controls events like such means that whenever that action is performed, in your case a click event, the attached method will fire off.
Put this somewhere in the loop before adding the picbox to the Controls collection:
picbox.MouseClick += picbox_MouseClick;
Then, implement the handler for the click somewhere in your showingmore class:
private void picbox_MouseClick(object sender, MouseEventArgs e)
{
// Your code here.
}
Add event handler to the PictureBox when creating it.
Something like below
PictureBox picbox = new PictureBox();
picbox.Click += new EventHandler(this.picbox_Click);
void picbox_Click(object sender, System.EventArgs e)
{
//your code...
}
I am trying to create a custom error dialog, that has a red x on the left hand side. Below is my code;
using JohnsonControls.FieldBusFDD.Properties;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace JohnsonControls.FieldBusFDD
{
public class ErrorDialog : Dialog
{
public static bool ShowDialog(string text, string title)
{
Form prompt = new Form();
prompt.Width = 435;
prompt.Height = 122;
prompt.FormBorderStyle = FormBorderStyle.FixedDialog;
prompt.Text = title;
prompt.StartPosition = FormStartPosition.CenterScreen;
PictureBox image = new PictureBox();
image.Image = Resources.red_x;
image.Location = new Point(10, 10);
image.Size = new Size(50, 50);
Label textLabel = new Label() { Left = 60, Top = 10, Width = 350, Text = text };
Button confirmation = new Button() { Text = "Ok", Left = 300, Width = 100, Top = 52 };
confirmation.Click += (sender, e) => { prompt.Close(); };
confirmation.DialogResult = DialogResult.OK;
prompt.Controls.Add(image);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
return prompt.ShowDialog() == DialogResult.OK ? true : false;
}
}
}
The file is stored in the project resources, and compiles just fine but the image is not displayed.
When the pixel size of the image is too big, the PictureBox only shows the upper-left corner of the image by default.
Try this:
image.SizeMode = PictureBoxSizeMode.Zoom;
From MSDN:
By default, in Normal mode, the Image is positioned in the upper-left corner of the PictureBox, and any part of the image that is too big for the PictureBox is clipped. Using the StretchImage value causes the image to stretch or shrink to fit the PictureBox. Using the Zoom value causes the image to be stretched or shrunk to fit the PictureBox; however, the aspect ratio in the original is maintained.
Try to strecth image on your picture box by:
image.SizeMode = PictureBoxSizeMode.StretchImage;
Using the StretchImage value causes the image to stretch or shrink to fit the PictureBox.
First off, sorry if this is the wrong place for this post, but I don't usually post in forums. I have been stuck on a problem and cannot figure it out so I've finally decided to ask for help. Also, I am very new to C#.
Ok, so I have a live stream from an IP camera that I want to save to an avi file. Here is my code, it is very messy with lots of things commented out because I've been trying so many things. The code does open the stream so I can view it, and it creates an avi file of the name I choose. However, when you open that avi file, it is just black for however long you choose, in this case 40 seconds. I think my main problem is not knowing where to add in this piece of code:
int width = 320;
int height = 240;
// create instance of video writer
VideoFileWriter writer = new VideoFileWriter( );
// create new video file
writer.Open( "test.avi", width, height, 25, VideoCodec.MPEG4 );
// create a bitmap to save into the video file
Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb );
// write 1000 video frames
for ( int i = 0; i < 1000; i++ )
{
image.SetPixel( i % width, i % height, Color.Red );
writer.WriteVideoFrame( image );
}
writer.Close( );
I have tried many things and am just stuck! Can someone please help? Here is my code, and the stuff commented out is me just trying stuff and seeing what sticks, so to speak:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using AForge.Video;
using AForge.Controls;
using AForge.Video.DirectShow;
using AForge.Video.VFW;
using AForge.Video.FFMPEG;
namespace _11GVideoFeed
{
public partial class Form1 : Form
{
private MJPEGStream jpegSource1 = new MJPEGStream("IpCameraFeed");
VideoFileWriter writer = new VideoFileWriter();
private void Form1_Load(object sender, System.EventArgs e)
{
jpegSource1.Login = "login";
jpegSource1.Password = "password";
Player.VideoSource = jpegSource1;
//Player.VideoSource.Start();
//VideoFileWriter writer = new VideoFileWriter();
//Create new AVI file and open it
//writer.Open("test102.avi", 320, 240, 25, VideoCodec.MPEG4);
//Create frame image
//Bitmap image1 = new Bitmap(320, 240);
//for (int i = 0; i < 1000; i++)
//{
// //image1.SetPixel(i % 320, i % 240, Color.Red);
// //add the image as a new frame of video file
// writer.WriteVideoFrame(image1);
//}
//writer.Close();
}
private void Form1_FormClosing(object sender,System.Windows.Forms.FormClosedEventArgs e)
{
Player.VideoSource.Stop();
jpegSource1.Stop();
}
private void jpegSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
Bitmap FrameData = new Bitmap(eventArgs.Frame);
Player.BackgroundImage = FrameData;
}
private void jpegSource_VideoSourceError(object sender, AForge.Video.VideoSourceErrorEventArgs eventArgs)
{
Debug.WriteLine(eventArgs.Description);
}
public Form1()
{
InitializeComponent();
//this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
this.Load += new EventHandler(Form1_Load);
jpegSource1.NewFrame += new NewFrameEventHandler(jpegSource_NewFrame);
jpegSource1.VideoSourceError += new VideoSourceErrorEventHandler(jpegSource_VideoSourceError);
}
private void StartButton_Click(object sender, EventArgs e)
{
Player.VideoSource.Start();
writer.Open("test1000.avi", 320, 240, 25, VideoCodec.MPEG4);
Bitmap image1 = new Bitmap(320, 240);
for (int i = 0; i < 1000; i++)
{
//image1.SetPixel(i % 320, i % 240, Color.Red);
//add the image as a new frame of video file
writer.WriteVideoFrame(image1);
}
//writer.Close();
}
private void stopButton_Click(object sender, EventArgs e)
{
Player.VideoSource.Stop();
writer.Close();
}
}
}
I'm having a problem with displaying transparent images with a transparent background. The transparent background takes the color of the underlying control and that is fine ... bu the problem is that some details (lines) on the underlying background are being covered the the images as can be seen in the image below.
Here is the code I am using.... This is the code for the notes....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Drawing;
namespace Simpe_Piano_new
{
class MusicNote: PictureBox
{
public SoundPlayer sp = new SoundPlayer();
Timer tmr = new Timer();
public int pitch; //The no. of the music key (e.g. the sound freuency).
public int noteDuration; //Shape of note.
public string noteShape;
public MusicNote(int iPitch, int iNoteDuration)
: base()
{
pitch = iPitch;
noteDuration = iNoteDuration;
Size = new Size(40, 40);
}
public void ShowNote()
{ if (this.noteDuration == 1) noteShape = "Quaver.png";
if (this.noteDuration == 4) noteShape = "Crotchet.png";
if (this.noteDuration == 7) noteShape = "minim.png";
if (this.noteDuration == 10) noteShape = "DotMin.png";
if (this.noteDuration == 12) noteShape = "SemiBreve.png";
this.BackgroundImage = Image.FromFile(noteShape);
this.BackColor = Color.Transparent;
Location = new Point((pitch * 40) - 40, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
public void PlaySound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
}
public void StopSound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Stop();
}
public void Play()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
//Time to play the duration
tmr.Interval = noteDuration;
tmr.Start();
tmr.Tick += new System.EventHandler(ClockTick);
}
void ClockTick(object sender, EventArgs e)
{
sp.Stop();
tmr.Stop();
}
}
}
This is the code for the underlying control..the music staff
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace Simpe_Piano_new
{
public class MusicStaff: Panel
{
Pen myPen;
Graphics g;
public MusicStaff()
{
this.Size = new Size(1000, 150);
this.Location = new Point(0, 0);
this.BackColor = Color.Transparent;
this.Paint += new PaintEventHandler(DrawLines);
}
private void DrawLines(object sender, PaintEventArgs pea)
{
myPen = new Pen(Color.Black, 1);
g = this.CreateGraphics();
for (int i = 1; i < 6; i++)
{
g.DrawLine(myPen, 0, (this.Height / 6) * i, this.Width, (this.Height / 6) * i);
}
}
}
}
I have found that C# does not handle transparency really well...
Any help would be greatly appreciated..
add the top control "MusicNote" in the children of the underlying control "MusicStaff"
something like that after -Initializing all components-
// mStaff: the MusicStaff object
// mNote: the MusicNote object
mStaff.Children.Add(mNote);
in old scenario, the form is the parent of both of them, so they display the form background in any transparent area
after modifying the parent of the "MusicNote", it displays the "MusicStaff" background in the transparent area
I hope that help!
Two mistakes. PictureBox supports transparent images well, as long as you set its BackColor property to Color.Transparent. Which you did for the MusicStaff but not for the MusicNote. Layered transparency does not work, you don't need MusicStaff to be transparent, just the picture boxes.
This kind of transparency is simulated by asking the Parent to paint itself into the control to provide the background pixels. Which is your second mistake, you use CreateGraphics() in your DrawLines() method. Which draws directly to the screen, not the control surface. You must use pea.Graphics here.
Do note that the value-add you get from using PictureBox is a very low one. Controls are expensive and you'll easily burn up hundreds of them to display a sheet of music. You'll notice, it will become slow to paint itself. You avoid this by having MusicStaff just paint the notes itself, using Graphics.DrawImage() gets the job done. Transparency effects are now much simpler as well, just layers of paint. Which is the way WPF does it. The only inconvenience you'll have to deal with is that mouse hit testing isn't as simple anymore, you need to map the panel's MouseDown event's coordinates to a note. Just keep a List that keeps track where every note is displayed. You'll use that for painting as well as mouse hit testing.