Reputation: 331
Preambule: I'm working with Black Magic Design (BMD) Decklink input card to acquire HD video signal. They provide C++ Sample with their SDK. I've successfully translated the c++ sample into Delphi (VCL). I've also isolated the API call in a TDecklink witch I want it to be available to the Delphi community. It work very well in VCL (I can provide the TDecklnk with a demo app to use it if requested).
Now I need to acquire the signal in a FMX form (but not crosscompile to other platform than Windows). I've tried to modify the TDecklink to be usable in FMX without success.
Core Question:
In my VCL version, I pass a TPaintBox refference to my TDecklink. The TPaintBox is used by the GraphBuilder as area to display the live video.
Here is some line of code I use in the VCL version to assign the TPaintBox to the 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
Where PWnd is a HWND
In FMX, what is the best component and parameter to use to provide what the GraphBuilder expect to receive ?
Upvotes: 1
Views: 1598
Reputation: 598029
In VCL, TPaintBox
is a TGraphicControl
descendant that draws onto the HDC
of its Parent
control's HWND
. When the Parent
control receives a WM_PAINT
message, it draws itself onto the provided HDC
as needed, and then temporarily gives that same HDC
to each child TGraphicControl
when drawing them, clipping the HDC
to each child's coordinates and rectangle accordingly. If you try to draw onto a TGraphicControl.Canvas
from outside of its Parent
control's WM_PAINT
handler (which you should never do), TCanvas
will temporarily grab the Parent
control's HDC
using the Win32 API GetDC()
function.
Thus, this statement:
pWnd := WindowFromDC(FpboxPreview.Canvas.Handle);
Is effectively the same as this:
pWnd := FpboxPreview.Parent.Handle;
So, you are actually putting your video on the window of the TPaintBox.Parent
control, not on the TPaintBox
itself. If you want the video associated with its own control, consider using TPanel
instead, as it is a TWinControl
descendant with its own HWND
.
FireMonkey, on the other hand, has no concept of TGraphicControl
and TWinControl
. Every control is a TControl
descendant with an overridden Paint()
method to handle any custom drawing onto a TCanvas
that is provided by either the parent TForm
or the caller of the TControl.PaintTo()
method. FireMonkey does not even create an HWND
for each control. Only the parent TForm
has its own HWND
(so it can interact with the OS). Child controls are drawn directly onto that window, adjusting the drawing coordinates and clipping rectangle accordingly as they go along (under the hood, FireMonkey uses DirectX (Windows) or OpenGL (other platforms) for all of its drawing).
So, if you really need an HWND
for your video class to display on, you will have to either:
use the HWND
of a TForm
, which you can get by either passing its Handle
property to the
FMX.Platform.Win.WindowHandleToPlatform()
function (or the FMX.Platform.Win.FmxHandleToHWND()
function on older FireMonkey versions):
uses
..., FMX.Platform.Win;
pWnd := WindowHandleToPlatform(Form1.Handle);
Or passing the TForm
itself to the FMX.Platform.Win.FormToHWND()
function:
uses
..., FMX.Platform.Win;
pWnd := FormToHWND(Form1);
use the Win32 API directly to create your own HWND
as needed and then embed it inside the HWND
of a TForm
.
Otherwise, you will have to re-think your video UI in FireMonkey. For instance, assuming the video class can provide you with images of the video frames, you can draw them onto the TPaintBox.Canvas
from within the TPaintBox.OnPaint
event (which is how TPaintBox
is meant to be used in the first place, in both VCL and FireMonkey). Or maybe derive your own custom TControl
that pulls images from the video class in its own overridden Paint()
method. I don't know what your GraphBuilder class is capable of, but BMD provides an SDK for controlling video recording/playback hardware and accessing video data (see this PDF).
Upvotes: 6