Q&A

  • Listview 에서 드래그해서 바탕화면이나 탐색기에 드랍을 시킬때
안녕 하십니까..  ^^
늘 도움만 받아가는 초봅니다 ~
FTP 같은 어플리케이션을 구현하려다가
문제가 좀 있어서 여기저기 검색하다가 이 정욱님께서 올린 글을 보았습니다.

제 어플리케이션의 LIstView 에 서버에 저장돼어있는 파일의 List 들이 잇습니다.
이 Listview 에서 드래그해서 바탕화면이나 탐색기에 드랍을 시킬때 Target  이 돼는 바탕화면이나 탐색기의 Fullpath 가 어떻게 돼는지 알고싶어서요..
.
이정욱 님께서는 이 문제를 어떻게 처리 하셧는지요 ..

아래는 아주 오랜전에 이정욱 님께서 올리신 글입니다 ~ ~


[질문]Drag&Drop에 관하여... ^^;  


안녕하세요?

답변만 하다가 질문도 하네요.. 히..

Drag&Drop을 하는데 생각보다 어렵네요.

바탕화면에 있는것이라던가 탐색이에 있는것을 내쪽으로 끌어오는것을 할 수 있겠는데 문제는 내쪽에 있는 객체나 파일을 바탕화면이나 탐색기로 끌어다가 놓으려니 그게 조금 어렵네요.

누구의 말로는 COM객체를 사용해서 한다고 하지만 전 잘 모르겠어요..흑...



혹시 이것에 대해 잘 아시는 분 계시면 답변좀 부탁드립니다.

감사합니다.

1  COMMENTS
  • Profile
    황준동 2005.06.04 03:54
    힘들게 구한 자료 입니다.

    도움 되셨으면 좋겠네요...

    그럼...


    <!--CodeS-->
    {This example will show you how your application
    will be able to copy files from your application to
    Windows Explorer using Drag'n' Drop.
    Exactly the way it is done by the OS itself!

    Create a new application containing just one unit,
    called 'Unit1'. Drop a FileListBox and a DirectoryListBox on to the form,
    leave their names the way they are.
    Connect FileListBox1 with DirectoryListBox1 by setting the FileList-property of
    DirectoryListBox1. Make sure that the MultiSelect-property of FileListBox1 is set to 'True'!

    The best thing you can do now is to replace all text with the code below:}

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

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
      Dialogs,
      StdCtrls, FileCtrl, ActiveX, ShlObj, ComObj;

    type
      TForm1 = class(TForm, IDropSource)
        DirectoryListBox1: TDirectoryListBox;
        FileListBox1: TFileListBox;

        procedure FileListBox1MouseDown(Sender: TObject; Button:
          TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure FileListBox1MouseMove(Sender: TObject; Shift: TShiftState;
          X,
          Y: Integer);
      private
        FDragStartPos: TPoint;
        function QueryContinueDrag(fEscapePressed: BOOL;
          grfKeyState: Longint): HResult; stdcall;
        function GiveFeedback(dwEffect: Longint): HResult; stdcall;
      public
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.DFM}

    function GetFileListDataObject(const Directory: string; Files:
      TStrings):
      IDataObject;
    type
      PArrayOfPItemIDList = ^TArrayOfPItemIDList;
      TArrayOfPItemIDList = array[0..0] of PItemIDList;
    var
      Malloc: IMalloc;
      Root: IShellFolder;
      FolderPidl: PItemIDList;
      Folder: IShellFolder;
      p: PArrayOfPItemIDList;
      chEaten: ULONG;
      dwAttributes: ULONG;
      FileCount: Integer;
      i: Integer;
    begin
      Result := nil;
      if Files.Count = 0 then
        Exit;
      OleCheck(SHGetMalloc(Malloc));
      OleCheck(SHGetDesktopFolder(Root));
      OleCheck(Root.ParseDisplayName(0, nil,
        PWideChar(WideString(Directory)),
        chEaten, FolderPidl, dwAttributes));
      try
        OleCheck(Root.BindToObject(FolderPidl, nil, IShellFolder,
          Pointer(Folder)));
        FileCount := Files.Count;
        p := AllocMem(SizeOf(PItemIDList) * FileCount);
        try
          for i := 0 to FileCount - 1 do
          begin
            OleCheck(Folder.ParseDisplayName(0, nil,
              PWideChar(WideString(Files[i])), chEaten, p^[i],
              dwAttributes));
          end;
          OleCheck(Folder.GetUIObjectOf(0, FileCount, p^[0], IDataObject,
            nil,
            Pointer(Result)));
        finally
          for i := 0 to FileCount - 1 do begin
            if p^[i] <> nil then Malloc.Free(p^[i]);
          end;
          FreeMem(p);
        end;
      finally
        Malloc.Free(FolderPidl);
      end;
    end;

    function TForm1.QueryContinueDrag(fEscapePressed: BOOL;
      grfKeyState: Longint): HResult; stdcall;
    begin
      if fEscapePressed or (grfKeyState and MK_RBUTTON = MK_RBUTTON) then
      begin
        Result := DRAGDROP_S_CANCEL
      end else if grfKeyState and MK_LBUTTON = 0 then
      begin
        Result := DRAGDROP_S_DROP
      end else
      begin
        Result := S_OK;
      end;
    end;

    function TForm1.GiveFeedback(dwEffect: Longint): HResult; stdcall;
    begin
      Result := DRAGDROP_S_USEDEFAULTCURSORS;
    end;

    procedure TForm1.FileListBox1MouseDown(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then
      begin
        FDragStartPos.x := X;
        FDragStartPos.y := Y;
      end;
    end;

    procedure TForm1.FileListBox1MouseMove(Sender: TObject; Shift:
      TShiftState;
      X, Y: Integer);
    const
      Threshold = 5;
    var
      SelFileList: TStrings;
      i: Integer;
      DataObject: IDataObject;
      Effect: LongInt;  // DWORD
    begin
      with Sender as TFileListBox do
      begin
        if (SelCount > 0) and (csLButtonDown in ControlState)
          and ((Abs(X - FDragStartPos.x) >= Threshold)
          or (Abs(Y - FDragStartPos.y) >= Threshold)) then
          begin
          Perform(WM_LBUTTONUP, 0, MakeLong(X, Y));
          SelFileList := TStringList.Create;
          try
            SelFileList.Capacity := SelCount;
            for i := 0 to Items.Count - 1 do
              if Selected[i] then SelFileList.Add(Items[i]);
            DataObject := GetFileListDataObject(Directory, SelFileList);
          finally
            SelFileList.Free;
          end;
          Effect := DROPEFFECT_NONE;
          DoDragDrop(DataObject, Self, DROPEFFECT_COPY, Effect);
        end;
      end;
    end;

    initialization
      OleInitialize(nil);
    finalization
      OleUninitialize;
    end.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {
    As you might have seen, TForm1 is not only a member of class TForm,
    but also of class IDropSource!

    Now make sure that the two FileListBox events
    'OnMouseMove' and 'OnMouseDown' are set correctly.

    Run your application and try out the Drag and Drop feature!
    You can select multiple items to drag and press escape to cancel.
    The cursor will show you what action will take place.
    }

    <!--CodeE-->