在一个小应用程序中,我想在创建主窗体之前显示一个打开的文件对话框。我在 *.dpr 中这样做:

begin
  Application.Initialize;
  Init; // <=========================================
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

当我使用以下 Init 过程时:
procedure Init;
var
  OpenDialog: TOpenDialog;
begin
  TheFileName := '(nix)';

  OpenDialog := TOpenDialog.Create(nil);
  try
    if OpenDialog.Execute then
      TheFileName := OpenDialog.FileName
    else
      Exit;
  finally
    OpenDialog.Free;
  end;
end;

在 Windows 7 下没有显示对话框。我可以通过将 UseLatestCommonDialogs 设置为 False 来解决这个问题,但我想避免这种情况。将 Init 过程更改为
procedure Init;
var
  OpenDialog: TOpenDialog;
begin
  TheFileName := '(nix)';

  CoInitialize(nil);
  try
    OpenDialog := TOpenDialog.Create(nil);
    try
      if OpenDialog.Execute then
        TheFileName := OpenDialog.FileName
      else
        Exit;
    finally
      OpenDialog.Free;
    end;
  finally
    CoUninitialize;
  end;
end;

作品。但是我不确定我是否正确使用了 CoInitialize/CoUninitialize,例如:
  • 我这么早就调用 CoUninitialize 是不是搞砸了?
  • 必须“知道”TOpenDialog 内部(有时)使用 COM 的事实,闻起来像我宁愿避免的泄漏抽象。

  • 编辑: 我找到了一个稍微好一点的方法:如果我将 ComObj 添加到 dpr 的 uses 子句中,我可以省略 CoInitialize/CoUninitialize 调用。当然,泄漏抽象问题仍然存在。

    最佳答案

    问题似乎是 COM 没有被初始化。这通常发生在 Application.Initialize 中,因为使用 ComObj 添加了初始化过程。但是您在评论中报告说 InitProcnil 内的 Application.Initialize,这表明 ComObj 未包含在您的项目中。

    因此,您可以通过在项目中包含 ComObj 来轻松解决该问题。或者,如果您想明确说明它,只需在 .dpr 文件的开头调用 CoInitilize(nil) 即可。

    10-08 05:06