using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace IconFreeArrangementPanel { public partial class FreeListView : ListView { [DllImport("comctl32.dll")] private static extern bool ImageList_BeginDrag(IntPtr imageList, int index, int x, int y); [DllImport("comctl32.dll")] private static extern void ImageList_EndDrag(); [DllImport("comctl32.dll")] private static extern bool ImageList_DragEnter(IntPtr window, int x, int y); [DllImport("comctl32.dll")] private static extern bool ImageList_DragLeave(IntPtr window); [DllImport("comctl32.dll")] private static extern bool ImageList_DragMove(int x, int y); [DllImport("comctl32.dll")] private static extern bool ImageList_Destroy(IntPtr imgaeList); [DllImport("comctl32.dll")] private static extern IntPtr ImageList_Merge(IntPtr imgaeList1, int index1, IntPtr imageList2, int index2, int x, int y); private IntPtr dragImage; /// ドラッグする前のクリック位置(X座標) private int pointX; /// ドラッグする前のクリック位置(Y座標) private int pointY; /// /// コンストラクタ /// public FreeListView() { InitializeComponent(); } public FreeListView(string imageDir) : this() { string[] jpgFiles = System.IO.Directory.GetFiles(imageDir, "*.jpg"); int width = 100; int height = 80; imageList1.ImageSize = new Size(width, height); this.LargeImageList = imageList1; Image original = null; Image thumbnail = null; for (int i = 0; i < jpgFiles.Length; i++) { original = Bitmap.FromFile(jpgFiles[i]); thumbnail = this.createThumbnail(original, width, height); // ImageListのImage設定 imageList1.Images.Add(thumbnail); // ListViewのラベル設定 this.Items.Add("Item" + i, i); original.Dispose(); //thumbnail.Dispose(); } } /// /// 幅w、高さhのImageオブジェクトを作成 /// /// /// /// /// public 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; } /// /// ドラッグ開始 /// /// protected override void OnItemDrag(ItemDragEventArgs e) { base.OnItemDrag(e); const int LvmCreateDragImage = 0x1000 + 33; Point pos = Point.Empty; foreach (ListViewItem item in this.SelectedItems) { IntPtr pp = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Point))); Message m = Message.Create(this.Handle, LvmCreateDragImage, new IntPtr(item.Index), pp); this.WndProc(ref m); Point p = (Point)Marshal.PtrToStructure(pp, typeof(Point)); Marshal.FreeCoTaskMem(pp); if (this.dragImage.Equals(IntPtr.Zero)) { this.dragImage = m.Result; pos = p; } else { IntPtr old = this.dragImage; this.dragImage = ImageList_Merge(old, 0, m.Result, 0, p.X - pos.X, p.Y - pos.Y); ImageList_Destroy(old); ImageList_Destroy(m.Result); } } Point view = this.PointToClient(Control.MousePosition); ImageList_BeginDrag(dragImage, 0, view.X - pos.X, view.Y - pos.Y); ImageList_DragEnter(this.Handle, view.X, view.Y); } /// /// コントロール上を移動 /// /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (dragImage != IntPtr.Zero) { ImageList_DragMove(e.X, e.Y); } } /// /// マウスボタンが離された(ドラッグ終了) /// /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (dragImage != IntPtr.Zero) { ImageList_DragLeave(this.Handle); ImageList_EndDrag(); ImageList_Destroy(dragImage); dragImage = IntPtr.Zero; foreach (ListViewItem srcItem in this.SelectedItems) { // ドロップ位置から挿入位置となるインデックス値を決定する ListViewItem item = this.GetItemAt(e.X, e.Y); int destIndex = this.Items.IndexOf(item); // 項目の範囲外でドロップしたときは、最後尾に追加する様にインデックス値を設定 if (destIndex < 0) { destIndex = this.Items.Count; } else if (destIndex > srcItem.Index) { destIndex++; } ListViewItem newItem = this.Items.Insert(destIndex, (ListViewItem)srcItem.Clone()); newItem.Selected = true; this.Items.Remove(srcItem); } } } } }