【问题标题】:Delphi 10.1 ShellExecute Error incompatible types 'HWND' and 'TWindowsHandle'Delphi 10.1 ShellExecute 错误不兼容类型'HWND'和'TWindowsHandle'
【发布时间】:2016-10-09 22:58:59
【问题描述】:

我对 Delphi 10.1 中的以下代码有问题:

ShellExecute(handle,'open',PChar(filename), '','',SW_SHOWNORMAL);

当我尝试运行代码时,它给了我这个错误:

不兼容的类型:“HWND”和“TWindowHandle”

【问题讨论】:

  • 尝试将handle参数改为0
  • 问问自己为什么要通过handle。我想那是您应用程序中表单的 FMX handle。你知道ShellExecute 会如何处理这个论点吗?你有什么理由不直接通过0?是什么驱使你传递不同的价值观?如果有的话,您是否理解该论点将如何使用?如果你不理解它,你为什么还要调用这个函数?
  • 不要使用ShellExecute,因为它不会以有用的方式报告错误。使用ShellExecuteEx 可以。你甚至检查错误吗?您想明确使用open 动词,还是真的要执行默认动词? filename 是可执行文件吗?如果是这样,那么您应该使用 CreateProcess 创建一个新进程,而不是让 shell 来完成这项工作。

标签: delphi shellexecute


【解决方案1】:

在 FireMonkey 中,Form 的 Handle 属性属于 TWindowHandle 类型(在 FMX.Types 单元中定义的类)。在 Windows 上,它被实现为TWinWindowHandleTWindowHandle 的子类在FMX.Platform.Win 单元中定义)。

TWinWindowHandleHWND 句柄存储在其Wnd 属性中。

要获得实际的HWND 句柄,您需要使用FmxHandleToHWND()

ShellExecute(FmxHandleToHWND(Handle), 'open', PChar(filename), '', '', SW_SHOWNORMAL);

这会将TWindowHandle 转换为TWinWindowHandle(使用WindowHandleToPlatform),然后返回其Wnd 属性值。

更新(基于 Remy 的 cmets):

Remy 指出 FmxHandleToHWND 已被记录为已弃用(从 XE4 开始)。这似乎没有得到最新源代码的支持,在 Delphi 10.1 Berlin RTM 版本的情况下,似乎已经放弃了通常的 deprecated 修饰符,但为了安全起见,让我们以文档的说法为准。

建议您不要使用FmxHandleToHWND,而是执行FmxHandleToHWND 所做的事情,即调用WindowHandleToPlatform 并访问Wnd 属性,因此:

ShellExecute(WindowHandleToPlatform(Handle).Wnd, 'open', PChar(filename), '', '', SW_SHOWNORMAL);

不过,更好的选择是使用FormToHWND,它比WindowHandleToPlatform 更直接替代FmxHandleToHWND(我们可能想知道为什么文档没有指出这个例程,尽管可能的答案是文档作者弄错了):

ShellExecute(FormToHWND(Handle), 'open', PChar(filename), '', '', SW_SHOWNORMAL);

【讨论】:

  • FmxHandleToHWND() 已弃用,您现在应该直接使用WindowHandleToPlatform(),例如:ShellExecute(WindowHandleToPlatform(Handle)->Wnd, 'open', PChar(filename), '', '', SW_SHOWNORMAL);
  • 更新答案以考虑文档的指控
  • 这不是指控,它确实在源代码中被标记为已弃用,并且已经有一段时间了。此外,获取TFormHWND 的更简单方法是在FMX.Platform.Win 单元中使用FormToHWND() 函数,例如:ShellExecute(FormToHWND(Self), 'open', PChar(filename), '', '', SW_SHOWNORMAL);
  • 我查看的来源是 Delphi 10.1 Berlin。没有deprecated 那里。也许这在更新中改变了?现在我回顾西雅图和更早的地方,我在那里看到了它,但在柏林 RTM 却没有。请检查。
  • 此外,如果FormToHWND是有效的非弃用替代品,为什么FmxHandleToHWND上的文档页面将编码器引用到WindowHandleToPlatform,这显然不是替代品??
【解决方案2】:

TWindowHandle 是一个 FireMonkey 类。 HWND 是 Windows 句柄。这些是完全不同的类型。

对于 VCL,可以将 TForm.Handle(即 HWND)传递给 ShellExecute()。对于 FireMonkey (FMX),它不是,因为那是 TWindowHandle

改用单元Winapi.Windows中的GetDesktopWindow()

ShellExecute(GetDesktopWindow, 'open', PChar(filename), '', '', SW_SHOWNORMAL);

【讨论】:

  • 永远不要将桌面窗口用作窗口所有者。 Pass 0 可能是最干净的。
  • @David - 就像 Jordan (inno-setup) 在您链接的页面上发表评论一样,Raymond 给出的示例并不准确。我怀疑它是否准确。也许在 9x.. 系统上....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多