title image


Smiley Re: vb6 - 3 fragen (zt. system betreffend)
ich muss gestehen, ich bin zu blöd dafür

Das glaube ich ohne Beweis deinerseit nicht



ich habe noch nie mit api gearbeitet konnte ich nicht Wissen, ist aber auch kein Beinbruch.

Du hast es zumindest mal selbst versucht (wenn ich die Zeiten von deinen zwei letzten Postings ansehe) und das ist ja mal der erste Schritt zum Profi.



Ich könnte dir jetzt problemlos einen Code posten, der genau das macht, was du willst.

Das bringt mir aber nur Arbeit (sollte dann ja fehlerfrei funktionieren) und dich nicht wirklich weiter (du bist ja meiner Einschätzung nach kein "Codekopierer")



Meiner Meinung nach brauchst du nur entsprechendes Backgroundwissen, rumprobieren kannst und willst du ja selbst.

Selbst ich als "Profi" verwende bei mir unbekannten API's die Try-and-Error-Methode, (natürlich nicht blind, in der MSDN die Doku der Fkt lesen, die zutreffendne Header-Dateinen ansehen (Kommentare, Konstanten ect) bei Google mal den Namen der Fkt eingeben etc...)







Ein bischen Theorie gibts von mir hier API Aufrufe, warum das so "schwierig" ist



Da ist zwar das in deinem Fall ausschlaggebende (String-Rückgabe) nicht dabei, schadet aber als Background sicher nicht, da das dort abgegebene allgemeingültig ist (entscheidend ist, was bei der API ankommt und wie die das interpretiert!).



Als Ausnahme der "Allgemeingültigkeit" von diesem Beitrag muß ich hier die Stringübergabe angeben. In VB hat eine Variable von Typ String als Inhalt die Speicheradresse des Strings, also einen Zeiger.

Bei Parameterübergaben an Function's Sub's innerhalb VB ist das nicht weiter tragisch, VB kennt ja beide Seiten und macht entsprechend das Richtige.

Bei Übergaben an API's gelten die Regeln, die im obigen Link angegeben sind. VB macht das, was man sagt! Weil der Inhalt einer Stringvariablen die Speicheradresse des Strings ist, wird bei der Deklaration ByVal As String der Inhalt der Stringvariablen (also die Speicheradresse) übergeben.

Eine API-Fkt, die als Parameter einen String will, erwartet genau das, die will die Speicheradresse des Strings.

Deshalb ist das bei der ByVal-ByRef-Übergabe an API'S bei Strings anders als bei "normalen" Datentypen. Nur wenn ein API-Parameter einen Pointer to a Pointer to a String will (was sehr selten vorkomt) muß man ByRef As String übergeben,

ansonsten: Bei String immer ByVal).







Wenn eine API-Funktion ein String-Variable zur Rückgabe will, muß vorher genügend Platz dafür geschaffen sein.



In der Doku (MSDN) zu GetLocaleInfo steht:



lpLCData

   Points to a buffer to receive the requested data.

chData

   Specifies the size, in bytes (ANSI version) or characters (Unicode version), of the lpLCData buffer.



Das bedeutet im VB-Jargon:

Im Parameter lpLCData muß eine Speicheradresse eines Strings übergeben werden.

Im Parameter chData muß die Größe des Strings übergeben werden.



Da ein String in VB was anderes ist wie ein String bei API-Funktionen, muß man dafür sorgen, daß bei der API-Fkt das richtige ankommt.

Wenn man den Declare der API mit ByVal As String schreibt, übergibt VB den richtigen Zeiger (Pointer) auf den String.

Allerdings muß man vorher dafür sorgen, daß im String genügend Platz ist.



Bei VB steht an der Speicheradresse, bevor der String beginnt, die Länge des Strings. Daher weiß VB immer, wie lang ein String gerade ist.

Bei API-Strings fehlt diese Information, API-Strings beginnen an der angegebenen Speicheradresse und gehen bis zum ersten 0-Zeichen (vb=Chr(0)).

(bei VB-Strings können jederzeit 0-Zeichen innerhalb des Strings vorkommen, entscheidend ist die Größenanbage)



API-Funktionen, die Strings zurückgeben, gehen davon aus, daß der ihnen übergebene String genügend groß ist, daß also vom Beginn der angegebenen Speicheradressse

bis zum ersten 0-Zeichen soviel Platz ist, wie sie brauchen. Ist das nicht der Fall, dann hören sie beim ersten 0-Zeichen auf oder tun gar nichts.



Bei der Deklaration mit ByVal ... As String übergibt VB zwar die richtige Adresse, aber die Länge des Strings wird nicht geändert.



Wenn man in VB eine Stringvariable definiert:



Dim s As String



dann hat dieser String die Länge 0.



Einen solchen String an eine API zu übergeben, ist nicht weiter schlimm, VB übergibt die richtige Adresse, nur die API schreibt nichts rein,

weil zwischen Startadresse und dem ersten 0-Zeichen einfach kein Platz ist. VB hängt bei einer API-Übergabe an den String ein Chr(0) (=0-Zeichen) an.

Da der String vorher leer war, folgt sofort auf die Anfangsadresse das 0-Zeichen, also tut die API nichts, weil kein Platz da ist.



Wenn man jetz zB mit



s = Space(256)



den String mit genügend Leerzeichen vorbelegt, dann hängt VB das 0-Zeichen erst nach diesen Leerzeichen an. In diesem Fall hat die API also 256 Zeichen Platz.

Dieser Wert (256) reicht in den meißten Fällen aus, oft steht auch in der MSDN, wie groß der String sein muß, dann eben entsprechend groß machen.



Es kommt auch ab und zu vor, daß die API die benötigte Größe zurückgibt, wenn der Platz nicht reicht. (Bei der Beschreibung der jeweiligen Fkt in der MSDN steht das idR dabei)



Im Fall von der APi GetLocaleInfo ist es so, daß diese API im Parameter chData die Größe des Strings wissen will, also Len(s).

In der Doku steht folgendes:

If cchData is zero, the function returns the number of bytes or characters required to hold the information, and the buffer pointed to by lpLCData is not used.



Das heißt im Klartext: Wenn man beim Parameter cchData den Wert 0 übergibt, gibt die Fkt die benötigte Stringgröße zurück.

Dadurch kann man mit einem zweimaigen Aufruf die gewünschte Info abholen, beim ersten Mal übergibt man bei der Länge 0, dann weiß man, wie groß man den String machen muß,

beim zweiten Mal dann eben den genügend großen String und dessen Länge übergeben.



Beispiel:



Private Const LOCALE_SENGLANGUAGE = &H1001

Private Declare Function GetSystemDefaultLangID Lib "kernel32" () As Integer

Private Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long



'//...

Dim s As String

Dim l As LOng



'// API mit cchData=0 aufrufen --> Rückgabewert ist die benötigte Größe

l = GetLocaleInfo(GetSystemDefaultLangID, LOCALE_SENGLANGUAGE, s, 0)



'// String in benötigter Größe vorbelegen

s = Space(l)

'// API mit richtig initialisierten Werten ausführen

l = GetLocaleInfo(GetSystemDefaultLangID, LOCALE_SENGLANGUAGE, s, Len(s))





Das dann eben für alle gewünschten Infos (LCTYPE-Konstanten) durchführen

evtl einen Left$(s,InStr(s, Chr(0))) durchführen,


Gruß
Gaga

___________________________________________________________________

Profilösungen für VB6
wenn nicht anders angegeben, sind alle Codebeispiele nicht getestet, nur getippt


geschrieben von

Login

E-Mail:
  

Passwort:
  

Beitrag anfügen

Symbol:
 
 
 
 
 
 
 
 
 
 
 
 
 

Überschrift: