2017-08-25 116 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

我沒有想過這方面,所以我希望現在這個例子是正確的。我離開了循環,因爲它很好地展示瞭如何在需要時訪問多個文件。 –

相關問題