-
Oct 25th, 2020, 09:10 AM
#1
Thread Starter
PowerPoster
vb6: how use an user type parameter on a class function\sub?
Code:
Private Type POINTL
X As Long
Y As Long
End Type
Friend Sub DrawImage(DestinationHDC As Long, ByRef Position As POINTL)
GdipDrawImage hGraphics, hBitmap, Position.X, Position.Y
End Sub
the 'POINTL' is an user type and must be used on DrawImage() sub parameter...
heres how i use it:
Code:
Dim s As POINTL
s.X = 0
s.Y = 0
img.DrawImage Me.hdc, s
error message: "byref argument type mismatch"
how can i use a user type argument on functions\subs parameters?
-
Oct 25th, 2020, 07:47 PM
#2
Re: vb6: how use an user type parameter on a class function\sub?
You did not show the code where you call the sub. Are you sure you are passing the right thing?
-
Oct 26th, 2020, 03:23 AM
#3
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by joaquim
Code:
Private Type POINTL
X As Long
Y As Long
End Type
Friend Sub DrawImage(DestinationHDC As Long, ByRef Position As POINTL)
GdipDrawImage hGraphics, hBitmap, Position.X, Position.Y
End Sub
the 'POINTL' is an user type and must be used on DrawImage() sub parameter...
heres how i use it:
Code:
Dim s As POINTL
s.X = 0
s.Y = 0
img.DrawImage Me.hdc, s
error message: "byref argument type mismatch"
how can i use a user type argument on functions\subs parameters?
Move struct POINTL definition to a standard module (.bas file) and make it Public.
On a side node: This way DrawImage can even be a method of *public* class in an ActiveX DLL. It's ok as long as the UDT is not exposed on a public interface, one that must be encoded in a typelib. This would not be possible with types in standard modules.
cheers,
</wqw>
-
Oct 26th, 2020, 04:57 PM
#4
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
wqweto: so everytime that i share the class, i must share the module file too?
why i can't create a type, inside the class, and use it on class?
-
Oct 27th, 2020, 01:54 AM
#5
Re: vb6: how use an user type parameter on a class function\sub?
That’s a normal scenario, unless you call a method from outside the class which requires a variable from type POINTL as a parameter
-
Oct 27th, 2020, 01:58 AM
#6
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by joaquim
wqweto: so everytime that i share the class, i must share the module file too?
why i can't create a type, inside the class, and use it on class?
Shortcoming of the the compiler. You cannot have a *public* UDT on a private class with same project scope the way public UDTs are implemented in a standard .bas module.
The compiler allows UDTs on private classes to be with private scope only and as a consequence these UDTs cannot be used/dimensioned in other modules of the project. So no callsite to the (friend) method can be compiled as no expression/variable can be supplied for its POINTL parameter.
If you try passing a Variant for the POINTL parameter you get a compile error "ByRef argument type mismatch" but UDTs cannot be passed ByVal at all in VB6 :-))
cheers,
</wqw>
-
Oct 27th, 2020, 02:34 AM
#7
Re: vb6: how use an user type parameter on a class function\sub?
hrhrhrhrhr.....
Written in Office/VBA (that's why the PtrSafe and LongPtr is there)
Code:
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Type POINTL
x As Long
y As Long
End Type
Private Sub DrawImage(ByVal hDC As Long, ByVal APoint As LongPtr)
Dim p As POINTL
CopyMemory ByVal VarPtr(p), ByVal APoint, LenB(p)
Debug.Print p.x '--> Prints 10
Debug.Print p.y '--> Prints 20
End Sub
Sub main()
Dim MyPoint As POINTL
MyPoint.x = 10
MyPoint.y = 20
DrawImage 0, VarPtr(MyPoint)
End Sub
Last edited by Zvoni; Oct 27th, 2020 at 03:13 AM.
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Oct 27th, 2020, 03:46 AM
#8
Re: vb6: how use an user type parameter on a class function\sub?
Maybe I'm thinking to simple, but why not pass 2 parameters:
Code:
Friend Sub DrawImage(DestinationHDC As Long, xPos As Long, yPos As Long)
GdipDrawImage hGraphics, hBitmap, xPos, yPos
End Sub
Then there is no need for a public POINTL udt and you can use your basic scenario:
Code:
'Dim s As POINTL
's.X = 0
's.Y = 0
'img.DrawImage Me.hdc, s
img.DrawImage Me.hdc, 0, 0
-
Oct 27th, 2020, 06:11 AM
#9
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by Arnoutdv
Maybe I'm thinking to simple, but why not pass 2 parameters:
Code:
Friend Sub DrawImage(DestinationHDC As Long, xPos As Long, yPos As Long)
GdipDrawImage hGraphics, hBitmap, xPos, yPos
End Sub
Then there is no need for a public POINTL udt and you can use your basic scenario:
Code:
'Dim s As POINTL
's.X = 0
's.Y = 0
'img.DrawImage Me.hdc, s
img.DrawImage Me.hdc, 0, 0
Had that thought, too, but since it's Graphic-API's i wouldn't be surprised when there are other API's waiting down the code, which actually are expecting a POINT-Structure as an argument
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Oct 27th, 2020, 06:34 AM
#10
Re: vb6: how use an user type parameter on a class function\sub?
I agree, but all "graphic" code is in the class, so keep it there.
No problem to construct the UDT from the 2 coordinates.
-
Oct 27th, 2020, 06:39 AM
#11
Re: vb6: how use an user type parameter on a class function\sub?
I admit: It's been some time having tried something like this,
but, couldn't he define a "child"-class "POINTL" with just two public Properties (x and y As Long), in this mode "Public - Not creatable" (or whatever it's called),
and expose this class as Public Property for his base-Class?
AFAIK, passing a class to a Function as Argument, should be possible.
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Oct 27th, 2020, 07:31 AM
#12
Re: vb6: how use an user type parameter on a class function\sub?
Well, there are games you might play. For example:
POINTL.cls
Code:
Option Explicit
'Mark as VB_PredeclaredId = True using a text editor.
Private Type tagPOINTL
X As Long
Y As Long
End Type
Private mPOINTL As tagPOINTL
Public Property Get X() As Long
X = mPOINTL.X
End Property
Public Property Let X(ByVal RHS As Long)
mPOINTL.X = RHS
End Property
Public Property Get Y() As Long
Y = mPOINTL.Y
End Property
Public Property Let Y(ByVal RHS As Long)
mPOINTL.Y = RHS
End Property
'A convenience member. Mark as Default:
Public Function Assign(ByVal X As Long, ByVal Y As Long) As POINTL
mPOINTL.X = X
mPOINTL.Y = Y
Set Assign = Me
End Function
'Used only within companion classes, not in client code:
Friend Property Get pPOINTL() As Long
pPOINTL = VarPtr(mPOINTL)
End Property
Friend Property Get cbPOINTL() As Long
cbPOINTL = LenB(mPOINTL)
End Property
Graphics.cls
Code:
Option Explicit
'Just for show, not a real Declare but a stand-in:
Private Function FakeDeclare(ByVal pPOINTL As Long) As Long
'We have a pointer to the UDT.
FakeDeclare = vbRed 'Prentend all pixels are red here, i.e. return a phoney value.
End Function
Public Function GetPixel(ByVal POINTL As POINTL) As Long
GetPixel = FakeDeclare(POINTL.pPOINTL)
End Function
Then we can have things like:
Form1.frm
Code:
Option Explicit
Private Sub Form_Load()
Dim Graphics As Graphics
Dim ptlPersistent As POINTL
Set Graphics = New Graphics
Debug.Print Graphics.GetPixel(POINTL(30, 30)) 'Use the predeclared instance.
Set ptlPersistent = New POINTL
ptlPersistent 15, 100
Debug.Print Graphics.GetPixel(ptlPersistent)
End Sub
-
Oct 27th, 2020, 12:31 PM
#13
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by Arnoutdv
Maybe I'm thinking to simple, but why not pass 2 parameters:
Code:
Friend Sub DrawImage(DestinationHDC As Long, xPos As Long, yPos As Long)
GdipDrawImage hGraphics, hBitmap, xPos, yPos
End Sub
This seems the easiest solution and a "Friend" scope isn't needed either in that case. In addition, if the class has a privately declared POINTL (or whatever), that DrawImage can Dim its own UDT from the passed parameters and then pass that UDT downstream to other private methods in the class where a UDT is a parameter
In other cases, I have used 2 data-related parameters for passing things by pointer, i.e.,
Code:
Public Sub SomeMethod(... params..., ByVal ptrData As Long, ByVal Count As Long)
' call API passing ptrData and Count as API parameters if so-defined
' i.e., SomeMethod params, VarPtr(myUDT), 1
End Sub
Public Sub SomeMethod2(... params..., ByVal ptrData As Long, ByVal SizeInBytes As Long)
' call API passing ptrData and SizeInBytes as API parameters if so-defined
' i.e., SomeMethod2 params, VarPtr(myUDT), LenB(myUDT)
End Sub
This type of solution is very similar to APIs that expect pointers, i.e., ByRef parameters. However, this type of solution is prone for crashes if the passed parameter values are not 100% correct.
Last edited by LaVolpe; Oct 27th, 2020 at 12:41 PM.
-
Oct 27th, 2020, 03:52 PM
#14
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
dilettante: imagine that i have 10 types, so i need create 10 class's
so the best is create all types\structures and declare all GDIPLUS functions\sub's on a module and then i can use it on a class...
so, if i share the class, i must share the module too.
even these test sub give me the similar\same error:
Code:
Private Sub DrawImagePoint(DestinationHDC As Long, ByRef Position As Variant)
Dim s As POINTL
s = Position
GdipDrawImage hGraphics, hBitmap, s.X, s.Y
End Sub
thank you so much for all to all
-
Oct 27th, 2020, 04:07 PM
#15
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by joaquim
dilettante: imagine that i have 10 types, so i need create 10 class's
Sure, it seems a bit crazy.
But look at what you get in most of the libraries designed for VB6 use, both DLLs and OCXs. They almost never provide structs but provide class wrappers instead.
The "sharing" unit for VB6 is the DLL or OCX, not source code. Do that and your problems disappear.
-
Oct 27th, 2020, 05:05 PM
#16
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
i never did a DLL\lib.. but i can learn it
-
Oct 30th, 2020, 05:06 PM
#17
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
on a module:
Code:
Option Explicit
Public Declare Function GetLastError Lib "kernel32" () As Long
Public Declare Function GetActiveWindow Lib "user32" () As Long
Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (ptr() As Any) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
'Get Key state:
Public Const KEY_DOWN As Integer = &H8000
Public Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As KeyCodeConstants) As Integer
'GDIPlus:
Public Type POINTL
X As Long
Y As Long
End Type
Public Enum GP_Result
GP_OK = 0
GP_GenericError = 1
GP_InvalidParameter = 2
GP_OutOfMemory = 3
GP_ObjectBusy = 4
GP_InsufficientBuffer = 5
GP_NotImplemented = 6
GP_Win32Error = 7
GP_WrongState = 8
GP_Aborted = 9
GP_FileNotFound = 10
GP_ValueOverflow = 11
GP_AccessDenied = 12
GP_UnknownImageFormat = 13
GP_FontFamilyNotFound = 14
GP_FontStyleNotFound = 15
GP_NotTrueTypeFont = 16
GP_UnsupportedGDIPlusVersion = 17
GP_GDIPlusNotInitialized = 18
GP_PropertyNotFound = 19
GP_PropertyNotSupported = 20
End Enum
Public Type GDIPlusStartupInput
GDIPlusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Public Declare Function GdiplusStartup Lib "gdiplus" (Token As Long, inputbuf As GDIPlusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Public Declare Function GdipLoadImageFromFile Lib "GdiPlus.dll" (ByVal mFilename As Long, ByRef mImage As Long) As Long
Public Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
Public Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, hGraphics As Long) As Long
Public Declare Function GdipDrawImage Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mImage As Long, ByVal mX As Single, ByVal mY As Single) As Long
Public Declare Function GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
Public Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal Token As Long)
Public Declare Function GdipDrawImageI Lib "gdiplus" (ByVal dstGraphics As Long, ByVal srcImage As Long, ByVal X As Long, ByVal Y As Long) As GP_Result
Public Declare Function GdipCreateFromHWND Lib "gdiplus" (ByVal hwnd As Long, Graphics As Long) As GP_Result
Public Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal Graphics As Long, ByVal lColor As Long) As Long
'Draw array Vertices:
Public Type POINTAPI
X As Long
Y As Long
End Type
Public Declare Function PlgBlt Lib "gdi32" ( _
ByVal hdcDest As Long, lpPoint As POINTAPI, ByVal hdcSrc As Long, ByVal nXSrc As Long, ByVal nYSrc As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hbmMask As Long, ByVal xMask As Long, ByVal yMask As Long) As Long
Public Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
'Faux "TrapezoidBlt" operation.
'
'Quick and dirty: Two PictureBox controls AutoRedraw = True to use their DCs.
' Picture1 prefilled with a bitmap to blit.
Public Enum StretchBltModes
[_SBMFAILED] = 0
BLACKONWHITE = 1
WHITEONBLACK = 2
COLORONCOLOR = 3
HALFTONE = 4
End Enum
Public Declare Function SetStretchBltMode Lib "gdi32" ( _
ByVal hdc As Long, _
ByVal StretchMode As StretchBltModes) As StretchBltModes
Public Declare Function StretchBlt Lib "gdi32" ( _
ByVal hdcDest As Long, _
ByVal nXOriginDest As Long, _
ByVal nYOriginDest As Long, _
ByVal nWidthDest As Long, _
ByVal nHeightDest As Long, _
ByVal hdcSrc As Long, _
ByVal nXOriginSrc As Long, _
ByVal nYOriginSrc As Long, _
ByVal nWidthSrc As Long, _
ByVal nHeightSrc As Long, _
Optional ByVal dwRop As RasterOpConstants = vbSrcCopy) As Long
Public Declare Function TransparentBlt Lib "msimg32" ( _
ByVal hdcDest As Long, _
ByVal nXOriginDest As Long, _
ByVal nYOriginDest As Long, _
ByVal nWidthDest As Long, _
ByVal hHeightDest As Long, _
ByVal hdcSrc As Long, _
ByVal nXOriginSrc As Long, _
ByVal nYOriginSrc As Long, _
ByVal nWidthSrc As Long, _
ByVal nHeightSrc As Long, _
ByVal crTransparent As Long) As Long
Public Enum Coordenates
None
Z
X
Y
End Enum
Public Type Position3D
X As Double
Y As Double
Z As Double
End Type
Public Type Angle3D
X As Double
Y As Double
Z As Double
RotationPosition3D As Position3D
End Type
Public Type Size3D
Width As Double
Height As Double
ZDepth As Double
distance As Double
End Type
Public Type Player
Position As Position3D
Movement As Position3D
size As Size3D
angle As Angle3D
MoveCoordenates As Coordenates
End Type
Public Type Camera
Position As Position3D
size As Size3D
End Type
Public Const Pi As Double = 3.14159265358979
everything is public, but i get the same error on my class:
Code:
Option Explicit
Private GDIsi As GDIPlusStartupInput, gToken As Long, hGraphics As Long, hBitmap As Long
Public X As Long
Public Y As Long
Public Z As Long
Public ImageHeight As Long
Public ImageWidth As Long
Private Pi As Double
Private Sub Class_Initialize()
Pi = 4 * Atn(1)
X = 0
Y = 0
Z = 0
GDIsi.GDIPlusVersion = 1&
GdiplusStartup gToken, GDIsi
If Err Then
Err.Clear
Exit Sub
ElseIf gToken = 0& Then
Exit Sub
End If
On Error GoTo 0
Call GdipCreateFromHWND(GetActiveWindow(), hGraphics)
End Sub
Private Sub Class_Terminate()
If hBitmap Then
GdipDisposeImage hBitmap
End If
GdipDeleteGraphics hGraphics
End Sub
Public Sub FromImageFile(ByVal FileName As String)
Call GdipGraphicsClear(hGraphics, &HFFFF0000)
Call GdipLoadImageFromFile(StrPtr(FileName), hBitmap)
End Sub
Friend Sub DrawImage(DestinationHDC As Long, PositionX As Long, PositionY As Long)
GdipDrawImage hGraphics, hBitmap, PositionX, PositionY
End Sub
'edit:
Public Sub DrawImageTrapezoid(Points() As POINTAPI, ByVal DestinationHDC As Long, ByVal TranspColor As Long)
Dim ScanLines As Long
Dim FullWidth As Long
Dim ScanWidth As Single
Dim ScanLeft As Single
Dim Delta As Single
Dim sbmOrig As StretchBltModes
Dim ScanLine As Long
Dim ScanZ As Single
Dim ScanZDec As Single
'Points(0) - UpperLeft
'Points(1) - UpperRight
'Points(2) - LowRight
'Points(3) - LowLeft
Dim PctTop As Long
PctTop = Points(2).X - Points(3).X
ScanLines = ImageHeight
FullWidth = ImageWidth
ScanWidth = ImageWidth * PctTop / 100
ScanLeft = (ImageWidth - ScanWidth) / 2
Delta = ScanLeft / ScanLines
sbmOrig = SetStretchBltMode(DestinationHDC, HALFTONE)
ScanZ = 1 + (PctTop / 100)
ScanZDec = ((PctTop / 100)) / ScanLines
For ScanLine = 0 To ScanLines - 1
StretchBlt DestinationHDC, _
ScanLeft + Points(0).X, _
ScanLine + Points(0).Y, _
ScanWidth, _
1, _
hGraphics, _
0, _
ScanLine * ScanZ, _
FullWidth, _
1
ScanLeft = ScanLeft - Delta
ScanWidth = ScanWidth + 2 * Delta
ScanZ = ScanZ - ScanZDec
Next
SetStretchBltMode DestinationHDC, sbmOrig
End Sub
why?
(on DrawImageTrapezoid())
-
Oct 31st, 2020, 12:05 AM
#18
Re: vb6: how use an user type parameter on a class function\sub?
I do not see where you are calling that sub, are you passing it an array of the udt?
-
Oct 31st, 2020, 05:25 PM
#19
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
DataMiser: the error message is on Compilation step.
-
Oct 31st, 2020, 06:46 PM
#20
Re: vb6: how use an user type parameter on a class function\sub?
To make a UDT "public" in the sense meant there you can't just use the "Public" decorator on it.
It must be "published" on the local system. That means defining it within a registered type library. For VB6 that means a registered ActiveX EXE or DLL unless you have created a TLB separately and registered that.
Your only other option is to use the "behind the back of COM" approach of defining the procedure(s) as "Friend" instead of "Public." This can make use of Public-but-unpublished UDTs because there will never be any COM Marshaling required.
Last edited by dilettante; Oct 31st, 2020 at 07:30 PM.
-
Nov 1st, 2020, 03:04 AM
#21
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by dilettante
This can make use of Public-but-unpublished UDTs because there will never be any COM Marshaling required.
If I may expand on this:
- "Private-and-unpublished" means it can only be used within the scope of the module it's declared in.
- "Public-but-unpublished" means public within the scope of the project -- can be used by every module in the project (not project group).
- "Public-in-typelib" means public within the scope of the machine -- every project can reference the typelib and use it in every module.
cheers,
</wqw>
-
Nov 1st, 2020, 07:34 AM
#22
Re: vb6: how use an user type parameter on a class function\sub?
User-Defined Data Types is brief but worth reading.
The same article appears in the Automation section of the MSDN Help used by VB6, though you probably won't have it if you never got updated CDs through the subscription that was provided with legal copies of Visual Studio 6.
Beginning with Windows NT 4.0 SP4, Windows 95 with DCOM 1.2, and Windows 98, Automation now supports passing UDTs in variants and safearrays of user defined types as arguments to methods.
That support is enabled by IRecordInfo definitions in typelibs.
-
Nov 1st, 2020, 10:10 PM
#23
Re: vb6: how use an user type parameter on a class function\sub?
Originally Posted by joaquim
DataMiser: the error message is on Compilation step.
You still did not show the line that calls it, nor did you answer my question as to if you were passing it an array. Type mismatch usually means you are passing the wrong thing.
-
Nov 2nd, 2020, 04:01 PM
#24
Thread Starter
PowerPoster
Re: vb6: how use an user type parameter on a class function\sub?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|