C# - Windows10のログイン画面の壁紙をサムネイル表示してドラッグ＆ドロップでエクスプローラにコピーするツール作ってみた

ロック画面の画像（[参考サイト#1](https://qiita.com/hsn/items/e80fcf88839ab64eba81)を参照ください）をサムネイル表示して、欲しい画像だけ簡単にコピーできるようにしたいと思ったのでC#で作ってみた。

# 画面キャプチャ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/80839d03-abb8-04bd-e730-b2ee43509776.png)



# 使い方

画像を選んでデスクトップ（他のフォルダでも可）にドラッグ＆ドロップすると、ファイルがコピーされます。
~~コピー後の拡張子の変更(.jpgにしてください)は手動でお願いします。（一時ファイルを作るのが面倒なため）~~ 使ってて不便すぎたので拡張子を付加するようにした（テンポラリフォルダ使用します）。

# ソースコード

```cs

using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;


class WinWallpaperPreview : Form
{
    class ImageItemInfo
    {
        public string FullPath{get; private set;}
        public System.Drawing.Size Size{get; private set;}
        public int Width {get{return Size.Width;}}
        public int Height {get{return Size.Height;}}

        public ImageItemInfo(string fullPath, Size size) {
            FullPath = fullPath;
            Size = size;
        }
    }

    class MyListViewItemComparer : IComparer
    {
        public int Compare(object item1, object item2)
        {
            var itemInfo1 = (ImageItemInfo)((ListViewItem)item1).Tag;
            var itemInfo2 = (ImageItemInfo)((ListViewItem)item2).Tag;
            
            int tmp = itemInfo1.Width.CompareTo(itemInfo2.Width);
            if ( tmp == 0 ) { tmp = itemInfo1.Height.CompareTo(itemInfo2.Height); }
            return tmp;
        }
    }

    // ------------------------------------------------------------

    static readonly string imageDir = GetDefaultWallpaperPath();

    ListView lsv;
    ImageList imgList;
    //StatusStrip sts;

    // ------------------------------------------------------------

    static string GetDefaultWallpaperPath()
    {
        return Path.Combine(Environment.GetEnvironmentVariable("LOCALAPPDATA"),
                             @"Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets");
    }
    
    // 幅w、高さhのImageオブジェクトを作成
    Image CreateSmallImage(Image image, Size size)
    {
        int w = size.Width;
        int h = size.Height;
        Bitmap canvas = new Bitmap(w, h);

        Graphics g = Graphics.FromImage(canvas);
        g.FillRectangle(Brushes.LightGray, 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;
    }

    void LoadImages()
    {
        string[] files = Directory.GetFiles(imageDir);
        int count = 0;

        foreach (string filePath in files)
        {
            Image original;
            try {
                original = Image.FromFile(filePath); // 拡張子がなくても自動判別してくれる
            }
            catch ( Exception ex ) { // かなり乱暴なのでマネしないように...
                Console.WriteLine(ex);
                Console.WriteLine("Ignored: " + Path.GetFileName(filePath));
                continue;
            }
            if ( original == null ) {
                Console.WriteLine("Ignored: " + Path.GetFileName(filePath));
                continue;
            }

            Image smallImage = CreateSmallImage(original, imgList.ImageSize);
            imgList.Images.Add(smallImage);
            string text = original.Size.Width.ToString() + " x " + original.Size.Height.ToString();
            lsv.Items.Add(text, count);
//            lsv.Items.Add(Path.GetFileName(filePath), count);
            lsv.Items[count].Tag = new ImageItemInfo(filePath, original.Size);
            count++;

            original.Dispose();
            smallImage.Dispose();
        }

        lsv.ListViewItemSorter = new MyListViewItemComparer();
    }

    //void Lsv_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
    //{
    //    Console.WriteLine(e.Action);
    //}

    void Lsv_ItemDrag(Object sender, ItemDragEventArgs e)
    {
        var item = (ListViewItem)(e.Item);
        string orgPath = ((ImageItemInfo)item.Tag).FullPath;

        // テンポラリフォルダに拡張子(.jpg)付きのファイルを作る
        string tempPath = Path.ChangeExtension(Path.Combine(Path.GetTempPath(), Path.GetFileName(orgPath)), ".jpg");
        Console.WriteLine(tempPath);
        if ( !File.Exists(tempPath) ) {
            try {
                File.Copy(orgPath, tempPath);
            }
            catch ( IOException exception ) {
                MessageBox.Show(exception.ToString());
                return;
            }
        }

        //ドラッグ&ドロップ処理を開始する
        IDataObject iData = new DataObject(DataFormats.FileDrop, new string[]{tempPath});
        lsv.DoDragDrop(iData, DragDropEffects.Copy);
    }



    /*
    壁紙変更は下記でやれるらしい
    [DllImport("User32.DLL")]
    public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, string pvParam, uint fWinIni);
    public static uint SPI_SETDESKWALLPAPER = 0x0014;

    String sName = fullPath;
    SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, sName, 0);
    */

 
    WinWallpaperPreview()
    {
        int width = 100;
        int height = 80;

        imgList = new ImageList();
        imgList.ImageSize = new Size(width, height);

        lsv = new ListView();
        lsv.View = View.Tile;
        lsv.LargeImageList = imgList;
        lsv.Dock = DockStyle.Fill;
        lsv.MultiSelect = false;
        //lsv.SelectedIndexChanged += ;
        lsv.ItemDrag += Lsv_ItemDrag;
        //lsv.QueryContinueDrag += Lsv_QueryContinueDrag;
        Controls.Add(lsv);

        //sts = new StatusStrip();
        //Controls.Add(sts);

        Load += (s,e)=>{LoadImages();};
        FormClosed += (s,e)=>{CleanUpTempDir();};

        Text = "Wallpaper Preview";
        ClientSize = new Size(700,500);
    }
    
    void CleanUpTempDir()
    {
        string tempDir = Path.GetTempPath(); // 変えるな危険！
        if ( Directory.Exists(tempDir) ) {
            try {
                Console.WriteLine(tempDir);
                //Directory.Delete(tempDir, true); // サブフォルダごと削除
            }
            catch ( IOException exception ) {
                Console.WriteLine(exception);
            }
        }
    }

    [STAThread]
    static void Main(string[] args)
    {
        Application.Run(new WinWallpaperPreview());
    }
}
```


# 参考サイト

1. [Windows10のロック画面の画像がキレイだから壁紙のスライドショーにしたいと思った - Qiita](https://qiita.com/hsn/items/e80fcf88839ab64eba81)
2. [ListViewコントロールでサムネイル画像を一覧表示するには？ - ＠IT](https://www.atmarkit.co.jp/ait/articles/0508/12/news091.html)
3. [異種アプリへドラッグアンドドロップする方法 - C# と VB.NET の質問掲示板](http://bbs.wankuma.com/index.cgi?mode=al2&namber=4785&KLOG=4)