文件前言 我正在使用Black Magic Design(BMD)Decklink输入卡来获取高清视频信号。他们为他们的SDK提供C ++示例。我已成功将c ++示例翻译成Delphi(VCL)。我还在TDecklink中隔离了API调用,我想让它可供Delphi社区使用。它在VCL中运行良好(我可以为TDecklnk提供一个演示应用程序,以便在需要时使用它)。
现在我需要以FMX格式获取信号(但不能交叉编译到除Windows之外的其他平台)。我试图修改TDecklink以便在FMX中使用而没有成功。
核心问题:
在我的VCL版本中,我将TPaintBox参考传递给我的TDecklink。 GraphBuilder使用TPaintBox作为显示实时视频的区域。
以下是我在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期望接收的内容的最佳组件和参数是什么?
答案 0 :(得分:6)
在VCL中,TPaintBox
是TGraphicControl
后代,可以吸引其HDC
控制Parent
的{{1}}。当HWND
控件收到Parent
消息时,它会根据需要将自己绘制到提供的WM_PAINT
上,然后暂时为每个孩子HDC
提供相同的HDC
在绘制它们时,相应地将TGraphicControl
剪切到每个孩子的坐标和矩形。如果您尝试从其HDC
控件TGraphicControl.Canvas
处理程序(您永远不应该这样做)之外的Parent
上绘图,WM_PAINT
会暂时抓取TCanvas
{1}}使用Win32 API Parent
函数控制HDC
。
因此,这句话:
GetDC()
实际上与此相同:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle);
因此,您实际上是将视频放在pWnd := FpboxPreview.Parent.Handle;
控件的窗口上,而不是TPaintBox.Parent
本身。如果您希望视频与其自己的控件相关联,请考虑使用TPaintBox
,因为它是TPanel
后代,并且拥有自己的TWinControl
。
另一方面,FireMonkey没有HWND
和TGraphicControl
的概念。每个控件都是TWinControl
后代,其中包含一个重写的TControl
方法,用于处理由Paint()
或TCanvas
的调用方提供的TForm
上的任何自定义绘图1}}方法。 FireMonkey甚至不为每个控件创建TControl.PaintTo()
。只有父HWND
有自己的TForm
(因此它可以与操作系统进行交互)。子控件直接绘制到该窗口上,相应地调整绘图坐标和剪切矩形(在引擎盖下,FireMonkey使用DirectX(Windows)或OpenGL(其他平台)进行所有绘图)。
因此,如果您确实需要HWND
来显示您的视频课程,则必须:
使用HWND
的{{1}},您可以通过将HWND
属性传递给TForm
FMX.Platform.Win.WindowHandleToPlatform()
函数(或旧版FireMonkey上的FMX.Platform.Win.FmxHandleToHWND()
函数):
Handle
或者将uses
..., FMX.Platform.Win;
pWnd := WindowHandleToPlatform(Form1.Handle);
本身传递给FMX.Platform.Win.FormToHWND()
函数:
TForm
根据需要直接使用Win32 API创建自己的uses
..., FMX.Platform.Win;
pWnd := FormToHWND(Form1);
,然后将其嵌入HWND
的{{1}}。
否则,您必须在FireMonkey中重新考虑您的视频用户界面。例如,假设视频类可以为您提供视频帧的图像,您可以在HWND
事件中将它们绘制到TForm
上(这就是TPaintBox.Canvas
的意图。在VCL和FireMonkey中首先使用)。或者可能派生出您自己的自定义TPaintBox.OnPaint
,它会以自己覆盖的TPaintBox
方法从视频类中提取图像。我不知道您的GraphBuilder类能够做什么,但BMD提供了一个SDK,用于控制视频录制/回放硬件和访问视频数据(参见this PDF)。