只有50分了!
再讲清楚点,因为我问过很多问题,回答的人都是答非所问。
设计时,向Imagelist添加的图片,每次运行都在。
但是在运行期间添加的图片,在运行结束后,在设计中看,Imagelist中并没有添加这个图片进去。
要求就是在运行期间添加的图片,运行结束后,能够在设计中看到。也就是说真正保存到Imagelist中去了。
再讲清楚点,因为我问过很多问题,回答的人都是答非所问。
设计时,向Imagelist添加的图片,每次运行都在。
但是在运行期间添加的图片,在运行结束后,在设计中看,Imagelist中并没有添加这个图片进去。
要求就是在运行期间添加的图片,运行结束后,能够在设计中看到。也就是说真正保存到Imagelist中去了。
Form1.cs
Form1.designer.cs
Form1.resx
第一个文件就是我们平常写代码用的,其它两个是由VS维护的。第二个文件的内容是由设计器自动生成的代码,第三个文件是存放资源的,比如图片什么的。
如果你打开Form1.designer.cs这个文件,可以看到其实每个在窗体上放置的控件其实也是由代码一行一行生成的,ImageList也不例外。假如我们手动修改了自动生成的代码,比如删除一行imageList1.Images.Add,这时你会发现在设计器里也会少一幅图片,也就是说,对这个designer.cs文件的修改会直接影响设计器。那么,ImageList里面的那些图片放在哪里呢?就放在Form1.resx里。打了这么多基础,最后再来回答你的问题,要想程序在运行时去修改设计时的内容,只有在运行时去修改相应源文件。如果要往ImageList里加图,那就得先在*.designer.cs文件里仿照原先格式的加入添加图片的语句,然后再把图片加入到*.resx文件里。当然你得控制得很得当,因为如果代码不正确,或者插入了重复的图片,可能会使设计器不能正常工作。强烈建议你不要这样做,不怕你生气,我觉得这个想法有点怪。因为设计器只是用来初始化一些比较固定的内容,虽然可以为我们减少很多工作量,但也不能过份依赖它。动态的内容还是应该动态加载,也不一定要搞什么数据库,最简单的办法就是把每张图都存到硬盘的目录里,比如如下代码:string[] files = System.IO.Directory.GetFiles("c:\\AppData\\AppName\\images\\*.jpg");
foreach (string path in files)
{
string key = System.IO.Path.GetFileName(path);
System.Drawing.Image image;
try
{
image = Image.FromFile(path);
imageList1.Images.Add(key, image);
}
catch(Exception ex)
{
Console.WriteLine("图片[0}加载失败,原因:{1}", path, ex.Message);
}
}以上代码未经测试,随手敲上的,仅供参考。
String strBLOBFilePath= this.open.FileName; //Modify this path as needed.
//从一个包含图片的路径中读取图片信息到流
FileStream fileStream= new FileStream(this.open.FileName, FileMode.Open, FileAccess.Read);
Byte[] bytes= new Byte[fileStream.Length];
fileStream.Read(bytes,0, bytes.Length);
fileStream.Close();//添加ImageCol列的参数
SqlParameter para= new SqlParameter("@ImageCol", SqlDbType.Image, bytes.Length, ParameterDirection.Input,false,0,0,null, DataRowVersion.Current, bytes);
cmd.Parameters.Add(para);//上传图片流信息
con.Open();
cmd.ExecuteNonQuery();
con.Close();二、读取图片SqlConnection cn= new SqlConnection(connString); cn.Open();
//从数据库获取图片流信息
SqlCommand cmd= new SqlCommand("select ImageCol from TestImage", cn);SqlDataAdapter da= new SqlDataAdapter(cmd);
DataTable dt= new DataTable();
da.Fill(dt);//假设只有一条记录
Byte[] byteImageCol= (Byte[])(dt.Rows[0]["ImageCol"]);
MemoryStream stmImageCol= new MemoryStream(byteImageCol);
pictureBox1.Image= Image.FromStream(stmImageCol);
cn.Close();
三、DataReader读取大数据 DataReader 的默认行为是在整个数据行可用时立即以行的形式加载传入数据。但是,对于二进制大对象 (BLOB) 则需要进行不同的处理,因为它们可能包含数十亿字节的数据,而单个行中无法包含如此多的数据。Command.ExecuteReader 方法具有一个重载,它将采用 CommandBehavior 参数来修改 DataReader 的默认行为。您可以将 CommandBehavior.SequentialAccess 传递到 ExecuteReader 方法来修改 DataReader 的默认行为,以便让 DataReader 按照顺序在接收到数据时立即将其加载,而不是加载数据行。这是加载 BLOB 或其他大数据结构的理想方案。
在将 DataReader 设置为使用 SequentialAccess 时,务必要注意访问所返回字段的顺序。DataReader 的默认行为是在整个行可用时立即加载该行,这使您能够在读取下一行之前按任何顺序访问所返回的字段。但是,当使用 SequentialAccess 时,必须按顺序访问由 DataReader 返回的不同字段。例如,如果查询返回三个列,其中第三列是 BLOB,则必须在访问第三个字段中的 BLOB 数据之前返回第一个和第二个字段的值。如果在访问第一个或第二个字段之前访问第三个字段,则第一个和第二个字段值将不再可用。这是因为 SequentialAccess 已修改 DataReader,使其按顺序返回数据,当 DataReader 已经读取超过特定数据时,该数据将不可用。
当访问 BLOB 字段中的数据时,请使用 DataReader 的 GetBytes 类型化访问器,该访问器将使用二进制数据填充 byte 数组。您可以指定要返回的特定数据缓冲区大小以及从返回的数据中读取的第一个字节的起始位置。GetBytes 将返回 long 值,它表示所返回的字节数。如果向 GetBytes 传递空的 byte 数组,所返回的长值将是 BLOB 中字节的总数。您可以选择将字节数组中的某索引指定为所读取数据的起始位置。
以下示例从 Microsoft SQL Server 中的 pubs 示例数据库中返回发行者 ID 和徽标。发行者 ID (pub_id) 是字符字段,而徽标则是图形,即 BLOB。请注意,由于必须按顺序访问字段,所以将在访问徽标之前访问当前数据行的发行者 ID。四、image和Byte数据的相互转换image to byte[]
MemoryStream ms=new MemoryStream();
byte[] imagedata=null;
pictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Gif );
imagedata=ms.GetBuffer ();
byte[] to image
ms = New IO.MemoryStream(by)
img = Drawing.Image.FromStream(ms)