我的表單支持從 Windows 資源管理器中拖放檔案:
uses
ShellApi, System.IOUtils;
procedure TFormMain.FormCreate(Sender: TObject);
begin
DragAcceptFiles(Self.Handle, True);
end;
procedure TFormMain.WMDropFiles(var Msg: TMessage);
var
hDrop: THandle;
FileCount, NameLen, i: Integer;
CurrFile: String;
FileSysEntries: TArray<String>;
begin
inherited;
hDrop := Msg.wParam;
try
FileCount := DragQueryFile(hDrop, $FFFFFFFF, nil, 0);
for i := 0 to FileCount - 1 do
begin
NameLen := DragQueryFile(hDrop, i, nil, 0) 1; // 1 for NULL
SetLength(CurrFile, NameLen);
DragQueryFile(hDrop, i, PWideChar(CurrFile), NameLen);
//If I don't do this...
SetLength(CurrFile, StrLen(PWideChar(CurrFile)));
if DirectoryExists(CurrFile) then
begin
//...I get a stack overflow here!
FileSysEntries := TDirectory.GetFiles(CurrFile, '*.*', TSearchOption.soAllDirectories);
//Rest removed for clarity...
end;
end;
finally
DragFinish(hDrop);
end;
end;
現在,如果我不#0從CurrFile字串中去除NULL ( ) 字符(參見第二個SetLength),我會在呼叫時出現堆疊溢位TDirectory.GetFiles,現在我知道為什么了。
第二個SetLength(那條#0)真的有必要還是我應該做NameLen - 1第一個SetLength?或者也許是別的什么?
uj5u.com熱心網友回復:
我看到幾個問題:
您
DragAcceptFiles()只在表單的OnCreate事件中呼叫。如果HWND在表單的生命周期內重新創建表單(它可能發生!),您將失去接收WM_DROPFILES訊息的能力。您需要
DragAcceptFiles()使用更新的HWND. 您可以覆寫 Form 的虛擬CreateWnd()方法來處理它。或者,您可以覆寫 Form 的虛擬
CreateParams()方法來WS_EX_ACCEPTFILES為每個HWND創建的視窗啟用擴展視窗樣式。您的訊息處理程式正在呼叫
inherited. 你并不需要這么做。默認處理程式不會對訊息執行任何操作。您為
CurrFile. 從技術上講,您在呼叫 時不需要包含空終止符SetLength(),因為它會自動為一個空間分配額外的空間(Delphistring隱式以空終止,因此PChar強制轉換可以與需要空終止字符指標的 C 樣式 API 一起使用) .如果您確實在
string's 的長度中包含空終止符,那么您必須在之后顯式縮小strings 長度,這是您正在做的(但效率不高,因為它DragQueryFile(i)會告訴您在沒有空終止符的情況下使用的長度,因此您不必使用StrLen())手動計算它。但是,最好不要一開始就過度分配。顯然,具有額外
#0的字串的長度是造成問題TDirectory.GetFiles()(或者更可能TPath,其TDirectory內部使用)。你應該提交一份關于這個的錯誤報告。但是,您確實需要確保不要#0在字串的長度中留下終止符作為開始,因為檔案系統路徑 API 無論如何都不接受它。
試試這個:
uses
ShellApi, System.IOUtils;
procedure TFormMain.CreateWnd;
begin
inherited;
DragAcceptFiles(Self.Handle, True);
end;
procedure TFormMain.WMDropFiles(var Msg: TMessage);
var
hDrop: THandle;
FileCount, NameLen, i: Integer;
CurrFile: String;
FileSysEntries: TArray<String>;
begin
hDrop := Msg.wParam;
try
FileCount := DragQueryFile(hDrop, $FFFFFFFF, nil, 0);
for i := 0 to FileCount - 1 do
begin
NameLen := DragQueryFile(hDrop, i, nil, 0);
SetLength(CurrFile, NameLen);
DragQueryFile(hDrop, i, PChar(CurrFile), NameLen 1);
if TDirectory.Exists(CurrFile) then
begin
FileSysEntries := TDirectory.GetFiles(CurrFile, '*.*', TSearchOption.soAllDirectories);
//...
end;
end;
finally
DragFinish(hDrop);
end;
end;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314729.html
標籤:德尔福 登录 拖放 delphi-10.4-悉尼 获取文件
