スキップしてメイン コンテンツへ

 none
listViewに表示してある画像を選択してパソコン本体のファイルに保存したい RRS feed

  • 質問

  • 前回https://social.msdn.microsoft.com/Forums/ja-JP/b0464c1b-d440-4f60-9d8a-c6f4226993cf/listview?forum=netfxgeneraljaでVisual Studio2017でWindowsFormをADO.NETを使ったデータベース(SqlServer)プログラミングでデータベースに保存してある画像をファイルに保存したいという質問をしプログラムを教えてもらいうまくできました。

    namespace WindowsFormsApp6
    {
        using System;
        using System.Collections.Generic;
        using System.Data;
        using System.Drawing;
        using System.Linq;
        using System.Windows.Forms;
        using System.IO;
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                this.listView1.ItemDrag += ListView1_ItemDrag;
            }
    
            /// <summary>
            /// アイテムをドラッグ開始
            /// </summary>
            private void ListView1_ItemDrag(object sender, ItemDragEventArgs e)
            {
                //一時フォルダ作成
                var tempDir = System.IO.Path.GetTempFileName();
                System.IO.File.Delete(tempDir);
                System.IO.Directory.CreateDirectory(tempDir);
    
                try
                {
                    List<string> tempFiles = new List<string>();
    
                    foreach (ListViewItem item in listView1.SelectedItems)
                    {//選択されている画像を一時フォルダに一時的に配置
                        var tempFile = System.IO.Path.Combine(tempDir, item.Text);
                        using (System.IO.FileStream fs = new System.IO.FileStream(tempFile, FileMode.Create, FileAccess.Write))
                        {
                            byte[] bs = (Byte[])item.Tag;//ファイル保存するのは保持しているバイナリ
                            fs.Write(bs, 0, bs.Length);
                        }
    
                        tempFiles.Add(tempFile);
                    }
    
                    //D&Dでファイルパスを渡す
                    DataObject dobj = new DataObject(DataFormats.FileDrop, tempFiles.ToArray());
    
                    //D&D開始
                    listView1.DoDragDrop(dobj, DragDropEffects.Copy);
    
                }
                finally
                {
                    System.IO.Directory.Delete(tempDir, true);
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                int width = 100;
                int height = 80;
                imageList1.ImageSize = new Size(width, height);
                listView1.LargeImageList = imageList1;
                imageList1.Images.Clear();
                listView1.Items.Clear();
    
                
                var dt = CreateTestDataTable(); // データベースの代わりにテストデータ
    
    
                foreach (var row in dt.AsEnumerable())
                {
                    var Photoname = row["Photoname"].ToString();
                    var ms = new MemoryStream((byte[])row["Photo"]);
    
                    var original = Image.FromStream(ms);
                    var thumbnail = createThumbnail(original, width, height);
    
                    imageList1.Images.Add(thumbnail);
                    ListViewItem item = listView1.Items.Add(Photoname, dt.Rows.IndexOf(row));
                    item.Tag = row["Photo"];//アイテムにバイナリを保持させる
    
                    original.Dispose();
                    thumbnail.Dispose();
                }
    
                Image createThumbnail(Image image, int w, int h)
                {
                    Bitmap canvas = new Bitmap(w, h);
    
                    Graphics g = Graphics.FromImage(canvas);
                    g.FillRectangle(new SolidBrush(Color.White), 0, 0, w, h);
    
                    float fw = (float)w / (float)image.Width;
                    float fh = (float)h / (float)image.Height;
    
                    float scale = Math.Min(fw, fh);
                    fw = image.Width * scale;
                    fh = image.Height * scale;
    
                    g.DrawImage(image, (w - fw) / 2, (h - fh) / 2, fw, fh);
                    g.Dispose();
    
                    return canvas;
                }
            }
    
            /// <summary>データベースではなくピクチャフォルダからテストデータ作成</summary>
            private DataTable CreateTestDataTable()
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Photoname", typeof(string));
                dt.Columns.Add("Photo", typeof(byte[]));
    
                System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures));
    
                foreach (var fi in di.GetFiles())
                {
                    switch (fi.Extension.ToLower())
                    {
                    case ".png":
                    case ".jpg":
    
                        var row = dt.NewRow();
                        row["Photoname"] = fi.Name;
                        using (System.IO.FileStream fs = fi.OpenRead())
                        {
                            byte[] bs = new byte[fs.Length];
                            fs.Read(bs, 0, bs.Length);
                            row["Photo"] = bs;
                        }
                        dt.Rows.Add(row);
                        break;
                    default:
                        break;
                    }
                }
    
                return dt;
            }
        }
    }

    D&Dで画像をファイルに保存するところを表示されている画像を選択してボタンを押すとwindowsのメモ帳にある名前を付けて保存すると同じ事がしたいんですが初心者なのでどこを修正したらできるのかわからないので教えてください。

    • 編集済み aqwpue 2019年12月14日 0:15
    2019年12月12日 23:29

すべての返信

  • 丸投げしないで、自分で考えて自分の手を動かしてコードを書いて、そのうえでどうしても前に進めないところにぶつかったら、どこまで自分で実装できたのか、どこで躓いているのか、何が分かれば解決するのか、自分が書いたコードをアップして説明して回答を募るようにしてはいかがですか?

    時々親切な人がいるので、丸投げしてもコードを書いてくれることを期待できるかもしれませんが、普通は丸なけではレスは付きにくいです。毎度それをやっているとそのうち相手にしてもらえなくなる恐れもありますし。
    2019年12月13日 7:17
  • コードを追加したようですが、それは私のアドバイスとは関係なく、前のあなたのスレッドの回答者のレスにあるコードをコピペしただけですよね。

    丸投げを改める気はないということ?

    2019年12月15日 0:42
  • aqwpueさん、こんにちは。フォーラムオペレーターのクモです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    コードに基づいてテストを行い、データベースに画像を保存し、listviewで表示しました。
    次はすべてのコードですが、ご参照ください。

    private void UpdateListView_Click(object sender, EventArgs e)
            {      
                int width = 100;
                int height = 80;
                imageList1.ImageSize = new Size(width, height);
                listView1.LargeImageList = imageList1;
                imageList1.Images.Clear();
                listView1.Items.Clear();
                DataTable dt = new DataTable();
    
                string connString = "your connection string";
                using (SqlConnection Conn = new SqlConnection(connString))
                {
                    Conn.Open();
                    string cmdText = "SELECT Name,imagebinary FROM TableImage";
                    SqlCommand cmd = new SqlCommand(cmdText, Conn);
                    dt.Load(cmd.ExecuteReader());
                }
                dt.Columns[0].ColumnName = "Photoname";
                dt.Columns[1].ColumnName = "Photo";
                foreach (var row in dt.AsEnumerable())
                {
                    var Photoname = row["Photoname"].ToString();
                    var ms = new MemoryStream((byte[])row["Photo"]);
    
                    var original = Image.FromStream(ms);
                    var thumbnail = createThumbnail(original, width, height);
    
                    imageList1.Images.Add(thumbnail);
                    ListViewItem item = listView1.Items.Add(Photoname, dt.Rows.IndexOf(row));
                    item.Tag = row["Photo"];
    
                    original.Dispose();
                    thumbnail.Dispose();
                }
                Image createThumbnail(Image image, int w, int h)
                {
                    Bitmap canvas = new Bitmap(w, h);
    
                    Graphics g = Graphics.FromImage(canvas);
                    g.FillRectangle(new SolidBrush(Color.White), 0, 0, w, h);
    
                    float fw = (float)w / (float)image.Width;
                    float fh = (float)h / (float)image.Height;
    
                    float scale = Math.Min(fw, fh);
                    fw = image.Width * scale;
                    fh = image.Height * scale;
    
                    g.DrawImage(image, (w - fw) / 2, (h - fh) / 2, fw, fh);
                    g.Dispose();
    
                    return canvas;
                }
            }
    
            private void SaveToDB_Click(object sender, EventArgs e)
            {
                using (OpenFileDialog openFileDialog = new OpenFileDialog())
                {
                    openFileDialog.InitialDirectory = "D:\\TestFile\\";
                    openFileDialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
                    openFileDialog.FilterIndex = 2;
                    openFileDialog.RestoreDirectory = true;
    
                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        string filePath = openFileDialog.FileName;
                        byte[] bt = imageToByteArray(Image.FromFile(filePath));
    
                        string connString = "your connection string";
                        using (SqlConnection Conn = new SqlConnection(connString))
                        {
                            Conn.Open();
                            string cmdText = "INSERT INTO TableImage(Name,imagebinary) VALUES (@Name,@imagebinary)";
                            SqlCommand cmd = new SqlCommand(cmdText, Conn);
                            SqlParameter param = cmd.Parameters.Add("@imagebinary", SqlDbType.VarBinary);
                            param.Value = bt;
                            SqlParameter param1 = cmd.Parameters.Add("@Name", SqlDbType.NVarChar);
                            param1.Value = openFileDialog.SafeFileName;
                            cmd.ExecuteNonQuery();
                            MessageBox.Show("Save image!");
                        }
                    }            
                }
            }
    
            public byte[] imageToByteArray(System.Drawing.Image imageIn)
            {
                MemoryStream ms = new MemoryStream();
                imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                return ms.ToArray();
            }
            private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
            {
                var tempDir = System.IO.Path.GetTempFileName();
                System.IO.File.Delete(tempDir);
                System.IO.Directory.CreateDirectory(tempDir);
    
                try
                {
                    List<string> tempFiles = new List<string>();
    
                    foreach (ListViewItem item in listView1.SelectedItems)
                    {
                        var tempFile = System.IO.Path.Combine(tempDir, item.Text);
                        using (System.IO.FileStream fs = new System.IO.FileStream(tempFile, FileMode.Create, FileAccess.Write))
                        {
                            byte[] bs = (Byte[])item.Tag;
                            fs.Write(bs, 0, bs.Length);
                        }
    
                        tempFiles.Add(tempFile);
                    }
                    DataObject dobj = new DataObject(DataFormats.FileDrop, tempFiles.ToArray());
                    listView1.DoDragDrop(dobj, DragDropEffects.Copy);
                }
                finally
                {
                    System.IO.Directory.Delete(tempDir, true);
                }
            }

    データーベースのデザイン:


    結果:

    どうぞよろしくお願いいたします。


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年12月18日 8:43
    モデレータ
  • 「名前を付けて保存」のダイアログを使うには、前回回答した SaveFileDialog をフォームに貼り付けて(あるいは new して)、それの ShowDialog メソッドを呼び出せば OK です。

    2019年12月18日 10:01
  • kumo-msftさん>

    > メモ帳は単純的なテキスト エディタであるため、図を挿入することはできません。

    「メモ帳」を使っているとか質問者さんの投稿のどこに書いてあるのですか? たとえ書いて
    あったとしても、今回の話はメモ帳とは関係ないのでは?

    Microsoft の人の回答は重いですよ。あなたの回答は Microsoft の看板を背負って、Microsoft 
    として 100% 責任を負えるものなのですか?
    2019年12月18日 11:55
  • Wicresoft 社の方は、Microsoft の社員ではありませんよ、一応念のため。

    マイクロソフトの製品やサービスに関する提携を結んでいる会社の一つですが、プロファイルの所属名情報 には、MSFT CSG が『これらの人はマイクロソフト社員ではなく、マイクロソフトを代表するものではありません。』と明記されています。


    2019年12月18日 12:05
  • > Wicresoft 社の方は、Microsoft の社員ではありませんよ、一応念のため。

    タイポだと思っていますが。そうでなければホントの Microsoft の管理者は何してるんでしょう?

    2019年12月18日 12:12
  • > ウィクレソフト社へのリンクを追加

    それを見て分かりました。理解が遅くてすみません。

    Microsoft がウィクレソフトという会社にこのフォーラムのオペレーションを業務委託したということのようで、kumo-msft さんは「マイクロソフト臨時社員」という立場の人と理解しました。

    ということであれば、以下のように聞き方を変えたいと思います。

    "フォーラムオペレーターの回答は重いですよ。あなたの回答は Microsoft から業務委託を受けた会社の看板を背負って、オペレータ―として 100% 責任を負えるものなのですか?"

    2019年12月19日 1:49
  • >SurferOnWwwさん

    申し訳ございませんが、理解を間違えてしまいました。
    今後気を付けます。

    ご協力のほどどうかよろしくお願いいたします。


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年12月19日 3:11
    モデレータ
  • >aqwpueさん

    申し訳ございません。
    先ほど回答をアップデートしましたので、ご覧になってください。

    どうぞよろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年12月19日 3:12
    モデレータ