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 ?
In VCL,
TPaintBox
is aTGraphicControl
descendant that draws onto theHDC
of itsParent
control'sHWND
. When theParent
control receives aWM_PAINT
message, it draws itself onto the providedHDC
as needed, and then temporarily gives that sameHDC
to each childTGraphicControl
when drawing them, clipping theHDC
to each child's coordinates and rectangle accordingly. If you try to draw onto aTGraphicControl.Canvas
from outside of itsParent
control'sWM_PAINT
handler (which you should never do),TCanvas
will temporarily grab theParent
control'sHDC
using the Win32 APIGetDC()
function.Thus, this statement:
Is effectively the same as this:
So, you are actually putting your video on the window of the
TPaintBox.Parent
control, not on theTPaintBox
itself. If you want the video associated with its own control, consider usingTPanel
instead, as it is aTWinControl
descendant with its ownHWND
.FireMonkey, on the other hand, has no concept of
TGraphicControl
andTWinControl
. Every control is aTControl
descendant with an overriddenPaint()
method to handle any custom drawing onto aTCanvas
that is provided by either the parentTForm
or the caller of theTControl.PaintTo()
method. FireMonkey does not even create anHWND
for each control. Only the parentTForm
has its ownHWND
(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 aTForm
, which you can get by either passing itsHandle
property to theFMX.Platform.Win.WindowHandleToPlatform()
function (or theFMX.Platform.Win.FmxHandleToHWND()
function on older FireMonkey versions):Or passing the
TForm
itself to theFMX.Platform.Win.FormToHWND()
function:use the Win32 API directly to create your own
HWND
as needed and then embed it inside theHWND
of aTForm
.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 theTPaintBox.OnPaint
event (which is howTPaintBox
is meant to be used in the first place, in both VCL and FireMonkey). Or maybe derive your own customTControl
that pulls images from the video class in its own overriddenPaint()
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).