I have a custom TYPE I want to put into a dictionary with a string key. Are any examples available?
Hi Richard, here my Tip for an short example , show in J.R. docs folder of AfxNova-Main (Github)
CDicObj (https://github.com/JoseRoca/AfxNova/blob/main/docs/Windows/Windows%20Script/CDicObj%20Class.md)
can be found in ..\docs\Windows\Windows Script\CDicObj Class.md
b.r. Hans (hajubu)
PS: see also the full .md collection as an HTML-Webview , which can be integrated in the Tiko as an help tool.
docs-as-Html for Tiko1.3/AfxNova (https://www.planetsquires.com/protect/forum/index.php?msg=36544)
find it here in this Support Forum -- PlanetSquires Software --# Tiko 1.3 and AfxNova Docs as integrated HelpTool #10
--> CDicObj Class
-->
CDicObj is an associative array of variants. Each item is associated with a unique key. The key is used to retrieve an individual item.
Example
' // Creates an instance of the CDicObj class
DIM pDic AS CDicObj
' // Adds some key, value pairs
pDic.Add "a", "Athens"
pDic.Add "b", "Belgrade"
pDic.Add "c", "Cairo" ..........and so on .....
I'll study things a bit. I've reached way back to PowerBasic days and I'm looking for replacements for LinkListCollection and PowerCollection.
What I'm trying to figure out is how to add a custom type like:
Type FontDescriptor
FontName As ZSTRING * 30
FontID As Long
FontStyle As Long
FontReferenced As Long
FontAscent As Long
FontCapHeight As Long
FontDescent As Long
FontFlags As Long
FontRectLeft As Long
FontRectTop As Long
FontRectRight As Long
FontRectBottom As Long
FontItalicAngle As Double
FontStemV As Long
FontWeight As Long
FontUnderlineThickness As Long
FontUnderlinePosition As Long
FontObject As Long
FontWidthObject As Long
FontDescriptorObject As Long
End Type
I'm getting a little closer using:
DIM uDescriptor As FontDescriptor
DIM uDescriptor1 As FontDescriptor
DIM oDicObj AS CDicObj
DIM sDescriptor AS STRING * LEN(UDescriptor)
DIM sDescriptor1 AS STRING
uDescriptor.FontName = "Arial"
uDescriptor.FontID = 1
uDescriptor.FontStyle = 1
uDescriptor.FontReferenced = 0
uDescriptor.FontAscent = 905
uDescriptor.FontCapHeight = 728
uDescriptor.FontDescent = -210
uDescriptor.FontFlags = 32
uDescriptor.FontRectLeft = -666
uDescriptor.FontRectTop = -210
uDescriptor.FontRectRight = 2000
uDescriptor.FontRectBottom = 728
uDescriptor.FontItalicAngle = 0
uDescriptor.FontStemV = 44
uDescriptor.FontWeight = 400
uDescriptor.FontUnderlineThickness = 73
uDescriptor.FontUnderlinePosition = -106
memcpy (StrPtr(sDescriptor), @uDescriptor, LEN(UDescriptor))
oDicObj.Add("F1",sDescriptor)
sDescriptor1 = oDicObj.Item("F1")
memcpy (@uDescriptor1, StrPtr(sDescriptor1), LEN(uDescriptor1))
print uDescriptor1.FontName
print str(uDescriptor1.FontID)
print str(uDescriptor1.FontStyle)
print str(uDescriptor1.FontReferenced)
print str(uDescriptor1.FontAscent)
print str(uDescriptor1.FontCapHeight)
print str(uDescriptor1.FontDescent)
print str(uDescriptor1.FontFlags)
print str(uDescriptor1.FontRectLeft)
print str(uDescriptor1.FontRectTop)
print str(uDescriptor1.FontRectRight)
print str(uDescriptor1.FontRectBottom)
print str(uDescriptor1.FontItalicAngle)
print str(uDescriptor1.FontStemV)
print str(uDescriptor1.FontWeight)
print str(uDescriptor1.FontUnderlineThickness)
print str(uDescriptor1.FontUnderlinePosition)
I'm not getting back what I sent in. More analysis needed.
hi,
I just added a 'Little' and had working output result:
'REMARK I did not use #cmdline option in Tiko !!! do NOT use -'s gui' for an ' -s console'
'I prefer to set the pref. to win console64 (shift-f7 ....) and in the basic - env - compiler pref to ' using cmd windows '
'!!!!!! IF you did (-s gui) on a console -check- you have to kill the running application manually via Taskmanager
' ALSO with the 'SLEEP at the end - do not forget to close it manually.
----------------
Arial
42926416
0
1662031610
29243
42926416
0
42934288
0
... and_eight_more_zeros
-------------------------
'CdicObj_RK_sample_onConsole
'REMARK I did not use #cmdline option in Tiko !!! do NOT use -'s gui' for an ' -s console'
'#cmdline "-s console" ' console application
''''''''''''''''''''''''''''''#cmdline "-s gui" ' gui application
'#cmdline "resource.rc" ' resource file
'REMARK
#include once "AfxNova\CdicObj.inc"
'
' then the Type...End section/region
Type FontDescriptor
.......................................
Type End
'
'then a copy of your 'code' region p to the last print statement
DIM uDescriptor As FontDescriptor
DIM uDescriptor1 As FontDescriptor
DIM oDicObj AS CDicObj
DIM sDescriptor AS STRING * LEN(UDescriptor)
DIM sDescriptor1 AS STRING
uDescriptor.FontName = "Arial"
uDescriptor.FontID = 1
'......up_to....
print str(uDescriptor1.FontUnderlinePosition)
'
'THEN a
SLEEP
' to ensure halting the console output ... waiting for a needed key <Enter>
Quote from: hajubu on May 02, 2026, 06:45:56 PMArial
42926416
0
1662031610
29243
42926416
0
42934288
0
... and_eight_more_zeros
That doesn't match up with what I sent into CDicObj. I think presence of x'00' s might in play. If I populate my first type, memcpy it to a string then memcpy from that string to a second type, the second type is equal to the first.
Problem solved....for now unless someone has a better idea. I just used AfxBase64EncodeA passed in and AfxBase64DecodeA on what came out with memcpy along the way.
The correct way is to use the IRecordInfo interface and assign the pointer to a variant of the type VT_RECORD. I will have to write a class to wrap the IRecordInfo interface. And please, when using COM forget ansi. Use WSTRING instead of ZSTRING. Using AfxNova, you better forget ansi forever.
I didn't know about IRecordInfo. The Zstring reference in that font UDT was what I just copied over from the old PowerBasic code I am looking to port. I can easily change that to WSTRING. I tried both the "W" and "A" versions of B24 calls any only the "A" version worked. I look forward to a more direct way to handle UDT's with CDicObj which is a great replacement for the PB PowerCollection.
Forget IRecordInfo. It is an interface added for Automation languages like VB6 and needs the use of a type library.
Regarding PowerBasic, it is using the trick of converting the udt to a string. This can work if the udt only contains primitive types, not objects or variants.
After thinking it over, this is the solution I've come up with. It stores the UDT as an array of unsigned bytes (a VT_ARRRAY OR VT_UI1 variant).. Works with ZSTRING too.
#cmdline "-s console"
#INCLUDE ONCE "AfxNova/CDicObj.inc"
USING AfxNova
TYPE Foo
x AS long
y as long
b as WSTRING * 260
END type
' // Creates an instance of the CDicObj class
DIM pDic AS CDicObj
' // Creates an instance of the Foo type
DIM t AS Foo = (12345, 72727, "Test string")
' // Assigns it to a DVARIANT
DIM dv AS DVARIANT
dv.PutBuffer(@t, SIZEOF(t))
' // Adds the type to the dictionary
pDic.Add "Foo1", dv
' // Creates another instance of the Foo type
DIM t2 AS Foo = (111111, 22222, "Test string 2")
' // Assigns it to a DVARIANT
DIM dv2 AS DVARIANT
dv2.PutBuffer(@t2, SIZEOF(t2))
' // Adds the type to the dictionary
pDic.Add "Foo2", dv2
' // Gets Foo1 from the dictionary
DIM dvFoo1 AS DVARIANT
dvFoo1 = pDic.Item("Foo1")
' // Assigns it to a Foo structure
DIM tFoo1 AS Foo
dvFoo1.ToBuffer(@tFoo1, SIZEOF(tFoo1))
' // DIsplays the values
print tFoo1.x
print tFoo1.y
print tFoo1.b
' // Gets Foo2 from the dictionary
DIM dvFoo2 AS DVARIANT
dvFoo2 = pDic.Item("Foo2")
' // Assigns it to a Foo structure
DIM tFoo2 AS Foo
dvFoo2.ToBuffer(@tFoo2, SIZEOF(tFoo2))
' // DIsplays the values
print tFoo2.x
print tFoo2.y
print tFoo2.b
PRINT
PRINT "Press any key..."
SLEEP
Oh wow! Updated my code to follow your example and, of course, it works perfectly.
Type FontDescriptor
FontName As WSTRING * 30
FontID As Long
FontStyle As Long
FontReferenced As Long
FontAscent As Long
FontCapHeight As Long
FontDescent As Long
FontFlags As Long
FontRectLeft As Long
FontRectTop As Long
FontRectRight As Long
FontRectBottom As Long
FontItalicAngle As Double
FontStemV As Long
FontWeight As Long
FontUnderlineThickness As Long
FontUnderlinePosition As Long
FontObject As Long
FontWidthObject As Long
FontDescriptorObject As Long
End Type
DIM uDescriptor AS FontDescriptor
DIM uDescriptor1 AS FontDescriptor
DIM oDicObj AS CDicObj
DIM dv AS DVARIANT
uDescriptor.FontName = "Arial"
uDescriptor.FontID = 1
uDescriptor.FontStyle = 1
uDescriptor.FontReferenced = 0
uDescriptor.FontAscent = 905
uDescriptor.FontCapHeight = 728
uDescriptor.FontDescent = -210
uDescriptor.FontFlags = 32
uDescriptor.FontRectLeft = -666
uDescriptor.FontRectTop = -210
uDescriptor.FontRectRight = 2000
uDescriptor.FontRectBottom = 728
uDescriptor.FontItalicAngle = 0
uDescriptor.FontStemV = 44
uDescriptor.FontWeight = 400
uDescriptor.FontUnderlineThickness = 73
uDescriptor.FontUnderlinePosition = -106
dv.PutBuffer(@uDescriptor, SIZEOF(uDescriptor))
oDicObj.Add "F1", dv
dv = oDicObj.Item("F1")
dv.ToBuffer(@uDescriptor1, SIZEOF(uDescriptor1))
print uDescriptor1.FontName
print str(uDescriptor1.FontID)
print str(uDescriptor1.FontStyle)
print str(uDescriptor1.FontReferenced)
print str(uDescriptor1.FontAscent)
print str(uDescriptor1.FontCapHeight)
print str(uDescriptor1.FontDescent)
print str(uDescriptor1.FontFlags)
print str(uDescriptor1.FontRectLeft)
print str(uDescriptor1.FontRectTop)
print str(uDescriptor1.FontRectRight)
print str(uDescriptor1.FontRectBottom)
print str(uDescriptor1.FontItalicAngle)
print str(uDescriptor1.FontStemV)
print str(uDescriptor1.FontWeight)
print str(uDescriptor1.FontUnderlineThickness)
print str(uDescriptor1.FontUnderlinePosition)
Time to figure out PB LinkListCollection
I have DWstrList and DVarList:
https://github.com/JoseRoca/AfxNova/blob/main/docs/String%20Management%20/Linked%20Lists.md
I also have stacks (CStack) and queues (CQueue):
See: https://github.com/JoseRoca/AfxNova/blob/main/docs/COM%20/Stacks%20and%20Queues.md
This completes the PowerCollection.
Thank you Jose. I'll certainly look into all of them as I progress with porting this PowerBasic project from 15 years ago.
I have the first piece done, a class that defines all the fonts. See attached.
Code I used to check it out...Got some sleeps in there so you have to press a key to get through it. I did that so I could see each section.
#cmdline "-s console" ' console application
#DEFINE UNICODE
#DEFINE _WIN32_WINNT &h0602
#INCLUDE ONCE "crInc\cPDF\cPDFFonts.bi"
USING AfxNova
Type FontDescriptor
FontName As WSTRING * 30
FontID As Long
FontStyle As Long
FontReferenced As Long
FontAscent As Long
FontCapHeight As Long
FontDescent As Long
FontFlags As Long
FontRectLeft As Long
FontRectTop As Long
FontRectRight As Long
FontRectBottom As Long
FontItalicAngle As Double
FontStemV As Long
FontWeight As Long
FontUnderlineThickness As Long
FontUnderlinePosition As Long
FontObject As Long
FontWidthObject As Long
FontDescriptorObject As Long
End Type
DIM oPDFFonts AS cPDFFonts
DIM sFontID AS DWSTRING
DIM dvFont AS DVARIANT
DIM sWidth AS DWSTRING
DIM uDescriptor AS FontDescriptor
print "Total Defined Fonts=" + str(oPDFFonts.TotalFonts)
print ""
SLEEP
oPDFFonts.GetFont(1, sFontID, dvFont, sWidth)
dvFont.ToBuffer(@uDescriptor, SIZEOF(uDescriptor))
print "Font Descriptor"
print ""
print uDescriptor.FontName
print str(uDescriptor.FontID)
print str(uDescriptor.FontStyle)
print str(uDescriptor.FontReferenced)
print str(uDescriptor.FontAscent)
print str(uDescriptor.FontCapHeight)
print str(uDescriptor.FontDescent)
print str(uDescriptor.FontFlags)
print str(uDescriptor.FontRectLeft)
print str(uDescriptor.FontRectTop)
print str(uDescriptor.FontRectRight)
print str(uDescriptor.FontRectBottom)
print str(uDescriptor.FontItalicAngle)
print str(uDescriptor.FontStemV)
print str(uDescriptor.FontWeight)
print str(uDescriptor.FontUnderlineThickness)
print str(uDescriptor.FontUnderlinePosition)
SLEEP
print ""
print "Font Widths"
print ""
print sWidth
SLEEP
In case your curious about the comma delimited list of font widths, they will eventually get parsed out using AfxArrays and AfxStr with code like this:
DIM nStart AS LONG = 1
DIM arWidths() AS LONG
WHILE nStart < LEN(sWidthList)
sWidth = AfxStrExtract(nStart,sWidthList,",",",")
AppendElementToArray (arWidths, CLNG(sWidth))
nStart = nStart + LEN(sWidth) + 1
WEND
Quote from: José Roca on May 03, 2026, 06:40:57 PMI have DWstrList and DVarList:
https://github.com/JoseRoca/AfxNova/blob/main/docs/String%20Management%20/Linked%20Lists.md
PB supports:
ILinkListCollection.ADD method adds am item to the end of the LinkListCollection.
ILinkListCollection.CLEAR method removes all items from the LinkListCollection.
ILinkListCollection.COUNT method returns the number of items currently in the LinkListCollection.
ILinkListCollection.FIRST method sets the current index for the LinkListCollection to one (1) and returns the previous value.
ILinkListCollection.INDEX method sets the current index for the LinkListCollection to the specified value and returns the previous value.
ILinkListCollection.INSERT method adds the specified item to the specified index position..
ILinkListCollection.ITEM method returns the item from the specified index position.
ILinkListCollection.LAST method sets the index value to the last item and returns the previous value.
ILinkListCollection.NEXT method returns the next item in the LinkListCollection.
ILinkListCollection.PREVIOUS method returns the previous item in the LinkListCollection.
ILinkListCollection.REMOVE method removes the item at the specified position from the LinkListCollection.
ILinkListCollection.REPLACE method replaces the item at the specified position with a new item in the LinkListCollection.
This old PB code I'm looking at uses:
Count, Clear, Item, Replace, Add
I think I'll move forward with DVarList and DWStrList
I have made mine indexed, allowing to work as if they were arrays.
' // Retrieve and print the results
FOR i AS LONG = 1 TO List->Count
PRINT List->Item(i)
NEXT
Therefore, First, Last, Next, Previous and For Each aren't needed.
Although DVarList can be used with any data type, because it uses variants, DWStrList is optimized to work with DWSTRING and it is much faster when you only need to use strings.
I also have safe arrays, both dynamic and fixed size (vectors).
https://github.com/JoseRoca/AfxNova/blob/main/docs/COM%20/DSAFEARRAY%20Class.md