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;
/// <summary> ドラッグする前のクリック位置(X座標) </summary>
private int pointX;
/// <summary> ドラッグする前のクリック位置(Y座標) </summary>
private int pointY;
/// <summary>
/// コンストラクタ
/// </summary>
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();
}
}
/// <summary>
/// 幅w、高さhのImageオブジェクトを作成
/// </summary>
/// <param name="image"></param>
/// <param name="w"></param>
/// <param name="h"></param>
/// <returns></returns>
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;
}
/// <summary>
/// ドラッグ開始
/// </summary>
/// <param name="e"></param>
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);
}
/// <summary>
/// コントロール上を移動
/// </summary>
/// <param name="e"></param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (dragImage != IntPtr.Zero)
{
ImageList_DragMove(e.X, e.Y);
}
}
/// <summary>
/// マウスボタンが離された(ドラッグ終了)
/// </summary>
/// <param name="e"></param>
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);
}
}
}
}
}