C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[185] 빌더에서 탐색기로부터의 Drag&Drop을 자유롭게 해 보자.
김태선 [cppbuilder] 18539 읽음    2009-02-17 22:03
C++빌더 개발자들이 드래그&드롭은 가끔씩 사용하고 자료를 구하기 어렵지도 않습니다.
가장 복사해서 사용하기 쉬운 형태는 아마도 폼 파일 헤더파일에 아래와 같이 처리하는 것이 아닌가 합니다.
//---------------------------------------------------------------------------

class TFormMain : public TForm
{
__published:	// IDE-managed Components
	TLabel *Label1;
	TListView *ListView1;
	TBitBtn *BitBtn1;
	TBitBtn *BitBtn2;
	TLabel *Label2;
	TBitBtn *BitBtn3;
	void __fastcall FormCreate(TObject *Sender);
	void __fastcall BitBtn1Click(TObject *Sender);
private:	// User declarations

protected:

protected:
	BEGIN_MESSAGE_MAP
		MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles)	// 드롭 메시지 받아 들이기.
	END_MESSAGE_MAP(TForm)

	// 드래그&드롭 메시지 핸들러
	//
	void __fastcall WMDropFiles(TWMDropFiles &msg)
	{
		int  nFileCount = DragQueryFile((HDROP)msg.Drop, 0xFFFFFFFF, NULL, 0);
		for(int c = 0; c < nFileCount; c++)
		{
			char filename[MAX_PATH];
			int  nLength = DragQueryFile((HDROP)msg.Drop, c, filename, MAX_PATH);

			// Do something..
			if (nLength)
				AddFile(filename);
		}
		DragFinish((HDROP)msg.Drop);
	}
	// 드래그 받을 WinControl을 지정하는 부분. FormCreate 핸들러에서 호출하는게 좋음.
	//
	void	InitDragAccept()
	{
		DragAcceptFiles(Handle, true);
	}
public:		// User declarations
	__fastcall TFormMain(TComponent* Owner);

	void	AddFile(String filename);

};
//---------------------------------------------------------------------------

헤더는 이렇게 하면 되고,  FormCreate 이벤트 핸들러에서 이렇게 호출해주면
드래그&드롭을 받아 들일 준비가 됩니다.
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormCreate(TObject *Sender)
{
	InitDragAccept();
}
//---------------------------------------------------------------------------

드래그&드롭이 일어나면 WM_DROPFILES 메시지가 발생하고,
이를 처리해주면 됩니다.
소스를 보면 쉽게 알수 있듯이 몇개의 파일 또는 폴더 명이 드롭되었나 구한 뒤,
for 루프를 돌며 개개별로 실제 이름을 구해서 그것을 처리해주면 됩니다.

위와 같이 구성한 이유는 쉽게 복사해서 사용하기 위해서 저렇게 한 것입니다.

이렇게 하면 폼 전체가 Drag&Drop을 받아 들이게 됩니다.

여기까지는 쉽게 알수 있는데, 문제는 폼 위의 특정한 컨트롤만 드래그&드롭을 받아 들이게 하고 싶을때는
어떻게 하는게 가장 쉬울까요?
프로그램 만들다 보면 이런 요구가 가끔씩 생기게 되는데, 이는 어떻게 처리하는게 가장 간편할까요?
이에 대한 코드로 컴포넌트 교체식으로 구현해 봤는데,
역시 마찬가지로 가장 쉽게 복사해서 쓸수 있는 형태로 아래처럼 꾸몄습니다.

예제는  폼위의 TListView 에 파일명이 열거되게 하고 싶고, 여기에 드래그 & 드롭을 받아 들이게 하고 싶을때
처리하는 방법입니다.

void	AddFile(String filename);

//---------------------------------------------------------------------------
// TListView 에만 드래그&드롭을 받는 방법

class TListView : public Comctrls::TListView
{
	typedef Comctrls::TListView		inherited;
public:
	BEGIN_MESSAGE_MAP
		MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles)	// 드롭 메시지 받아 들이기.
	END_MESSAGE_MAP(inherited)

	// 드래그&드롭 메시지 핸들러
	//
	void __fastcall WMDropFiles(TWMDropFiles &msg)
	{
		int  nFileCount = DragQueryFile((HDROP)msg.Drop, 0xFFFFFFFF, NULL, 0);
		for(int c = 0; c < nFileCount; c++)
		{
			char filename[MAX_PATH];
			int  nLength = DragQueryFile((HDROP)msg.Drop, c, filename, MAX_PATH);

			// Do something..
			if (nLength)
				AddFile(filename);
		}
		DragFinish((HDROP)msg.Drop);
	}
	// 드래그 받을 WinControl을 지정하는 부분. FormCreate 핸들러에서 호출하는게 좋음.
	//
	void	InitDragAccept()
	{
		DragAcceptFiles(Handle, true);
	}
};
#define TListView		::TListView

//---------------------------------------------------------------------------
이 부분을 헤더 파일
class TForm1 : public TForm
바로 위에 두면 됩니다.

그러면 TListView 컨트롤만 드래그&드롭을 받을 수 있습니다.
초기화는 FormCreate 핸들러에서 아래처럼  ListView1 인스턴스가 드래그&드롭을 받아 들이게 해주면 됩니다.
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormCreate(TObject *Sender)
{
	ListView1->InitDragAccept();
}
//---------------------------------------------------------------------------

이렇게 하면 TListView 의 인스턴스 중에서 ListView1 만 드래그&드롭을 받아 들이게 됩니다.
TListView 뿐만 아니라 TWinControl 후손이면
모든 컨트롤에 이와 같은 방법을 쓸수 있습니다.

들어온 파일명은 대략 아래처럼 처리할 수 있고요...

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

void	TFormMain::AddFile(String filename)
{
	TListItems  *items = ListView1->Items;
	TListItem   *item = items->Add();
	item->Caption = filename;
}

void	AddFile(String filename)
{
	FormMain->AddFile(filename);
}

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


이렇게 컴포넌트 교체식으로 해결하지 않으면
메시지 핸들러를 서브클래싱해서 해결하면 됩니다.

이 부분은 장성호님 강좌가 잘 되어 있으니 보시면 됩니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=622


그럼.
김태선 [cppbuilder]   2009-02-19 14:50 X
델파이로 빌더와 똑같이 컴포넌트 교체식으로 위와 같이 특정 TListView 객체만 드래그&드롭을 받게 하고 싶으면
다음과 같이 코딩하면 됩니다. 빌더와 마찬가지로 매우 간편하게 처리 가능합니다.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ShellApi;

type
  TListView = class(ComCtrls.TListView)
  protected
    procedure WMDropFiles(var msg: TWMDropFiles); message WM_DROPFILES;
  public
    procedure InitDragAccept();
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    procedure  AddFile(filename: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListView1.InitDragAccept;
end;

procedure  TForm1.AddFile(filename: string);
var
  item: TListItem;
begin
  item := ListView1.Items.Add;
  item.Caption := filename;
end;

procedure  AddFile(filename: string);
begin
  Form1.AddFile(filename);
end;

{ TListView }

procedure TListView.InitDragAccept;
begin
  DragAcceptFiles(Handle, true);
end;

procedure TListView.WMDropFiles(var msg: TWMDropFiles);
var
  c,
  nFileCount: integer;
  filename: array[0..MAX_PATH] of char;
begin
  nFileCount := DragQueryFile(msg.Drop, $FFFFFFFF, nil, 0);
  for c := 0 to nFileCount - 1 do begin
    DragQueryFile(msg.Drop, c, filename, MAX_PATH);
    AddFile(filename);
  end;
  DragFinish(msg.Drop);
end;

end.

+ -

관련 글 리스트
185 빌더에서 탐색기로부터의 Drag&Drop을 자유롭게 해 보자. 김태선 18539 2009/02/17
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.