2012-09-25 2 views
2

J'envoie des données à une application Delphi en utilisant WM_COPYDATA de l'application vb6. Dans mon système où local est l'anglais, je reçois les données correctement, mais sur un autre système avec le néerlandais local, le texte reçu est brouillé.Sendmessage avec WM_COPYDATA de vb6 à delphi est brouillé

l'application de réception est le delphi, le code est

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData); 
var 
    copyDataType: TCopyDataType; 
begin 
    copyDataType := TCopyDataType(Msg.CopyDataStruct.dwData); 

    //Handle of the Sender 
    mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From])); 

    case copyDataType of 
    cdtString: HandleCopyDataString(Msg.CopyDataStruct); 
    end; 

    //Send something back 
    msg.Result := mmoResult.Lines.Count; 
end; 

procedure TReceiverMainForm.HandleCopyDataString(
    copyDataStruct: PCopyDataStruct); 
var 
    s: string; 
begin 
    s := PChar(copyDataStruct.lpData); 
    mmoResult.Lines.Add(s); 
end; 

EDIT

ici est le code VB6 qui envoie les données, les données am envoyaient est une chaîne

Dim buf() As Byte 
ReDim buf(1 To LenB(Message)) 
Call CopyMemory(buf(1), ByVal Message, Len(Message)) 
cds.dwData = 0 
cds.cbData = Len(Message) + 1 
cds.lpData = VarPtr(buf(1)) 
' Send the string. 
Dim i As Long 
i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds) 

Quelqu'un peut-il me dire ce qui ne va pas?

+1

Comment envoyez-vous les données? Selon la version de Delphi que vous utilisez, la chaîne peut être interprétée comme unicode ou ANSI. Si vous pouvez confirmer votre méthode d'envoi de code VB, et la version Delphi, je peux faire une réponse appropriée. – Deanna

+0

@Deanna, il a une étiquette Delphi 7, donc vous êtes à mi-chemin ;-) – TLama

+0

J'ai vu ce qui implique qu'il fait la conversion ANSI. J'ai encore besoin de connaître le code VB6 avant de pouvoir donner une réponse définitive. [D7 semble prendre en charge les caractères larges, mais pas l'interface utilisateur] (http://stackoverflow.com/a/2281327/588306). – Deanna

Répondre

3

Les chaînes VB sont basées sur le type de chaîne COM BSTR, tout comme le type de chaîne WideString de Delphi. Un BSTR est une chaîne Unicode codée UTF-16. LenB() renvoie le nombre d'octets qu'une chaîne VB occupe lorsqu'elle est convertie en paramètres régionaux actuels de la machine locale. Vous ne prenez pas cela en compte. Vous ne copiez pas correctement les octets de chaîne dans votre mémoire tampon et vous ne définissez pas non plus le champ cds.cbData sur la valeur correcte. Len() renvoie le nombre de caractères codés UTF-16 dans la chaîne, tandis que LenB() renvoie le nombre d'octets à la place. Pour une chaîne en anglais, Len() et LenB() renverront la même valeur, mais pour un autre langage non garanti.

Je vous suggère d'envoyer les données codées VB Unicode telles quelles, et de modifier votre code Delphi pour traiter les données entrantes comme Unicode au lieu d'Ansi comme il le fait actuellement (PChar est Ansi dans Delphi 7, mais est Unicode dans Delphi 2009+).

Vous devez également affecter une valeur unique au champ cds.dwData. WM_COPYDATA est utilisé par la VCL pour certaines de ses propres données internes, vous devez donc faire la différence entre vos messages WM_COPYDATA et les messages de la VCL.

Essayez ceci:

cds.dwData = RegisterWindowMessage("MyWMCopyData") 
If cds.dwData <> 0 Then 
    cds.cbData = Len(Message) * 2 ' characters are 2-bytes each 
    cds.lpData = StrPtr(Message) ' access the string's character buffer directly 
    ' Send the string. 
    Dim i As Long 
    i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds) 
End If 

.

var 
    uMyWMCopyDataMsg: UINT = 0; 

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData); 
var 
    s: WideString; // you can use UnicodeString in D2009+ 
begin 
    if (uMyWMCopyDataMsg = 0) or (Msg.CopyDataStruct.dwData <> uMyWMCopyDataMsg) then 
    begin 
    inherited; 
    Exit; 
    end; 

    mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From])); 

    SetString(s, PWideChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData div SizeOf(WideChar)); 
    mmoResult.Lines.Add(s); 

    msg.Result := mmoResult.Lines.Count; 
end; 

initialization 
    uMyWMCopyDataMsg := RegisterWindowMessage('MyWMCopyData'); 
+0

Je ne comprends pas alors comment ça marche avec une chaîne anglaise, un caractère dans un BSTR est toujours de 2 octets, n'est-ce pas? –

+0

Oui, un caractère 'BSTR' est de 2 octets. Cependant, dans VB, le passage d'une chaîne 'ByVal' le convertit en Ansi pour la compatibilité avec les API' char'. Ainsi, le code convertit la chaîne source en Ansi lors de l'appel de 'CopyMemory()', mais utilise Len() 'à la place de' LenB() 'comme troisième paramètre. Cela ne fonctionnera correctement que pour les langues à un octet, comme les langues anglaises et latines1. –

+0

merci. Mais cela ne devrait pas faire partie du problème puisque, hormis les langues de l'Extrême-Orient, tous les chars Ansi sont à un seul octet par caractère. Pour autant que je sache, les Néerlandais utilisent latin-1 (win-1252). –

Questions connexes