需要帮助在构建图形的上下文中找到与 VCL TpaintBox.Canvas.Handle 等效的 FireMonkey
Need help to find FireMonkey equivalent of the VCL TpaintBox.Canvas.Handle in the context of building graph
前言:
我正在使用 Black Magic Design (BMD) Decklink 输入卡来获取高清视频信号。他们在 SDK 中提供 C++ 示例。我已经成功地将 c++ 示例翻译成 Delphi (VCL)。我还在 TDecklink 中隔离了 API 调用 我希望它对 Delphi 社区可用。它在 VCL 中运行良好(如果需要,我可以为 TDecklnk 提供一个演示应用程序来使用它)。
现在我需要以 FMX 形式获取信号(但不能交叉编译到 Windows 以外的其他平台)。我试图修改 TDecklink 以在 FMX 中使用但没有成功。
核心问题:
在我的 VCL 版本中,我将 TPaintBox 引用传递到我的 TDecklink。 TPaintBox 被 GraphBuilder 用作显示实时视频的区域。
这是我在 VCL 版本中用于将 TPaintBox 分配给 GraphBuilder 的一些代码行:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle); //WindowFromDC retreive HWND from HDC
hr:= pIVMRWindowlessCtrl.SetVideoClippingWindow(pWnd); // set the bounds of the video to the preview window
if hr = S_OK then
begin
previewRect.Left := FpboxPreview.Left;
previewRect.Right := FpboxPreview.Width;
previewRect.Top := FpboxPreview.Top;
previewRect.Bottom := FpboxPreview.Height;
hr:= pIVMRWindowlessCtrl.SetVideoPosition(nil, @previewRect); // show the whole of the source frame in the whole of the client area of the control
hr:= pIVMRWindowlessCtrl.SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); // maintain the aspect ratio of the video
hr:= pIVMRWindowlessCtrl.SetBorderColor(GetSysColor(COLOR_BTNFACE)); // set the colour of the letter or pillar boxed area
其中 PWnd 是一个 HWND
在 FMX 中,用于提供 GraphBuilder 期望接收的内容的最佳组件和参数是什么?
在 VCL 中,TPaintBox
是一个 TGraphicControl
后代,它绘制到其 Parent
控件的 HWND
的 HDC
上。当 Parent
控件收到 WM_PAINT
消息时,它会根据需要将自己绘制到提供的 HDC
上,然后暂时将相同的 HDC
分配给每个 child TGraphicControl
绘制它们时,将 HDC
剪裁到每个 child 的坐标和相应的矩形。如果您尝试从其 Parent
控件的 WM_PAINT
处理程序外部绘制到 TGraphicControl.Canvas
(您永远不应该这样做),TCanvas
将暂时获取 Parent
控件的 HDC
使用 Win32 API GetDC()
函数。
因此,这条语句:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle);
实际上与此相同:
pWnd := FpboxPreview.Parent.Handle;
因此,您实际上是将视频放在 TPaintBox.Parent
控件的 window 上,而不是 TPaintBox
本身。如果您希望视频与其自己的控件关联,请考虑使用 TPanel
,因为它是 TWinControl
的后代,具有自己的 HWND
.
另一方面,FireMonkey 没有TGraphicControl
和TWinControl
的概念。每个控件都是 TControl
的后代,具有覆盖的 Paint()
方法来处理 TCanvas
上的任何自定义绘图,该 TCanvas
由 parent TForm
或调用者提供TControl.PaintTo()
方法。 FireMonkey 甚至不为每个控件创建 HWND
。只有 parent TForm
有自己的 HWND
(因此它可以与 OS 交互)。 Child 控件直接绘制到 window 上,相应地调整绘制坐标和裁剪矩形(在后台,FireMonkey 使用 DirectX (Windows) 或 OpenGL(其他平台)对于它的所有绘图)。
因此,如果您确实需要 HWND
来显示您的视频 class,您必须:
使用 TForm
的 HWND
,您可以通过将其 Handle
属性 传递给
FMX.Platform.Win.WindowHandleToPlatform()
function (or the FMX.Platform.Win.FmxHandleToHWND()
旧版 FireMonkey 的功能):
uses
..., FMX.Platform.Win;
pWnd := WindowHandleToPlatform(Form1.Handle);
或将 TForm
本身传递给 FMX.Platform.Win.FormToHWND()
函数:
uses
..., FMX.Platform.Win;
pWnd := FormToHWND(Form1);
直接使用 Win32 API 根据需要创建自己的 HWND
,然后将其嵌入到 TForm
的 HWND
中。
否则,您将不得不在 FireMonkey 中 re-think 您的视频 UI。例如,假设视频 class 可以为您提供视频帧的图像,您可以从 TPaintBox.OnPaint
事件中将它们绘制到 TPaintBox.Canvas
上(TPaintBox
应该首先在 VCL 和 FireMonkey 中使用)。或者可能派生出您自己的自定义 TControl
,以其自己覆盖的 Paint()
方法从视频 class 中提取图像。我不知道你的 GraphBuilder class 有什么功能,但 BMD 提供了一个 SDK 用于控制视频 recording/playback 硬件和访问视频数据(参见 this PDF)。
前言: 我正在使用 Black Magic Design (BMD) Decklink 输入卡来获取高清视频信号。他们在 SDK 中提供 C++ 示例。我已经成功地将 c++ 示例翻译成 Delphi (VCL)。我还在 TDecklink 中隔离了 API 调用 我希望它对 Delphi 社区可用。它在 VCL 中运行良好(如果需要,我可以为 TDecklnk 提供一个演示应用程序来使用它)。
现在我需要以 FMX 形式获取信号(但不能交叉编译到 Windows 以外的其他平台)。我试图修改 TDecklink 以在 FMX 中使用但没有成功。
核心问题:
在我的 VCL 版本中,我将 TPaintBox 引用传递到我的 TDecklink。 TPaintBox 被 GraphBuilder 用作显示实时视频的区域。
这是我在 VCL 版本中用于将 TPaintBox 分配给 GraphBuilder 的一些代码行:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle); //WindowFromDC retreive HWND from HDC
hr:= pIVMRWindowlessCtrl.SetVideoClippingWindow(pWnd); // set the bounds of the video to the preview window
if hr = S_OK then
begin
previewRect.Left := FpboxPreview.Left;
previewRect.Right := FpboxPreview.Width;
previewRect.Top := FpboxPreview.Top;
previewRect.Bottom := FpboxPreview.Height;
hr:= pIVMRWindowlessCtrl.SetVideoPosition(nil, @previewRect); // show the whole of the source frame in the whole of the client area of the control
hr:= pIVMRWindowlessCtrl.SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); // maintain the aspect ratio of the video
hr:= pIVMRWindowlessCtrl.SetBorderColor(GetSysColor(COLOR_BTNFACE)); // set the colour of the letter or pillar boxed area
其中 PWnd 是一个 HWND
在 FMX 中,用于提供 GraphBuilder 期望接收的内容的最佳组件和参数是什么?
在 VCL 中,TPaintBox
是一个 TGraphicControl
后代,它绘制到其 Parent
控件的 HWND
的 HDC
上。当 Parent
控件收到 WM_PAINT
消息时,它会根据需要将自己绘制到提供的 HDC
上,然后暂时将相同的 HDC
分配给每个 child TGraphicControl
绘制它们时,将 HDC
剪裁到每个 child 的坐标和相应的矩形。如果您尝试从其 Parent
控件的 WM_PAINT
处理程序外部绘制到 TGraphicControl.Canvas
(您永远不应该这样做),TCanvas
将暂时获取 Parent
控件的 HDC
使用 Win32 API GetDC()
函数。
因此,这条语句:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle);
实际上与此相同:
pWnd := FpboxPreview.Parent.Handle;
因此,您实际上是将视频放在 TPaintBox.Parent
控件的 window 上,而不是 TPaintBox
本身。如果您希望视频与其自己的控件关联,请考虑使用 TPanel
,因为它是 TWinControl
的后代,具有自己的 HWND
.
FireMonkey 没有TGraphicControl
和TWinControl
的概念。每个控件都是 TControl
的后代,具有覆盖的 Paint()
方法来处理 TCanvas
上的任何自定义绘图,该 TCanvas
由 parent TForm
或调用者提供TControl.PaintTo()
方法。 FireMonkey 甚至不为每个控件创建 HWND
。只有 parent TForm
有自己的 HWND
(因此它可以与 OS 交互)。 Child 控件直接绘制到 window 上,相应地调整绘制坐标和裁剪矩形(在后台,FireMonkey 使用 DirectX (Windows) 或 OpenGL(其他平台)对于它的所有绘图)。
因此,如果您确实需要 HWND
来显示您的视频 class,您必须:
使用
TForm
的HWND
,您可以通过将其Handle
属性 传递给FMX.Platform.Win.WindowHandleToPlatform()
function (or theFMX.Platform.Win.FmxHandleToHWND()
旧版 FireMonkey 的功能):uses ..., FMX.Platform.Win; pWnd := WindowHandleToPlatform(Form1.Handle);
或将
TForm
本身传递给FMX.Platform.Win.FormToHWND()
函数:uses ..., FMX.Platform.Win; pWnd := FormToHWND(Form1);
直接使用 Win32 API 根据需要创建自己的
HWND
,然后将其嵌入到TForm
的HWND
中。
否则,您将不得不在 FireMonkey 中 re-think 您的视频 UI。例如,假设视频 class 可以为您提供视频帧的图像,您可以从 TPaintBox.OnPaint
事件中将它们绘制到 TPaintBox.Canvas
上(TPaintBox
应该首先在 VCL 和 FireMonkey 中使用)。或者可能派生出您自己的自定义 TControl
,以其自己覆盖的 Paint()
方法从视频 class 中提取图像。我不知道你的 GraphBuilder class 有什么功能,但 BMD 提供了一个 SDK 用于控制视频 recording/playback 硬件和访问视频数据(参见 this PDF)。