RichEdit如何在BC或Delphi程序中接受文件拖放?

How RichEdit can accept file drag & dropping in BCB or Delphi program?

我正在编写一个程序,可以将文本文件拖放到表单上以通过 RichEdit 显示和编辑它。

我已经使用 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)

现在拖动操作在window的任何地方都有效,但除了RichEdit,在RichEdit上拖动时光标显示一个拒绝图标。

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

其实我确定RichEdit是可以拖拽文件的,因为我去年写过代码,但是我丢了源码忘记了。我现在正在尝试重建同一个。

这是the google drive download link to the executable file that I have finished last year. And here is the github url我目前正在编写的未完成的源代码。

感谢您的收看

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

一个可能的实现可能如下所示:

  • 在您的表单上添加 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);
    }