2012-09-25 44 views
2

vb6 앱에서 WM_COPYDATA를 사용하여 데이터를 델파이 응용 프로그램으로 보냅니다. 내 로컬 시스템은 영어로, 나는 데이터를 올바르게 수신하지만, 네덜란드 시스템을 사용하는 다른 시스템에서는 수신 텍스트가 왜곡됩니다.vb6에서 delphi로 WM_COPYDATA가있는 SendMessage가 깨졌습니다.

수신 앱이 델파이이다, 코드가

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; 

데이터를 보내는 VB6 코드 여기

편집입니다, 데이터를 전송하고 문자열

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) 
입니다

아무도 내가 뭘 잘못하고 있다고 말할 수 있습니까?

+1

어떻게 데이터를 보내시겠습니까? 사용중인 Delphi 버전에 따라 문자열은 유니 코드 또는 ANSI로 해석 될 수 있습니다. VB 코드 전송 방법 및 Delphi 버전을 확인할 수 있다면 적절한 대답을 할 수 있습니다. – Deanna

+0

@Deanna, Delphi 7 태그가있어서 반쯤 더 가깝습니다 ;-) – TLama

+0

ANSI 변환을 수행한다는 의미입니다. 난 아직 확실한 대답을 줄 수 있기 전에 VB6 코드를 알아야합니다. [D7은 다양한 문자를 지원하지만 UI는 그렇지 않습니다.] (http://stackoverflow.com/a/2281327/588306). – Deanna

답변

3

VB 문자열은 COM BSTR 문자열 유형을 기반으로하며, 문자열 유형은 Delphi의 WideString 문자열 유형과 동일합니다. BSTR은 UTF-16으로 인코딩 된 유니 코드 문자열입니다. LenB()은 로컬 시스템의 현재 로켈로 변환 할 때 VB 문자열이 차지하는 바이트 수를 반환합니다. 당신은 그것을 고려하지 않습니다. 문자열 바이트를 버퍼에 올바르게 복사하지 않고 cds.cbData 필드를 올바른 값으로 설정하지 않습니다. Len()은 문자열에서 UTF-16으로 인코딩 된 문자의 수를 반환하지만 LenB()은 대신 바이트 수를 반환합니다. 영어 문자열 인 경우 Len()LenB()은 동일한 값을 반환하지만 foriegn 언어는 보장되지 않습니다.

원본 VB Unicode 인코딩 된 데이터를있는 그대로 보내고 현재 수행중인 것처럼 Ansi 대신 들어오는 데이터를 Ansi로 처리하도록 Delphi 코드를 변경하는 것이 좋습니다 (PChar은 Delphi 7의 Ansi이지만 in Unicode in Delphi 2009 이상).

또한 cds.dwData 필드에 고유 한 값을 지정해야합니다. WM_COPYDATA은 내부 데이터의 일부에 VCL에서 사용되므로 WM_COPYDATA 메시지와 VCL의 메시지를 구별해야합니다.

대신을 시도해보십시오

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

난 어떻게 이해가 안가 영어 문자열, BSTR에있는 문자는 항상 2 바이트, 안 그래? –

+0

예, 'BSTR' 문자는 2 바이트입니다. 그러나 VB에서는'ByVal' 문자열을 전달하면'char' 기반 API와의 호환성을 위해 Ansi로 변환됩니다. 따라서 코드는'CopyMemory()'를 호출 할 때 소스 문자열을 Ansi로 변환하지만 세 번째 매개 변수로'LenB()'대신'Len()'을 사용합니다. 이는 영어 및 라틴어 기반 언어와 같은 1 바이트 언어에 대해서만 올바르게 작동합니다. 덕분에 –

+0

. 그러나 먼 동부 언어를 제외하고는 모든 ANSI 문자 세트가 문자 당 1 바이트가되기 때문에 이것은 여전히 ​​문제의 일부가되어서는 안됩니다. 내가 말할 수있는 한, 네덜란드어는 latin-1 (win-1252)을 사용합니다. –