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,
TPaintBoxis aTGraphicControldescendant that draws onto theHDCof itsParentcontrol'sHWND. When theParentcontrol receives aWM_PAINTmessage, it draws itself onto the providedHDCas needed, and then temporarily gives that sameHDCto each childTGraphicControlwhen drawing them, clipping theHDCto each child's coordinates and rectangle accordingly. If you try to draw onto aTGraphicControl.Canvasfrom outside of itsParentcontrol'sWM_PAINThandler (which you should never do),TCanvaswill temporarily grab theParentcontrol'sHDCusing 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.Parentcontrol, not on theTPaintBoxitself. If you want the video associated with its own control, consider usingTPanelinstead, as it is aTWinControldescendant with its ownHWND.FireMonkey, on the other hand, has no concept of
TGraphicControlandTWinControl. Every control is aTControldescendant with an overriddenPaint()method to handle any custom drawing onto aTCanvasthat is provided by either the parentTFormor the caller of theTControl.PaintTo()method. FireMonkey does not even create anHWNDfor each control. Only the parentTFormhas 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
HWNDfor your video class to display on, you will have to either:use the
HWNDof aTForm, which you can get by either passing itsHandleproperty to theFMX.Platform.Win.WindowHandleToPlatform()function (or theFMX.Platform.Win.FmxHandleToHWND()function on older FireMonkey versions):Or passing the
TFormitself to theFMX.Platform.Win.FormToHWND()function:use the Win32 API directly to create your own
HWNDas needed and then embed it inside theHWNDof 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.Canvasfrom within theTPaintBox.OnPaintevent (which is howTPaintBoxis meant to be used in the first place, in both VCL and FireMonkey). Or maybe derive your own customTControlthat 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).