我在 Delphi XE 中使用IPreviewHandler接口来查看 Adobe PDF 文件列表。一切正常,除了第一个视图关闭时(界面被破坏)有大约 20 秒的长时间延迟。所有后续视图都正常进行,没有这种延迟,当然,直到我重新启动应用程序。
有没有人经历过这种奇怪的行为,这可能是什么原因?
另一个开发人员在另一台机器上可以重现该问题。操作系统是 Windows 7 Ultimate,Adobe Reader XI 是 v11.0.3。
CLSID='{DC6EFB56-9CFA-464D-8880-44885D7DC193}'。代码片段:
TqdPreviewControl = class(TCustomControl)
private
FResult : HRESULT;
FFileName : string;
FLastError: string;
FComPreviewHandler : IPreviewHandler;
function IsOk(Ret : HRESULT) : boolean;
function UpdatePreviewSize :boolean;
class function GetCLSIDForFileName(AFileName: string): string; static;
function PreviewFile :boolean;
procedure SetFileName(const Value: string);
protected
procedure Resize; override;
public
constructor Create(AOwner :TComponent); override;
destructor Destroy; override;
property FileName: string read FFileName write SetFileName;
property LastError: string read FLastError;
end;
destructor TqdPreviewControl.Destroy;
begin
if FComPreviewHandler <> nil then
FComPreviewHandler.Unload; // this helps to reduce first delay to 5 sec
FComPreviewHandler := nil; //! only on first destroy spends here 20 sec
inherited Destroy;
end;
function TqdPreviewControl.PreviewFile :boolean;
var
ACLSID: string;
AGUID: TGUID;
AInit: IInitializeWithStream;
AFile: PWideChar;
StreamAdapter : IStream;
Stream : TMemoryStream;
Size : TRect;
begin
Result := false;
FLastError := '';
ACLSID := GetCLSIDForFileName(FFileName);
if (ACLSID = '') then begin
FLastError := 'No CLSID';
Exit;
end;
AGUID := StringToGUID(ACLSID);
FComPreviewHandler := CreateComObject(AGUID) as IPreviewHandler;
if (FComPreviewHandler = nil) then
begin
FLastError := 'No Handler';
Exit;
end;
AInit := FComPreviewHandler as IInitializeWithStream;
Stream := TMemoryStream.Create;
Stream.LoadFromFile(FFileName);
StreamAdapter := TStreamAdapter.Create(Stream, soOwned);
FResult := AInit.Initialize(StreamAdapter as IStream, STGM_READ);
StreamAdapter := nil;
Size := Rect(0, 0, Width, Height);
if not IsOk(FComPreviewHandler.SetWindow(Handle, Size)) then
Exit;
if not UpdatePreviewSize then
Exit;
if IsOk(FComPreviewHandler.DoPreview) then
Result := true;
end;
更新:找到了一个有用的方法 - 卸载,这将延迟从 20 秒减少到 5 秒。
更新:进一步按摩已将 Application.ProcessMessages 放入析构函数中,这允许拥有的表单立即关闭,但延迟被转移到冻结 5 秒的父表单。在视觉上仍然比在半更新状态下看到关闭视图要好一些。
更新:使用 Foxit 预览处理程序确认延迟确实是 Adobe 的工件,与 Delphi 代码完全无关