向各位高手请教,我想在程序里加上这样一个功能,从外部脱拽文件到程序里,如果文件是预期的,程序将自动打开该文件,并运行.(类似于,媒体播放软件,从外边脱拽影音文件,将自动被播放)

解决方案 »

  1.   

    如何在 Delphi 程序中支持文件拖放支持文件拖放关键在于两点 : 
    1 、使程序能接收 WM_DROPFILES  消息 ; 
    2 、在 WM_DROPFILES  消息的响应程序中取得被拖放的文件名,然后进行相应处理。  
    使程序能接收 WM_DROPFILES  消息  
         首先,需要调用 WINAPI DragAcceptFiles(handle,True); 其中的 handle 为要接收 WM_DROPFILES 消息的控件的 handle 。例如,我们要让 Memo1 接收该消息,则调用形式为 DragAcceptFiles(Form1.Memo1.handle,True); 
         其次,要在收到 WM_DROPFILES 消息时做处理,需要用自己的代码替换该控件的 WindowProc 方法。在替换前,要保存原来的 WindowProc 方法以便处理其他消息。为此,我们定义一个全程变量  OldWndProc:TWndMethod 保存原来的 WindowProc 方法 ; 再在窗体定义的 Public 段定义了一个方法 procedure DragFileProc(var Message: TMessage); 作为新的 WindowProc 方法。在 Unit 的 implementation  段内写下 DragFileProc 的完整代码,当消息为其他消息地调用 OldWndProc 来处理,当消息为 WM_DROPFILES 时,作相应处理。  
    取得被拖放的文件名,然后进行相应处理  
      在 WM_DROPFILES 消息的响应程序中,先调用 DragQueryFile(Message.wParam,$FFFFFFFF,nil,0) 返回值为拖放的文件总数。再循环调用 DragQueryFile(Message.wParam,i,buf,len); 取得拖放文件全名。 i 为 0 到拖放的文件总数减 1  的值,buf 为 Pchar 型,是存放文件名的缓冲区,len 为文件名缓冲区长度。至于取得文件名后的处理,就悉听尊便了。一定要注意 Pchar 和 String 的转换!  
    以下为程序片段  
    type 
            TForm1 = class(TForm) 
            . 
            . 
            . 
                btnEnableDragFile: TButton; 
            . 
            . 
            . 
                procedure btnEnableDragFileClick(Sender: TObject); 
            private 
                    { Private declarations } 
            public 
                    { Public declarations } 
                procedure DragFileProc(var Message: TMessage); 
            end; 
      
    implementation 
    var OLDWndProc:TWndMethod; 



    procedure TForm1.btnEnableDragFileClick(Sender: TObject); 
    begin 
            DragAcceptFiles(self.MemoDrag.Handle,true); 
            OLDWndProc:=self.MemoDrag.WindowProc; 
            // 保存原来的 WindowProc 
            self.MemoDrag.WindowProc:=self.DragFileProc; 
            // 设置新的 WindowProc 
    end; 
    procedure TForm1.DragFileProc(var Message:TMessage) ; 
    var i:word; 
    p:array[0..254]of char; 
    begin 
            if Message.Msg=WM_DropFiles 
            then 
                    begin 
                            self.MemoDrag.Clear; 
                            i:=DragQueryFile(Message.WParam,$FFFFFFFF,nil,0); 
                            // 取得拖放文件总数  
                            for i:=0 to i-1 do 
                            begin 
                                    DragQueryFile(Message.WParam,i,p,255); 
                                     // 取得拖放文件名  
                                    self.MemoDrag.Lines.add(StrPas(p)); 
                                    // 对文件的处理  
                            end; 
                    end 
        else // 其他消息,调用原来的处理程序  
                OLDWndProc(Message); 
    end; 



      

  2.   

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Dragacceptfiles(form1.handle,true);
    end;procedure tform1.wmdropfiles(var message:tmessage);
    var
      p:array[0..254] of char;
      i:word;
    begin
      inherited;
      memo1.lines.clear;
      {$IFDEF WIN32}
      I:=dragqueryfile(message.wparam,$ffffffff,nil,0);
      {$ELSE}
      I:=dragqueryfile(message.wparam,$ffff,nil,0);
      {$ENDIF}
      caption:=inttostr(i);
      for i:=0 to i-1 do
      begin
        dragqueryfile(message.wparam,i,p,255);
        memo1.lines.add(strpas(p));
      end;
    end;
    end.
      

  3.   

    AHM 的shell控件直接支持所有拖放,弹出菜单。
      

  4.   

    ---- 首先要说明的是下面的三个API 函数, 为通用起见, 函数说明 
    使用C 语言格式,  1. VOID DragAcceptFiles(
    HWND hWnd,
    BOOL fAccept   );
    ---- DragAcceptFiles 函数是用来为拖放文件作初始化, 它的第一个参 
    数hWnd 指明目标窗体的句柄, 第二个参数fAccept 是一个布尔型变 
    量, 为True 时则hWnd 所指向的窗体可以接受拖放的文件. 
    2. UINT DragQueryFile(
    HDROP hDrop,
        UINT iFile,
        LPTSTR lpszFile,
        UINT cch    )
    ---- DragQueryFile 函数用来查询拖放文件的文件名, 其本身的返回值 
    是一个无符号整数, 参数hDrop 是一个存放所拖放文件名称的数 
    据结构的句柄, 也就是文件名缓冲区的句柄, 需要从Windows 消息
    WM_DROPFILES 中获得.iFile 指明所要查询文件的序号, 它有两种取 
    值方式,1. 值为十六进制数FFFFFFFF 时,DragQueryFile 的返回值为所拖 
    放文件的数目;2. 值在0 到拖放文件总数之间时, DragQueryFile 函数将 
    相应序号的文件名放入参数lpszFile 所指向的缓冲区内, 若此时
    lpszFile 的值为NULL, 则DragQueryFile 会返回相应文件名的长度. 参数
    cch 决定缓冲区的长度, 由于Windows95 支持长文件名, 它的值不能 
    设得太小. 
    3.VOID DragFinish(  HDROP hDrop  );
    ---- 使用DragFinish 函数告诉Windows 拖放操作结束, 使其释放文件名 
    缓冲区, 它的参数hDrop 与DragQueryFiles 函数中的一样, 也由Windows 消 
    息WM_DROPFILES 的hDrop 参数获得. 
    ---- 下面将结合一个我编写的例子来说明具体的编程步骤. 本例 
    中窗体上放置了一个Memo 控件memo1, 在Windows 中选取数个文件拖 
    至程序窗体放下, 则memo1 中便会显示所选文件的总数及每个文 
    件的各自名称. 程序代码如下: unit Unit1;
    interface
    uses
      Windows, Messages, SysUtils, Classes, 
      Graphics, Controls, Forms, Dialogs,
      StdCtrls;
    type
      TForm1 = class(TForm)
        Memo1: TMemo;
        procedure FormCreate(Sender: TObject);
        procedure Label3Click(Sender: TObject);
        procedure Label4Click(Sender: TObject);
      private
             PROCEDURE FinishDropped ( VAR Msg : TMessage );
             Message WM_DropFiles ;
        { Private declarations }
      public
        { Public declarations }
      end;
    var
      Form1: TForm1;
    implementation
    uses shellapi;
    {$R *.DFM}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
         //initialize the drag process;
         DragAcceptFiles(Handle,True);
    end;
    Procedure TForm1.FinishDropped ( VAR Msg : TMessage ) ;
    Var
       hDrop : THandle ;
       iFile:Uint;
       lpszFile :pchar;
       CountOfFiles : integer ;
       FileIndex : integer ;
       ReSults : string ;
       begin
            hDrop := Msg.WParam ;
    getmem(pchar,255);
    iFile:=$FFFFFFFF;
            CountOfFiles := DragQueryFile(hDrop,iFile,lpszFile,254);
            ReSults := '' ;
            for FileIndex := 0  CountOfFiles-1 do
               begin
    iFile:=FileIndex;
                    DragQueryFile(hDrop,iFile,lpszFile,254);
                    // Get the File names by order;
                    ReSults := ReSults + #13#10 + lpszFile ;
                end ;
    Dispose(lpszFile);
            memo1.Clear;
            memo1.lines.add(' 拖放了'+IntToStr
            (CountOfFiles) + ' 个文件:' + ReSults );
            DragFinish ( hDrop);
    end ;
    end.
    ---- 从以上代码可以看出, 首先应该在窗体的OnCreate 事件中用
    DragAccepteFiles 来说明程序窗体支持文件的拖放. 
    ---- 另外, 除了调用以上3 个API 函数, 在Delphi 中还应编写针对
    WM_DROPFILES 的消息处理过程FinishDropped, 截取了WM_DROPFILES, 由 
    其wParam 才能够得到文件名缓冲区的句柄. ---- 在FinishDropped 过程里, 有两处DragQueryFile 函数, 第一处其iFile 参数 
    为$FFFFFFFF, 得到拖放文件的总数; 第二处iFile 参数为每个文件的 
    序号, 则可在lpszFile 中可得到相应的文件名. 当然, 为了明显的对比
    iFile 的值对DragQueryFile 函数的影响, 这里的代码不够简练. 有一点 
    需要注意的是,lpszFile 是Pchar 型的变量, 为了程序运行安全, 它使用 
    前需用getmem 过程为其分配内存, 使用后再用dispose 过程将其释放. 
    在FinishDropped 过程的最后, 用DragFinish 函数释放文件名缓冲区