由于 OP 似乎要求我最初理解的其他内容,因此我有以下答案:
{$J+}
USES Windows;
{$IFDEF UNICODE }
FUNCTION FileHandleToFileName(Handle : THandle) : STRING;
BEGIN
SetLength(Result,MAX_PATH+1);
TRY
SetLength(Result,GetFinalPathNameByHandle(Handle,@Result[LOW(Result)],LENGTH(Result),FILE_NAME_NORMALIZED))
EXCEPT
ON E:EExternalException DO SetLength(Result,0) ELSE RAISE
END;
IF COPY(Result,1,4)='\\?\' THEN DELETE(Result,1,4)
END;
{$ELSE }
CONST FILE_NAME_NORMALIZED = $00000000;
FUNCTION GetFinalPathNameByHandleUndefined(hFile : THandle ; lpszFilePath : PChar ; cchFilePath,dwFlags : DWORD) : DWORD; stdcall;
BEGIN
StrPCopy(lpszFilePath,'');
Result:=0
END;
FUNCTION FileHandleToFileName(Handle : THandle) : STRING;
TYPE
TGetFinalPathNameByHandle = FUNCTION(hFile : THandle ; lpszFilePath : PChar ; cchFilePath,dwFlags : DWORD) : DWORD; stdcall;
CONST
GetFinalPathNameByHandle : TGetFinalPathNameByHandle = NIL;
VAR
Err : Cardinal;
BEGIN
IF NOT Assigned(GetFinalPathNameByHandle) THEN BEGIN
GetFinalPathNameByHandle:=GetProcAddress(GetModuleHandle('kernel32'),'GetFinalPathNameByHandleA');
IF NOT Assigned(GetFinalPathNameByHandle) THEN GetFinalPathNameByHandle:=GetFinalPathNameByHandleUndefined
END;
SetLength(Result,MAX_PATH+1);
SetLength(Result,GetFinalPathNameByHandle(Handle,@Result[1],LENGTH(Result),FILE_NAME_NORMALIZED));
IF COPY(Result,1,4)='\\?\' THEN DELETE(Result,1,4)
END;
{$ENDIF }
FUNCTION FileNameOf(VAR TXT : TextFile) : STRING;
VAR
Handle : THandle;
BEGIN
Handle:=TTextRec(TXT).Handle;
Result:=FileHandleToFileName(Handle);
IF Result='' THEN Result:=StrPas(TTextRec(TXT).Name)
END;
我目前使用 UNICODE 定义来确定 Delphi 是否已经有 GetFinalPathNameByHandle 的导入定义 - 如果我发现哪个版本实际实现了这个定义,它可能会被微调。
另请注意,GetFinalPathNameByHandle 仅适用于 Windows Vista 及更高版本。如果尝试在以前的版本上运行,它将退回到简单地提取分配的文件名。如果您需要对 pre-Vista 的支持,您可以查看 David 链接到的页面,以获取适用于早期版本的版本。