2017-08-25 122 views
1

我正在编写一个程序,可以将文本文件拖放到表单上,以便通过RichEdit显示和编辑它。RichEdit如何在BCB或Delphi程序中接受文件拖放?

我用ChangeWindowMessageFilterEx确保WM_DROPFILES和WM_COPYDATA可以通过我的主要形式接收:

ChangeWindowMessageFilterEx(Handle, WM_DROPFILES, MSGFLT_ADD, NULL); 
    ChangeWindowMessageFilterEx(Handle, WM_COPYDATA, MSGFLT_ADD, NULL); 
    ChangeWindowMessageFilter(73 , MSGFLT_ADD); 

,并调用表单制作功能DragAcceptFiles(Handle, true)

现在拖动操作是有效的在窗口的任何地方,但除了在RichEdit,光标显示在RichEdit中拖动时否认图标。

拖动任何组件,例如。文本编辑器,面板,组合框和按钮,可以导致接收WM_DROPFILES消息,但RichEdit除外。

其实,我敢肯定,有可能在RichEdit中拖动文件,因为我写的代码,去年,但我已经失去了源代码,忘了。我正在尝试重建同一个。

这里是the google drive download link到我已在去年完成的可执行文件。这里是github url来我目前写的未完成的源代码。

谢谢您的关注。

回答

1

我不知道为什么TRichEdit使用消息映射时,没有收到WM_DROPFILES,但你可以处理TRichEditWindowProc

一个possilble实施看起来是这样的:

  • 删除一个TRichEdit窗体上
  • 修改头文件

    private:  
    TWndMethod OldWindowProc; 
    void __fastcall NewWindowProc(TMessage& Msg); 
    
  • 添加实施

    __fastcall TForm1::TForm1(TComponent* Owner) 
    : TForm(Owner) 
    { 
        OldWindowProc = RichEdit1->WindowProc; 
        RichEdit1->WindowProc = NewWindowProc; 
        DragAcceptFiles(RichEdit1->Handle, true); 
    }  
    
    void __fastcall TForm1::NewWindowProc(TMessage& Msg) 
    { 
        switch (Msg.Msg) { 
         case WM_DROPFILES: 
         { 
          HDROP DropH = (HDROP)Msg.WParam; 
          int droppedFileCount = DragQueryFile(DropH, 0xFFFFFFFF, NULL, 0); 
          TStringList* Buffer = new TStringList(); 
          for (int i = 0; i < droppedFileCount; i++) { 
           int fileNameLength = DragQueryFile(DropH, i, NULL, 0); 
           String FileName; 
           FileName.SetLength(fileNameLength); 
           DragQueryFile(DropH, i, FileName.w_str(), fileNameLength + 1); 
           Buffer->LoadFromFile(FileName); 
           RichEdit1->Lines->AddStrings(Buffer); 
           RichEdit1->Lines->Add(""); 
          } 
          delete Buffer; 
          DragFinish(DropH); 
          Msg.Result = 0; 
          break; 
         } 
         case CM_RECREATEWND: 
          DragAcceptFiles(RichEdit1->Handle, true); 
          break; 
        default:; 
        } 
        OldWindowProc(Msg); 
    }   
    
+0

如果注册用'DragAcceptFiles一个VCL窗口()'(或'RegisterDragDrop()',就此而言),则必须处理窗口娱乐活动所以可以将每个一个娱乐发生时间重新注册新视窗。在上面的例子中,这意味着'NewWindowProc()'需要处理'CM_RECREATEWND'消息。一个更好的解决方案是从'TRichEdit'派生一个新的类,并覆盖虚拟的'CreateWnd()'方法(你可以在'TForm'中做同样的事情)。此外,在循环中调用'RichEdit1-> Lines-> LoadFromFile()'是没有用的,因为只有加载的最后一个文件会在UI中看到。所以摆脱循环。 –

+0

谢谢你的回答。我以为我找到了一些理由。这与管理员访问权限有关。 对于程序with'DragAcceptFiles()'主窗体的初始化,由普通用户打开可以在任何地方的窗口中拖动文件图标来触发文件放置消息,无论你拖&下降了什么样的孩子组成部分。 但使用管理员帐户打开程序,拖放,当在某个组件的位置是禁止的(如RichEdit中,一个的PageControl的TabSheets)。这是我的观察,但有可能是一个更好的解释。 – jl81

+0

我没有想过这方面,所以我希望现在这个例子是正确的。我离开了循环,因为它很好地展示了如何在需要时访问多个文件。 –

相关问题