DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

クリップボードにファイルをコピーまたは切り取りをする、クリップボードからファイルを取得する、貼り付ける

ここでは、エクスプローラなどに貼付けができるようにファイル(またはフォルダ)をコピーしたり、切り取り(カット)をする方法とを紹介します。また、エクスプローラなどでコピーやカットしたファイルのパスを取得する方法と、コピーやカットしたファイルを貼り付ける方法も紹介します。

ファイル(またはフォルダ)をクリップボードにコピーする

まずは、指定したファイルをクリップボードにコピーする方法です。

.NET Framework 2.0以降

.NET Framework 2.0からは、Clipboard.SetFileDropListメソッドを使って簡単にコピーすることができます。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'コピーするファイルのパスをStringCollectionに追加する
Dim files As New System.Collections.Specialized.StringCollection()
files.Add("C:\1.txt")
files.Add("C:\2.txt")
files.Add("C:\3.txt")
'クリップボードにコピーする
Clipboard.SetFileDropList(files)
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//コピーするファイルのパスをStringCollectionに追加する
System.Collections.Specialized.StringCollection files =
    new System.Collections.Specialized.StringCollection();
files.Add("C:\\1.txt");
files.Add("C:\\2.txt");
files.Add("C:\\3.txt");
//クリップボードにコピーする
Clipboard.SetFileDropList(files);
補足:VB.NETでは、My.Computer.Clipboard.SetFileDropListメソッドを使っても同じことができます。

.NET Framework 1.1以前

.NET Framework 1.1以前では、Clipboard.SetDataObjectメソッドを使用し、DataFormats.FileDrop形式のDataObjectオブジェクトをクリップボードに貼り付けます。データはコピーするファイルのパスの配列にします。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'コピーするファイルのパス
Dim fileNames As String() = {"C:\1.txt", "C:\2.txt", "C:\3.txt"}
'ファイルドロップ形式のDataObjectを作成する
Dim data = New DataObject(DataFormats.FileDrop, fileNames)
'クリップボードにコピーする
Clipboard.SetDataObject(data)
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//コピーするファイルのパス
string[] fileNames = {"C:\\1.txt", "C:\\2.txt", "C:\\3.txt"};
//ファイルドロップ形式のDataObjectを作成する
IDataObject data = new DataObject(DataFormats.FileDrop, fileNames);
//クリップボードにコピーする
Clipboard.SetDataObject(data);

ファイル(またはフォルダ)をクリップボードに切り取る(カットする)

ファイルを切り取る方法は、コメントで教えていただきました。また、「IronInTheFire.Net - Clipboard File Operations」などでも紹介されています。これらを参考にして、以下のサンプルを書かせていただきました。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'切り取るファイルのパス
Dim fileNames As String() = {"C:\1.txt", "C:\2.txt", "C:\3.txt"}
'ファイルドロップ形式のDataObjectを作成する
Dim data As IDataObject = New DataObject(DataFormats.FileDrop, fileNames)

'DragDropEffects.Moveを設定する(DragDropEffects.Move は 2)
Dim bs As Byte() = New Byte() {CByte(DragDropEffects.Move), 0, 0, 0}
Dim ms As System.IO.MemoryStream = New System.IO.MemoryStream(bs)
data.SetData("Preferred DropEffect", ms)

'クリップボードに切り取る
Clipboard.SetDataObject(data)
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//切り取るファイルのパス
string[] fileNames = { "C:\\1.txt", "C:\\2.txt", "C:\\3.txt" };
//ファイルドロップ形式のDataObjectを作成する
IDataObject data = new DataObject(DataFormats.FileDrop, fileNames);

//DragDropEffects.Moveを設定する(DragDropEffects.Move は 2)
byte[] bs = new byte[] { (byte)DragDropEffects.Move, 0, 0, 0 };
System.IO.MemoryStream ms = new System.IO.MemoryStream(bs);
data.SetData("Preferred DropEffect", ms);

//クリップボードに切り取る
Clipboard.SetDataObject(data);

コピーされたファイル(またはフォルダ)のパスを取得する

.NET Framework 2.0以降

.NET Framework 2.0以降では、Clipboard.GetFileDropListメソッドを使って簡単にコピーされたファイルのパスを取得できます。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'クリップボードにファイルドロップ形式のデータがあるか確認
If Clipboard.ContainsFileDropList() Then
    'データを取得する(取得できなかった時はNothing)
    Dim files As System.Collections.Specialized.StringCollection = _
        Clipboard.GetFileDropList()
    '取得したファイル名を列挙する
    Dim fileName As String
    For Each fileName In files
        Console.WriteLine(fileName)
    Next fileName
End If
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//クリップボードにファイルドロップ形式のデータがあるか確認
if (Clipboard.ContainsFileDropList())
{
    //データを取得する(取得できなかった時はnull)
    System.Collections.Specialized.StringCollection files =
        Clipboard.GetFileDropList();
    //取得したファイル名を列挙する
    foreach (string fileName in files)
    {
        Console.WriteLine(fileName);
    }
}
補足:VB.NETでは、My.Computer.Clipboard.GetFileDropListメソッドを使っても同じことができます。

.NET Framework 1.1以降

クリップボードに文字列をコピー、クリップボードから文字列を取得」で紹介しているのと同じように、Clipboardクラス(System.Windows.Forms名前空間)のGetDataObjectメソッドを使うことにより、コピーされたファイルのパスを取得できます。IDataObject.GetDataメソッドでデータを抽出する際にはDataFormats.FileDropデータ形式を指定し、文字列配列として取得します。

次のコードでは、クリップボードにファイルがコピーされている時にそのパスを取得し、出力しています。

VB.NET
コードを隠すコードを選択
'Imports System.Windows.Forms

'クリップボードのデータを取得する
Dim data As IDataObject = Clipboard.GetDataObject()
'クリップボードにファイルドロップ形式のデータがあるか確認
If data.GetDataPresent(DataFormats.FileDrop) Then
    'データを取得する(取得できなかった時はNothing)
    Dim fileNames As String() = _
        CType(data.GetData(DataFormats.FileDrop), String())
    '取得したファイル名を列挙する
    Dim fileName As String
    For Each fileName In fileNames
        Console.WriteLine(fileName)
    Next fileName
End If
C#
コードを隠すコードを選択
//using System.Windows.Forms;

//クリップボードのデータを取得する
IDataObject data = Clipboard.GetDataObject();
//クリップボードにファイルドロップ形式のデータがあるか確認
if (data.GetDataPresent(DataFormats.FileDrop))
{
    //データを取得する(取得できなかった時はnull)
    string[] fileNames = (string[]) data.GetData(DataFormats.FileDrop);
    //取得したファイル名を列挙する
    foreach (string fileName in fileNames)
    {
        Console.WriteLine(fileName);
    }
}

コピー、または切り取られたファイルを貼り付ける

エクスプローラ等でコピー、または切り取られたファイルを貼り付けるには、先に紹介した方法でコピーされたファイルのパスを取得し、そのファイルを「ファイルをコピー、移動(名前の変更)、削除する」で紹介しているような方法でコピー、または移動します。

ただここで問題になるのは、ファイルがコピーされたのか切り取られたのかをどうやって知るかということです。この方法についても「IronInTheFire.Net - Clipboard File Operations」などで説明されています。

ファイルを貼り付ける簡単なコード(PasteFilesメソッド)を書いてみましたので、参考にしてください。ただ、ファイルをコピーまたは移動する部分(CopyFilesToDirectoryメソッド)はいい加減で、コピー先に同名のファイルが存在する時や、フォルダがコピーされた時のことを考えていないなど問題が多く、実用的ではありません。

VB.NET
コードを隠すコードを選択
''' <summary>
''' 指定したフォルダにコピーまたは切り取られたファイルを貼り付ける
''' </summary>
Public Shared Sub PasteFiles(ByVal destDir As String)
    'クリップボードのデータを取得する
    Dim data As IDataObject = Clipboard.GetDataObject()
    'クリップボードにファイルドロップ形式のデータがあるか確認
    If Not data Is Nothing AndAlso data.GetDataPresent(DataFormats.FileDrop) Then
        'コピーされたファイルのリストを取得する
        Dim files As String() = DirectCast(data.GetData(DataFormats.FileDrop), String())
        'DragDropEffectsを取得する
        Dim dde As DragDropEffects = GetPreferredDropEffect(data)
        If dde = (DragDropEffects.Copy Or DragDropEffects.Link) Then
            'ファイルがコピーされていた時
            CopyFilesToDirectory(files, destDir, False)
        ElseIf dde = DragDropEffects.Move Then
            'ファイルが切り取られていた時
            CopyFilesToDirectory(files, destDir, True)
        End If
    End If
End Sub

''' <summary>
''' クリップボードの"Preferred DropEffect"を調べる
''' </summary>
Public Shared Function GetPreferredDropEffect(ByVal data As IDataObject) As DragDropEffects
    Dim dde As DragDropEffects = DragDropEffects.None

    If Not data Is Nothing Then
        'Preferred DropEffect形式のデータを取得する
        Dim ms As System.IO.MemoryStream = _
            DirectCast(data.GetData("Preferred DropEffect"), System.IO.MemoryStream)
        If ms IsNot Nothing Then
            '先頭のバイトからDragDropEffectsを取得する
            dde = DirectCast(ms.ReadByte(), DragDropEffects)

            If dde = (DragDropEffects.Copy Or DragDropEffects.Link) Then
                Console.WriteLine("コピー")
            ElseIf dde = DragDropEffects.Move Then
                Console.WriteLine("切り取り")
            End If
        End If
    End If

    Return dde
End Function

''' <summary>
''' 複数のファイルを指定したフォルダにコピーまたは移動する
''' </summary>
Public Shared Sub CopyFilesToDirectory(ByVal sourceFiles As String(), _
        ByVal destDir As String, ByVal move As Boolean)
    For Each sourcePath As String In sourceFiles
        'コピー先のパスを決定する
        Dim destName As String = System.IO.Path.GetFileName(sourcePath)
        Dim destPath As String = System.IO.Path.Combine(destDir, destName)
        If Not move Then
            'ファイルをコピーする
            System.IO.File.Copy(sourcePath, destPath)
        Else
            'ファイルを移動する
            System.IO.File.Move(sourcePath, destPath)
        End If
    Next
End Sub
C#
コードを隠すコードを選択
/// <summary>
/// 指定したフォルダにコピーまたは切り取られたファイルを貼り付ける
/// </summary>
public static void PasteFiles(string destDir)
{
    //クリップボードのデータを取得する
    IDataObject data = Clipboard.GetDataObject();
    //クリップボードにファイルドロップ形式のデータがあるか確認
    if (data != null && data.GetDataPresent(DataFormats.FileDrop))
    {
        //コピーされたファイルのリストを取得する
        string[] files = (string[])data.GetData(DataFormats.FileDrop);
        //DragDropEffectsを取得する
        DragDropEffects dde = GetPreferredDropEffect(data);
        if (dde == (DragDropEffects.Copy | DragDropEffects.Link))
        {
            //ファイルがコピーされていた時
            CopyFilesToDirectory(files, destDir, false);
        }
        else if (dde == DragDropEffects.Move)
        {
            //ファイルが切り取られていた時
            CopyFilesToDirectory(files, destDir, true);
        }
    }
}

/// <summary>
/// クリップボードの"Preferred DropEffect"を調べる
/// </summary>
public static DragDropEffects GetPreferredDropEffect(IDataObject data)
{
    DragDropEffects dde = DragDropEffects.None;

    if (data != null)
    {
        //Preferred DropEffect形式のデータを取得する
        System.IO.MemoryStream ms =
            (System.IO.MemoryStream)data.GetData("Preferred DropEffect");
        if (ms != null)
        {
            //先頭のバイトからDragDropEffectsを取得する
            dde = (DragDropEffects)ms.ReadByte();

            if (dde == (DragDropEffects.Copy | DragDropEffects.Link))
            {
                Console.WriteLine("コピー");
            }
            else if (dde == DragDropEffects.Move)
            {
                Console.WriteLine("切り取り");
            }
        }
    }

    return dde;
}

/// <summary>
/// 複数のファイルを指定したフォルダにコピーまたは移動する
/// </summary>
public static void CopyFilesToDirectory(string[] sourceFiles, string destDir, bool move)
{
    foreach (string sourcePath in sourceFiles)
    {
        //コピー先のパスを決定する
        string destName = System.IO.Path.GetFileName(sourcePath);
        string destPath = System.IO.Path.Combine(destDir, destName);
        if (!move)
        {
            //ファイルをコピーする
            System.IO.File.Copy(sourcePath, destPath);
        }
        else
        {
            //ファイルを移動する
            System.IO.File.Move(sourcePath, destPath);
        }
    }
}
  • 履歴:
  • 2007/2/18 .NET Framework 2.0に関する情報を追加。
  • 2010/4/6 切り取る方法、貼り付ける方法を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。