Results 1 to 4 of 4

Thread: Never use Len when you use unicode string.

  1. #1
    Member
    Join Date
    Aug 2015
    Location
    Keralam, India
    Posts
    121
    Rep Power
    21

    Never use Len when you use unicode string.

    Hi all,
    Last day, I was trying to create a static control (Label) for my gui toolkit. Eventually, I need to implement the AutoSize property for my tLabel type.
    After a few minutes of google search, I ended up in GetTextExtentPoint32W function. Here is the header.
    Declare Function GetTextExtentPoint32 Lib "Gdi32.dll" Alias "GetTextExtentPoint32W"(Byval hdc As Dword, 
                                                                                          Byval lpString As string,
                                                                                          ByVal c As Int32,
                                                                                          Byval psizl As Long) As Boolean
    
    The third parameter c is the length of the string in question. At first, I've use Len(Me.Text) for that. I got wrong results. My primary suspect was the type of second parameter. So I tried to change it to Asciiz, Wstring etc. But no luck. After wasting some hours, I decided to read about string functions in Win32. At that time, I noticed the lstrlenW function. Suddenly, I realized my mistake. Then I warped up lstrlen in a function like this.
    Function StrLen(sValue As String) As Int32
      Return lstrlen(UTF8ToWideChar$(sValue))
    End Function
    
    And here is the header.
    Declare Function lstrlen Lib "Kernel32.dll" Alias "lstrlenW"(ByVal lpString as string) As int32
    
    Then I got the correct result.
    Last edited by kcvinu; 30-04-2021 at 10:33.

  2. #2
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,527
    Rep Power
    170
    Quote Originally Posted by kcvinu View Post
    thats right. For Unicode, especially WideString use LenW.

    Hint: If an Win32-Function ends with a Capital Char and involves Strings as Parameter or returned value it a signals

    ...A: to be ANSI
    ...W: for unicode wide

    ...Ex: there was previously another Function that got Extended in any way now.


    and for thinBasic: if you see something trailing some keywords:

    ...$ : get ready to receive a string
    ...W : widechar involved
    ...Z : terminating zero ,for Utf-7/8 Ascii append $NUL,
    for Utf-16 append mkWrd$(0) or mkByt$(0, 0) or String$(2, $Nul)
    UCS-2/Utf-32 append mkDwd$(0), i.e. Repeat$(4, $Nul) or Chr$(0, 0, 0, 0)


    ...F is a faster solution of a function but requires mostly to work with a value stored to a dimensioned variable
    accepts virtually applied variables upon the memory as well.

    In some cases if subelement of subelement within an array of udt...

    its anyway fast style to name the thing locally when its used more than once.
    saves you repeatedly to type in "the same corners where to go around" like
     local lSetting as Long at varptr( 
                       myApp_settings.Editorsettings(
                                %Userdefined + currentUserID).codepage  )
    
    ' now that long thing above is just: lSetting
    
    before you type this a second or third time you will certainly consider to place a local name there and not calculate a second time %Userdefined+currrentUserID and additional every dot to signal it goes down another branch.of.something = that means for the processor to find the matching subelements name, lookup the distance from the root and add it - for each and every dot you typed

    Consider to move the name that is covering the bytes in memory and puts the mask of a variable onto it to another position relative to its current position is to prefer over calculating from the root (here: varptr(myApp_Settings)) again.
    To find distance and direction of movement subtract the actual position from the target position. Thats easy.

    setAt( lSetting, GetAt(lSetting)+(anotherUserID - currentUserID) * SizeOf(Editorsettings) )
    
    ' or if the next setting just were following the current:
    
    setAt(lSetting, GetAt(lSetting)+ SizeOf(lSetting))
    
    What you pre-calculate using "Brains 2.0 incl. ExpansionPack" while you are coding will make your code run faster
    I think there are missing some Forum-sections as beta-testing and support

  3. #3
    Member
    Join Date
    Aug 2015
    Location
    Keralam, India
    Posts
    121
    Rep Power
    21
    @Rene Miner,
    I am sorry, I didn't get you. I am confused about "SetAt". What is it used for ? To set a pointer at new memory location ?

  4. #4
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,527
    Rep Power
    170
    Quote Originally Posted by kcvinu View Post
    @Rene Miner,
    I am sorry, I didn't get you. I am confused about "SetAt". What is it used for ? To set a pointer at new memory location ?
    SetAt will place a virtual variable to another position
    GetAt will retrieve the current position
    IF you

    Dim x Like myObject.typename$ At myObject.DataPtr
    ' now x will let you access myObject 
    ' and if you have another object of the same type:
    if myOtherObject.typename$ = myObject.typename$ then
      setAt(x, myOtherObject.DataPtr)
      ' now x is myOtherObject
    endif
    'if you have an array/string/heap of dataptrs that point to objects 
    'lets say
    String sPtrs= mkDWD$(ptr1, ptr2, ptr3)
    ' easy to append more:
    sPtrs &= mkdwd$(ptr4, ptr5)
    
    store them to a heap 
    Dword pMyHeap=Heap_AllocByStr(sPtrs)
    
    ' append more? 
    Heap_Set(pMyHeap, Heap_Get(pMyHeap) & mkdwd$(ptr7, ptr8,...))
    
    'you could set a surfing-dword at the first or last one 
    Local surfer as Dword at pMyHeap
     '                                               (or at Heap_End(pMyHeap -3) to go backwards)
    repeat
    
    ' do something with the object the surfer points now
    ' will be one of ptr1, ptr2, ptr3 etc.
    
    ' then push the surfer forward 
      SetAt(Surfer, GetAt(Surfer) + SizeOf(Surfer) )
    '                                     - SizeOf... to go backward
    until getAt(Surfer)>= Heap_End(pMyHeap)
    '                  < pMyHeap if backwards
    
    this allows to iterate through an array. if the array is pointers (Dword) then the pointers can point different types,
    its like an array where any member can be of another type
    And
    Sub DoSomethingWith(byval pData as dword, byval sTypename as string)
    
    Local X LIKE sTypename at pData
    x.doSomething()
    End Sub
    
    lets you call same named functions on different types
    Last edited by ReneMiner; 02-05-2021 at 13:38.
    I think there are missing some Forum-sections as beta-testing and support

Similar Threads

  1. How to display unicode string in ThinBasic controls
    By kcvinu in forum UI (User Interface)
    Replies: 4
    Last Post: 03-04-2021, 02:06
  2. need a Unicode working example
    By fkapnist in forum thinBasic General
    Replies: 8
    Last Post: 27-11-2018, 09:39
  3. Does ThinAir supports Unicode ?
    By kcvinu in forum thinAir General
    Replies: 19
    Last Post: 29-08-2016, 14:57
  4. Proposed Wide String (Unicode) support in OxygenBasic
    By Charles Pegge in forum O2h Compiler
    Replies: 2
    Last Post: 27-02-2011, 04:08
  5. Is this ASCII, ANSI, UNICODE or something else?
    By martin in forum thinAir General
    Replies: 12
    Last Post: 29-04-2009, 09:56

Members who have read this thread: 1

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •