需要帮助在构建图形的上下文中找到与VCL TpaintBox.Canvas.Handle等效的FireMonkey

时间:2015-06-11 02:11:22

标签: delphi firemonkey

文件前言 我正在使用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期望接收的内容的最佳组件和参数是什么?

1 个答案:

答案 0 :(得分:6)

在VCL中,TPaintBoxTGraphicControl后代,可以吸引其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没有HWNDTGraphicControl的概念。每个控件都是TWinControl后代,其中包含一个重写的TControl方法,用于处理由Paint()TCanvas的调用方提供的TForm上的任何自定义绘图1}}方法。 FireMonkey甚至不为每个控件创建TControl.PaintTo()。只有父HWND有自己的TForm(因此它可以与操作系统进行交互)。子控件直接绘制到该窗口上,相应地调整绘图坐标和剪切矩形(在引擎盖下,FireMonkey使用DirectX(Windows)或OpenGL(其他平台)进行所有绘图)。

因此,如果您确实需要HWND来显示您的视频课程,则必须:

  1. 使用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
  2. 根据需要直接使用Win32 API创建自己的uses ..., FMX.Platform.Win; pWnd := FormToHWND(Form1); ,然后将其嵌入HWND的{​​{1}}。

  3. 否则,您必须在FireMonkey中重新考虑您的视频用户界面。例如,假设视频类可以为您提供视频帧的图像,您可以在HWND事件中将它们绘制到TForm上(这就是TPaintBox.Canvas的意图。在VCL和FireMonkey中首先使用)。或者可能派生出您自己的自定义TPaintBox.OnPaint,它会以自己覆盖的TPaintBox方法从视频类中提取图像。我不知道您的GraphBuilder类能够做什么,但BMD提供了一个SDK,用于控制视频录制/回放硬件和访问视频数据(参见this PDF)。