C++ Builder CE tips

ファイルドラグアンドドロップできるようにしてみよう VCL版

VCLでWindowsのファイルエクスプローラーからファイルのDrag and Dropを受け付けられるようにします。FMXでも可能ですが、今回はVCLでインプリメントします。VCLで新規プログラムを作ります。フォームにまずはTMemoでも貼って、そのプロパティーのAlignalBottomにでもしておきましょう。上側のハンドルを適宜引き上げて、いい案配にしておきます。お好みないしデザインセンスでご自由に。この状態のフォームが、

とりあえず、当面これだけ。ここで一旦セーブしておきましょう。この状態でUnit1.hは、

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TMemo *Memo1;
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

ですが、Drag and Dropに対応するために、少しだけコードを追加しないといけません。private:

  void __fastcall WMDropFiles(TWMDropFiles &Message);

を、__fastcall TForm1(TComponent* Owner);の次の行から、

protected:
//追加
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles)
END_MESSAGE_MAP(TForm)

を追加します。結局Unit1.hは、

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TMemo *Memo1;
private:	// ユーザー宣言
  void __fastcall WMDropFiles(TWMDropFiles &Message);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
protected:
//追加
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

となります。ファイルをドラグアンドドロップした時に呼び出されるWMDropFiles()Unit1.cpp側に用意します。

void __fastcall TForm1::WMDropFiles(TWMDropFiles &Message)
{   
  const unsigned int count = DragQueryFile((HDROP)Message.Drop, -1, NULL, 0);
  for (unsigned int i = 0; i < count; ++i)
  {   
    const unsigned int length = DragQueryFile((HDROP)Message.Drop, i, NULL, 0);
    std::unique_ptr<wchar_t[]> filename(new wchar_t[length + 1]);
   
    DragQueryFile((HDROP)Message.Drop, i, filename.get(), length + 1);    
	Parse_File(filename.get());

  }
}

Unit1.cpp全体は、

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


#include <vcl.h>
#pragma hdrstop

#include <memory>

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Memo1->Lines->Clear();
  DragAcceptFiles(this->Handle, true);
}
//---------------------------------------------------------------------------
void Parse_File(UnicodeString filename)
{
   Form1->Memo1->Lines->Add(filename);
}

void __fastcall TForm1::WMDropFiles(TWMDropFiles &Message)
{

  const unsigned int count = DragQueryFile((HDROP)Message.Drop, -1, NULL, 0);
  for (unsigned int i = 0; i < count; ++i)
  {

	const unsigned int length = DragQueryFile((HDROP)Message.Drop, i, NULL, 0);
	std::unique_ptr<wchar_t[]> filename(new wchar_t[length + 1]);

	DragQueryFile((HDROP)Message.Drop, i, filename.get(), length + 1);

	Parse_File(filename.get());

  }
}

となります。gesourceさんのサイトhttps://www.gesource.jp/programming/bcb/109.htmlを参考にしました。ここでスマートポインタを使っている関係で、トップの#include <memory>が必要です。今のParse_File(filename)は、ファイル名をMemo1に表示するだけですが、関数の中身を変えていきます。さて、build and runしてみましょう。

このフォーム上にエクスプローラーからファイルの実体を掴んで、持ってきて落とします。その経緯を記録した動画は、

となります。複数のファイルを選択して、drag and dropしてもおけです。続きではjpg画像ファイルのexim情報を抜き出すプログラムを作る予定です。その前にFMXでのdrag and dropかな。

コメント

  1. […] VCLやらFMXでエクスプローラーからフォームへのファイルのドラグアンドドロップを実現するためのやり方を3通り示しましたが、2番目の方法でjpegファイルをドラグアンドドロップすると撮影日時を表示するものを作りました。元のプログラムは、これC++ Builder CE tipsです。 […]