【问题标题】:How to cast an IDispatch as a TOleServer in Delphi XE2?如何在 Delphi XE2 中将 IDispatch 转换为 TOleServer?
【发布时间】:2015-09-30 06:26:15
【问题描述】:

我正在尝试使用来自

的 Video Capture SDK

DTK Software

在我的 Delphi 应用程序中。他们提供的唯一真正帮助是如何导入他们的类型库!我成功地做到了这一点,并且在我的项目中有一个 DTKVideoCapLib_TLB.pas

我已经走到这一步了。

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  s: String;
  VideoCaptureUtils: TVideoCaptureUtils;
  VideoDevice: TVideoDevice;
begin
    VideoCaptureUtils := TVideoCaptureUtils.Create(Self);
    for i := 0 to VideoCaptureUtils.VideoDevices.Count - 1 do
    begin
       s := VideoCaptureUtils.VideoDevices.Item[i].Name;
       ShowMessage(s);
       VideoDevice := TVideoDevice(VideoCaptureUtils.Videodevices.Item[i]);
    end;

ShowMessage 向我展示 Microsoft LifeCam VX-800

所以我一定做对了,但在下一行之后,在调试器中,VideoDevicenil

查看DTKVideoCapLib_TLB.pas,我看到以下内容

 TVideoDevice = class(TOleServer)
  private
    FIntf: IVideoDevice;
    function GetDefaultInterface: IVideoDevice;
  protected
  ...

  IVideoDevice = interface(IDispatch)
    ['{8A40EA7D-692C-40EE-9258-6436D1724739}']
    function Get_Name: WideString; safecall;
  ...

所以现在,我真的不知道该怎么做?

更新

将问题中的 item[0] 更正为 item[i]。在 IDE 中右键单击 item[i] 并选择 Find Declaration 带我到

type
  IVideoDeviceCollection = interface(IDispatch) 
    ...
    property Item[index: Integer]: IVideoDevice read Get_Item;
    ...
  end;

【问题讨论】:

  • 未经检查的强制转换通常很糟糕。你怎么知道VideoCaptureUtils.Videodevices.Item[0] 真的是TVideoDevice 类型?为什么要使用索引0VideoCaptureUtils.Videodevices.Item[i] 是什么类型?

标签: delphi com activex ole


【解决方案1】:

您应该使用as。 Delphi 将自动尝试为您获取所需的界面。像这样的东西(未经测试!)应该可以工作:

var
  VideoDevice: IVideoDevice; // note the type of the variable
....
VideoDevice := VideoCaptureUtils.Videodevices.Item[0] as IVideoDevice;

但是,您的更新提供了我写原始答案时没有出现的更多细节。该更新包括表明Videodevices 已经包含IVideoDevice 的代码,因此您根本不需要强制转换 - 您只需要正确的变量声明:

var
  VideoDevice: IVideoDevice; // note the type of the variable
....
VideoDevice := VideoCaptureUtils.Videodevices.Item[i];

【讨论】:

  • 该行产生编译器错误:[DCC Error] Unit1.pas(65): E2010 Incompatible types: 'TVideoDevice' and 'IVideoDevice' 而这一行 VideoDevice := VideoCaptureUtils.Videodevices.Item[0] as TVideoDevice;编译但产生运行时错误“EIntfCastError: Interface not supported”
  • 好的,我上面的回复也有点快。一旦我将 VideoDevice 类型更改为 IVideoDevice,问题就解决了。我将其标记为答案。
  • 根据 David Heffernen 在下面的回答,如果类型是 IVideoDevice,则演员表(作为 IVideoDevice)是多余的。你想更正你的答案吗?
【解决方案2】:
VideoCaptureUtils.Videodevices.Item[i]

类型为IVideoDevice。所以你不能把它转换成TVideoDevice

你需要更正变量的类型:

var
  VideoDevice: IVideoDevice;

然后像这样分配它:

VideoDevice := VideoCaptureUtils.VideoDevices.Item[i];

【讨论】:

  • 那么我认为,也不能将 TVideoDevice 转换为 IVideoDevice 吗?这就解释了为什么 Tx = Class(TOleServer) 类,都有:private... function GetDefaultInterface: Ix 方法,对吧?
  • 如果你真的有一个TVideoDevice,那么你肯定可以从中得到一个IVideoDevice。但是你有一个IVideoDevice。这不是你需要的吗?
  • 就具体问题而言,是的!在使用库的其他功能方面,没有。大多数情况下,我将使用 x := Tx.Create(nil); y.Ix := x.GetDefaultInterface,你看到了吗?
  • 不,我不认为这是这样做的方式。无论如何,这个问题似乎已经完成了。
  • 也许我应该发布一个新问题。
猜你喜欢
  • 1970-01-01
  • 2012-02-05
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2011-11-22
  • 2011-01-20
相关资源
最近更新 更多