Hi Chriss,
And the plot thickens. Below is the code of two classes - BitMapInfoHeader class (based on Struct class) and Webcam (wrapper class to the GitHub code).
[pre]**************************************************
*-- Class Library: d:\vfpxdev\payprox\classes\webcam.vcx
**************************************************
*-- Class: bitmapinfoheader (d:\vfpxdev\payprox\classes\webcam.vcx)
*-- ParentClass: struct (d:\vfpxdev\common\classes\struct.vcx)
*-- BaseClass: label
*-- Time Stamp: 10/27/23 01:41:03 PM
*
DEFINE CLASS bitmapinfoheader AS struct
Height = 17
Width = 137
bisize = 0
biwidth = 0
biheight = 0
biplanes = 0
bibitcount = 0
bicompression = 0
bisizeimage = 0
bixpelspermeter = 0
biypelspermeter = 0
biclrused = 0
biclrimportant = 0
cmembers = "ul:biSize, sl:biWidth, sl:biHeight, uw:biPlanes, uw:biBitCount, ul:biCompression, ul:biSizeImage, sl:biXPelsPerMeter, sl:biYPelsPerMeter, ul:biClrUsed, ul:biClrImportant"
Name = "bitmapinfoheader"
ENDDEFINE
*
*-- EndDefine: bitmapinfoheader
**************************************************
*-- Class: webcam (d:\vfpxdev\payprox\classes\webcam.vcx)
*-- ParentClass: _custom (d:\vfpxdev\common\classes\base.vcx)
*-- BaseClass: custom
*-- Time Stamp: 10/28/23 03:11:07 PM
*
#INCLUDE "d:\vfpxdev\payprox\classes\webcam.h"
*
DEFINE CLASS webcam AS _custom
Height = 16
Width = 87
hwindow = 0
hcapture = 0
capwidth = 0
capheight = 0
capoverlay = 0
capleft = 0
captop = 0
bitmapinfoheaderclass = "bitmapinfoheader"
bitmapinfoheaderclasslib = "webcam.vcx"
usebitmapinfo = .F.
bisize = 0
biwidth = 0
biheight = 0
biplanes = 0
bibitcount = 0
bicompression = 0
bisizeimage = 0
bixpelspermeter = 0
biypelspermeter = 0
biclrused = 0
biclrimportant = 0
Name = "webcam"
PROCEDURE declaredlls
DECLARE INTEGER DestroyWindow IN user32 INTEGER hWindow
DECLARE INTEGER capCreateCaptureWindow IN avicap32;
STRING lpszWindowName, LONG dwStyle,;
INTEGER x, INTEGER y, INTEGER nWidth,;
INTEGER nHeight, INTEGER hParent, INTEGER nID
DECLARE INTEGER SetWindowPos IN user32;
INTEGER hWindow, INTEGER hWndInsertAfter,;
INTEGER x, INTEGER y, INTEGER cx, INTEGER cy,;
INTEGER wFlags
DECLARE INTEGER SendMessage IN user32 As SendMsgInt;
INTEGER hWindow, INTEGER Msg,;
INTEGER wParam, INTEGER lParam
DECLARE INTEGER SendMessage IN user32 As SendMsgStr;
INTEGER hWindow, INTEGER Msg,;
INTEGER wParam, STRING @lParam
ENDPROC
PROCEDURE cleardlls
CLEAR DLLS "DestroyWindow", "capCreateCaptureWindow", "SetWindowPos",;
"SendMsgInt", "SendMsgStr"
ENDPROC
PROCEDURE releasecapturewindow
IF This.hCapture # 0
This.DriverDisconnect()
= DestroyWindow( This.hCapture )
This.hCapture = 0
ENDIF
ENDPROC
PROCEDURE driverdisconnect
This.MessageCenter( WM_CAP_DRIVER_DISCONNECT, 0, 0 )
ENDPROC
PROCEDURE messagecenter
LPARAMETERS msg, wParam, lParam, nMode
DO CASE
CASE This.hCapture = 0
CASE VARTYPE( nMode ) # "N" OR nMode = 0
= SendMsgInt( This.hCapture, msg, wParam, lParam )
OTHERWISE
= SendMsgStr( This.hCapture, msg, wParam, @lParam )
ENDCASE
ENDPROC
PROCEDURE getvideoformat
LOCAL cBuffer, nBuffSize
nBuffSize = 4096
cBuffer = PADR( This.Num2DWord( BITMAPINFOHEADER_SIZE ), nBuffsize, CHR(0) )
This.MessageCenter( WM_CAP_GET_VIDEOFORMAT, nBuffsize, @cBuffer, 1 )
This.capWidth = This.Buff2DWord( SUBSTR(cBuffer, 5, 4) )
This.capHeight = This.Buff2DWord( SUBSTR(cBuffer, 9, 4) )
ENDPROC
PROCEDURE num2dword
LPARAMETERS lnValue
LOCAL b0, b1, b2, b3
#DEFINE m0 0x100
#DEFINE m1 0x10000
#DEFINE m2 0x1000000
IF lnValue < 0
lnValue = 0x100000000 + lnValue
ENDIF
b3 = INT( lnValue/m2 )
b2 = INT( (lnValue - b3*m2)/m1 )
b1 = INT( (lnValue - b3*m2 - b2*m1)/m0 )
b0 = MOD( lnValue, m0 )
RETURN CHR( b0 ) + CHR( b1 ) + CHR( b2) + CHR( b3 )
ENDPROC
PROCEDURE buff2dword
LPARAMETERS lcBuffer
RETURN Asc( SUBSTR(lcBuffer, 1,1) ) + ;
BitLShift( Asc( SUBSTR(lcBuffer, 2,1)), 8 ) +;
BitLShift( Asc( SUBSTR(lcBuffer, 3,1)), 16 ) +;
BitLShift( Asc( SUBSTR(lcBuffer, 4,1)), 24 )
ENDPROC
PROCEDURE resizecapturewindow
This.GetVideoFormat()
= SetWindowPos( This.hCapture, 0, This.capLeft, This.capTop, This.capWidth, This.capHeight, SWP_SHOWWINDOW )
ENDPROC
PROCEDURE getframe
This.MessageCenter( WM_CAP_GRAB_FRAME, 0, 0 )
ENDPROC
PROCEDURE showformatdialog
This.MessageCenter( WM_CAP_DLG_VIDEOFORMAT, 0,0 )
This.ResizeCaptureWindow()
ENDPROC
PROCEDURE iscaptureconnected
LOCAL cBuffer, nResult
cBuffer = REPLICATE( CHR(0), CAPDRIVERCAPS_SIZE )
This.MessageCenter( WM_CAP_DRIVER_GET_CAPS, LEN(cBuffer), @cBuffer, 1 )
This.capOverlay = This.Buff2DWord( SUBSTR(cBuffer,5,4) )
nResult = ASC( SUBSTR( cBuffer, 21, 1 ) )
RETURN ( nResult # 0 )
ENDPROC
PROCEDURE driverconnect
This.MessageCenter( WM_CAP_DRIVER_CONNECT, 0, 0 )
RETURN This.IsCaptureConnected()
ENDPROC
PROCEDURE startpreview
This.MessageCenter( WM_CAP_SET_PREVIEWRATE, 30, 0 )
This.MessageCenter( WM_CAP_SET_PREVIEW, 1, 0 )
IF This.capOverlay # 0
This.MessageCenter( WM_CAP_SET_OVERLAY, 1, 0 )
ENDIF
ENDPROC
PROCEDURE stoppreview
This.MessageCenter( WM_CAP_SET_PREVIEW, 0, 0 )
ENDPROC
PROCEDURE savetodib
LPARAMETERS lcPath
LOCAL cFilename, lcTempDir
IF PCOUNT() > 0
cFilename = ADDBS( lcPath ) + SYS(2015) + ".dib" + CHR(0)
ELSE
cFilename = SYS(2015) + ".dib" + CHR(0)
ENDIF
This.MessageCenter( WM_CAP_FILE_SAVEDIB, 0, @cFilename, 1 )
RETURN cFilename
ENDPROC
PROCEDURE initcapturewindow
LPARAMETERS hParent, nLeft, nTop
WITH This
.hWindow = hParent
.capLeft = nLeft
.capTop = nTop
.capWidth = 0
.capHeight = 0
.hCapture = capCreateCaptureWindow("", BITOR( WS_CHILD, WS_VISIBLE ), .capLeft, .capTop, 1, 1, .hWindow, 1 )
IF .DriverConnect()
.MessageCenter( WM_CAP_SET_SCALE, 1, 0 )
.ResizeCaptureWindow()
ENDIF
ENDWITH
RETURN This.IsCaptureConnected()
ENDPROC
PROCEDURE setvideoformat
LOCAL loBitMapInfoHeader, lcString, lpString
IF This.UseBitMapInfo
MESSAGEBOX( 'Using BitMapInfo...' )
loBitMapInfoHeader = NEWOBJECT( This.BitMapInfoHeaderClass, This.BitMapHeaderClassLib )
&& CREATEOBJECT( This.BitMapInfoHeaderClass )
loBitMapInfoHeader.biSize = loBitMapInfoHeader.SizeOf()
loBitMapInfoHeader.biWidth = This.biWidth
loBitMapInfoHeader.biHeight = This.biHeight
loBitMapInfoHeader.biPlanes = This.biPlanes
loBitMapInfoHeader.biBitCount = This.biBitCount
loBitMapInfoHeader.biCompression = This.biCompression
loBitMapInfoHeader.biSizeImage = This.biSizeImage
loBitMapInfoHeader.biXPelsPerMeter = This.biXPelsPerMeter
loBitMapInfoHeader.biYPelsPerMeter = This.biYPelsPerMeter
loBitMapInfoHeader.biClrUsed = This.biClrUsed
loBitMapInfoHeader.biClrImportant = This.biClrImportant
lpString = loBitMapInfoHeader.GetPointer( loBitMapInfoHeader.SizeOf() )
This.MessageCenter( WM_CAP_SET_VIDEOFORMAT, loBitMapInfoHeader.SizeOf(), lpString )
ELSE
This.ShowFormatDialog()
ENDIF
This.GetVideoFormat() && ???
* Below is to check the values on SCREEN
ACTIVATE SCREEN
CLEAR
? 'loBitMapInfoHeader Values'
? TRANSFORM( loBitMapInfoHeader.biSize )
? TRANSFORM( loBitMapInfoHeader.biWidth )
? TRANSFORM( loBitMapInfoHeader.biHeight )
? TRANSFORM( loBitMapInfoHeader.biPlanes )
? TRANSFORM( loBitMapInfoHeader.biBitCount )
? TRANSFORM( loBitMapInfoHeader.biCompression )
? TRANSFORM( loBitMapInfoHeader.biSizeImage )
? TRANSFORM( loBitMapInfoHeader.biXPelsPerMeter )
? TRANSFORM( loBitMapInfoHeader.biYPelsPerMeter )
? TRANSFORM( loBitMapInfoHeader.biClrUsed )
? TRANSFORM( loBitMapInfoHeader.biClrImportant )
? 'loBitMapInfoHeader Vartypes'
? VARTYPE( loBitMapInfoHeader.biSize )
? VARTYPE( loBitMapInfoHeader.biWidth )
? VARTYPE( loBitMapInfoHeader.biHeight )
? VARTYPE( loBitMapInfoHeader.biPlanes )
? VARTYPE( loBitMapInfoHeader.biBitCount )
? VARTYPE( loBitMapInfoHeader.biCompression )
? VARTYPE( loBitMapInfoHeader.biSizeImage )
? VARTYPE( loBitMapInfoHeader.biXPelsPerMeter )
? VARTYPE( loBitMapInfoHeader.biYPelsPerMeter )
? VARTYPE( loBitMapInfoHeader.biClrUsed )
? VARTYPE( loBitMapInfoHeader.biClrImportant )
? ''
? 'This Values'
? TRANSFORM( loBitMapInfoHeader.SizeOf() )
? TRANSFORM( This.biWidth )
? TRANSFORM( This.biHeight )
? TRANSFORM( This.biPlanes )
? TRANSFORM( This.biBitCount )
? TRANSFORM( This.biCompression )
? TRANSFORM( This.biSizeImage )
? TRANSFORM( This.biXPelsPerMeter )
? TRANSFORM( This.biYPelsPerMeter )
? TRANSFORM( This.biClrUsed )
? TRANSFORM( This.biClrImportant )
? 'This. Vartypes'
? VARTYPE( loBitMapInfoHeader.SizeOf() )
? VARTYPE( This.biWidth )
? VARTYPE( This.biHeight )
? VARTYPE( This.biPlanes )
? VARTYPE( This.biBitCount )
? VARTYPE( This.biCompression )
? VARTYPE( This.biSizeImage )
? VARTYPE( This.biXPelsPerMeter )
? VARTYPE( This.biYPelsPerMeter )
? VARTYPE( This.biClrUsed )
? VARTYPE( This.biClrImportant )
ENDPROC
PROCEDURE Destroy
This.ReleaseCaptureWindow()
ENDPROC
PROCEDURE Init
This.DeclareDLLs()
ENDPROC
ENDDEFINE
*
*-- EndDefine: webcam
**************************************************
[/pre]
In the SetVideoFormat method, I instantiated the BitMapInfoHeader class, then populated its properties like biHeight, biHeight etc. with the values of Webcam class (as oWebcam) which contains the exact same properties names but actual values when I dropped the Webcam custom class onto the Form.
[pre]oWebcam.biSize = loBitMapInfoHeader.SizeOf()
oWebcam.biWidth = 640
oWebcam.biHeight = 480
oWebcam.biPlanes = 1
oWebcam.biBitCount = 16
oWebcam.biCompression = 844715353
oWebcam.biSizeImage = 614400
oWebcam.biXPelsPerMeter = 0
oWebcam.biYPelsPerMeter = 0
oWebcam.biClrUsed = 0
oWebcam.biClrImportant = 0
[/pre]
Do note that in the SetVideoFormat(), I sent to the screen the values of these properties. And voila!
It is all blanks in the BitMapInfoHeader object! What the heck!