[VB] Pointer naar string

Pagina: 1
Acties:

  • MrDry
  • Registratie: December 2001
  • Laatst online: 21-08 16:48

MrDry

Desperados!

Topicstarter
ik ben een beetje aan het experimenteren geslagen met winamp plugins (in VB) maar ik zit met een klein vraagje.

Ik wil de bestandsnaam van een playlistentry hebben.

Op de nsdn site van winamp staat het volgende:

212 - Retrieves (and returns a pointer in 'ret') a string that contains the title of a playlist entry (indexed by 'data'). Returns NULL if error, or if 'data' is out of range.

Nu stuur ik mijn message op de volgende manier:
code:
1
2
3
Dim title As String , Dim Index as Integer
index = SendMessage(hwnd_winamp, WM_USER, 0, IPC_GETLISTPOS)
title = SendMessage(hwnd_winamp, WM_USER, index, WA_GETPLAYLISTTITLE)


In de variabele title krijg ik geen string maar een reeks getallen (bv. 4555848) ... Volgens mij is dit dus een pointer naar de string....

Nu heb ik hier wel iets gevonden: http://www.experts-exchan...ual_Basic/Q_20370991.html maar ik krijg nog steeds niet de string terug die ik verwacht.

Hoe krijg ik in VB nu de string i.p.v. de pointer?

[ Voor 3% gewijzigd door MrDry op 21-05-2003 16:44 ]

Quod licet lovi, non licet bovi


  • pkouwer
  • Registratie: November 2001
  • Laatst online: 07-10-2025
VB werkt niet met pointers

  • MrDry
  • Registratie: December 2001
  • Laatst online: 21-08 16:48

MrDry

Desperados!

Topicstarter
pkouwer schreef op 21 mei 2003 @ 21:44:
VB werkt niet met pointers
Dat weet ik ook wel :)

Maar...het is mogelijk om C routine in VB te gebruiken...alleen weet ik niet hoe ik bij de data kom....

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CopyStringA Lib "kernel32" Alias "lstrcpyA" (ByVal NewString As String, ByVal OldString As Long) As Long
Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Public Declare Function lstrlenA Lib "kernel32" (ByVal lpString As Long) As Long

'Get ANSI string from pointer. 
'lpzA - pointer to ANSI string
'nSize - size of string. If ommitted, string will be truncated up to first null char (chr(0))

Public Function StrFromPtrA(ByVal lpszA As Long, Optional nSize As Long = 0) As String
  Dim s As String, bTrim As Boolean
  If nSize = 0 Then
     nSize = lstrlenA(lpszA)
     bTrim = True
  End If
  s = String(nSize, Chr$(0))
  CopyStringA s, ByVal lpszA
  If bTrim Then s = TrimNULL(s)
  StrFromPtrA = s
End Function

'Get WIDE string from pointer (Unicode/DBCS). 
'lpzW - pointer to WIDE string
'nSize - size of string. If ommitted, string will be 
Public Function StrFromPtrW(ByVal lpszW As Long, Optional nSize As Long = 0) As String
  Dim s As String, bTrim As Boolean
  If nSize = 0 Then
     nSize = lstrlenW(lpszW)
     bTrim = True
  End If
  s = String(nSize, Chr$(0))
  CopyMemory ByVal StrPtr(s), ByVal lpszW, nSize
  If bTrim Then s = TrimNULL(s)
  StrFromPtrW = s
End Function

Public Function TrimNULL(ByVal str As String) As String
   If InStr(str, Chr$(0)) > 0& Then
       TrimNULL = Left$(str, InStr(str, Chr$(0)) - 1&)
   Else
       TrimNULL = str
   End If
End Function


Met bovenstaande code zou het moeten werken maar ik krijg wel een string terug als ik de pointer invul maar niet wat ik verwacht....

Iemand?

[ Voor 78% gewijzigd door MrDry op 21-05-2003 21:54 ]

Quod licet lovi, non licet bovi


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
VB kan wel werken met Pointers.

Kijk op MSDN voor de antwoorden ivm Strings (BStr vs null-ended strings)

  • MrDry
  • Registratie: December 2001
  • Laatst online: 21-08 16:48

MrDry

Desperados!

Topicstarter
hobbit_be schreef op 21 May 2003 @ 22:00:
VB kan wel werken met Pointers.

Kijk op MSDN voor de antwoorden ivm Strings (BStr vs null-ended strings)
Ik kom hier nog niet echt verder mee.

Ik weet dat het verschil tussen strings in VB en C is dat VB het gebruik van pointers zelf afhandeld en in C is krijg ik een referentie naar de String (de pointer dus)

Zou iemand me (iets verder) opweg kunnen helpen?

Quod licet lovi, non licet bovi


  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 09:12

johnwoo

3S-GTE

De kern van de code snippet hierboven is deze API call:
Visual Basic .NET:
1
CopyMemory ByVal StrPtr(s), ByVal lpszW, nSize

Een DLL wordt in de address space van een proces geladen, dus de functies in de DLL kunnen gewoon bij het geheugen van de applicatie module. Met die SendMessage krijg je van Winamp een pointer naar een stukje geheugen. Je DLL kan daar gewoon bij. De voor de hand liggende methode is dus om dat stukje geheugen te kopieren naar een eigen variabele, en wel met CopyMemory.

Echter komen daar bij VB nog wat onhandigheden bij kijken: VB werkt niet met ASCII strings, maar met Unicode. De pointer die je terug krijgt wijst naar een gewone ASCII string. Die zul je dus om moeten zetten. Daarnaast zijn VB strings niet null-terminated, maar dragen ze zelf hun lengte met zich mee. De pointer die je terug krijgt wijst naar een null-terminated string. Je zult dus die lstrlenA API moeten gebruiken om te bepalen hoe groot je de buffer van je eigen variabele moet maken.
Een oplossing is het gebruik van de MultiByteToWideChar API, die kopieert je ASCII string naar een nieuwe string, en zet hem tegelijkertijd om naar Unicode (en hij stopt netjes bij een null character). Helaas geen voorbeeldje van ASCII -> Unicode omzetting, maar ik heb hier wel een snippet die van een pointer naar een Unicode string, een ASCII string maakt:
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Public Function GetStrFromPtrW(lpszW As Long) As String
    Dim sRtn As String
    sRtn = String$(lstrlenW(ByVal lpszW) * 2, 0)   ' 2 bytes/char
    ' WideCharToMultiByte also returns Unicode string length
    Call WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, ByVal sRtn, Len(sRtn), 0, 0)
    GetStrFromPtrW = GetStrFromBufferA(sRtn)
End Function
' Returns the string before first null char encountered (if any) from an ANSII string.
Public Function GetStrFromBufferA(sz As String) As String
    If InStr(sz, vbNullChar) Then
        GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1)
    Else
        ' If sz had no null char, the Left$ function
        ' above would return a zero length string ("").
        GetStrFromBufferA = sz
    End If
End Function

Met wat gepruts, en het vervangen van WideCharToMultiByte door MultiByteToWideChar, moet dat wel aan de praat te krijgen zijn :)

[ Voor 9% gewijzigd door johnwoo op 21-05-2003 23:40 ]

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • MrDry
  • Registratie: December 2001
  • Laatst online: 21-08 16:48

MrDry

Desperados!

Topicstarter
@johnwoo

Bedankt voor je uitleg helaas ben ik er nog niet helemaal uit.

Als ik het goed begrijp verwijzen de C-pointers naar ANSI strings.
Dan zou ik met de onderstaande code toch de unicode string moeten kunnen terughalen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
'Get WIDE string from pointer (Unicode/DBCS).
'lpzW - pointer to WIDE string
'nSize - size of string. If ommitted, string will be
Private Function StrFromPtrW(ByVal lpszW As Long, Optional nSize As Long = 0) As String
  Dim s As String, bTrim As Boolean
  If nSize = 0 Then
     nSize = lstrlenW(lpszW)
     bTrim = True
  End If
  s = String(nSize, Chr$(0))
  CopyMemory ByVal StrPtr(s), ByVal lpszW, nSize
  If bTrim Then s = TrimNULL(s)
  StrFromPtrW = s
End Function


En vervolgens met het VB-commando StrConv er een unicodestring van maken.....
Helaas werkt dat niet. Wat mis ik hier?

Oja...ik heb ook geprobeerd jouw functie om te bouwen met MultiByteToWideChar maar dat viel niet mee. (ben bang dat dit net te hoog gegrepen is....)

[ Voor 2% gewijzigd door MrDry op 23-05-2003 13:38 . Reden: Typo ]

Quod licet lovi, non licet bovi


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Yow MrDry:

die laatste functies retrieved een Unicode String vanuit C(++) en niet een ascii string.
Je zult dus effe moeten checken wat jou c(++) in feite doorgeeft.

Effe verduidelijk: een ascii string heeft per character 1 byte, een unicode 2bytes (er is
ook nog zoiets als mb (waar dat de bytes per character anders zijn). In c(++) word deze weergegeven als w (wide-char) maar is dus niets dan een unsigned short.

De functies (pure API) die je daar ziet doen GEEN conversie Ascii->Unicode gebruik dus
StrFromPtrA (String from a Pointer To An Ascii String). Die copyStrA doet de Unicode Conversie voor jouw als het goed gaat (ascii is deel van unicode)

  • MrDry
  • Registratie: December 2001
  • Laatst online: 21-08 16:48

MrDry

Desperados!

Topicstarter
Eindelijk....het is gelukt...

Het had inderdaad te maken met de verschillen in variabele typen tussen C++ en VB en het in gebruik zijn van de verschillende processen.
Hieronder heb ik de code gepost die het doet (voor de liefhebbers....)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Public Function getfilename() As String
    On Error Resume Next
    
    Dim h_winamp As Long
    Dim index As Integer
    Dim Trackpos As Long
    Dim mpointer As Long
    Dim Temp, temphandle, hwndwinampp As Long
    Dim ntemp, ptemp
    Dim Data As String * 256
    
    h_winamp = FindWindow("Winamp v1.x", vbNullString)
    index = SendMessage(h_winamp, WM_USER, 0, IPC_GETLISTPOS)
    mpointer = SendMessage(h_winamp, WM_USER, index, 211) '212 is Title
            
    'do interprocess magic:
    Temp = GetWindowThreadProcessId(h_winamp, temphandle)
    hwndwinampp = OpenProcess(PROCESS_VM_READ, False, temphandle)
    Data = Space(256)
    'pull the data:
    ntemp = ReadProcessMemory(hwndwinampp, mpointer, Data, 256, Temp)
    'bail out:
    ptemp = CloseHandle(hwndwinampp)
    getfilename = Left(Data, InStr(1, Data, Chr(0)) - 1)
    
End Function


Bedankt allemaal voor jullie hulp _/-\o_

[ Voor 5% gewijzigd door MrDry op 27-05-2003 23:18 . Reden: typo ]

Quod licet lovi, non licet bovi

Pagina: 1