1

) VB アプリから Delphi アプリに短いテキストを送信しようとしています。ここに VB コードがあります: Sender Program "Sender"

Public Class SendData

 Const WM_COPYDATA = &H4A
 Public Structure CopyDataStruct
    Public dwData As Integer
    Public cbData As Integer
    Public lpData As String
 End Structure

Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
 (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ 
 (ByVal hWnd As Long,  ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As _
 CopyDataStruct) As Long

Private Sub SendData(ByVal cds)
    Dim iHwnd As Long
    Dim SS As String = "Test String less than 30 Char"
    Dim cds As CopyDataStruct
    cds.dwData = 0
    cds.cbData = Len(SS)
    cds.lpData = SS
    iHwnd = FindWindow(0&, "Receive")
    SendMessage(iHwnd, &H4A, Me.Handle, cds) 
End Sub

Delphiコードは次のとおりです。レシーバープログラム「Receive」

 procedure TForm1.HandleCopyDataString(copyDataStruct: PCopyDataStruct);
 var
  s : string;
 begin
  s := PChar(CopyDataStruct.lpData);
  cdMemo.Lines.Add(Format('Received data "%s" at %s',[s, TimeToStr(Now)]));
 end;

 procedure TForm1.WMCopyData(var Msg: TWMCopyData) ;
 var
  s : string;
  sText: array[0..255] of Char;
  copyDataType : TCopyDataType;
 begin
  copyDataType := TCopyDataType(Msg.CopyDataStruct.dwData);
  s := PChar(Msg.CopyDataStruct.dwData);
  Form1.cdMemo.Lines.Add(Format('Data from: %d',[msg.From]));
  HandleCopyDataString(Msg.CopyDataStruct);
  case Msg.CopyDataStruct.dwData of 0: //we are being sent a string
  begin
    StrLCopy(sText, Msg.CopyDataStruct.lpData, Msg.CopyDataStruct.cbData);
    Form1.Label1.Caption := sText;
  end;
end;
end;

ここで何が間違っていますか?WM_COPYDATA コマンドと SendMessage 関数を使用して、VB から Delphi プログラムに文字列を送信できますか?

私を助けてください :-)

4

1 に答える 1

5

Delphi コードにはいくつか問題があります。

  1. dwDataフィールドにはintegerが保持されますが、それをポインタである に型キャストしてからPChar、文字列に割り当てます。これは、文字列データを保存したフィールドではありません。それはlpData

  2. 渡す文字列は null で終了しません。OS は、フィールドで指定したバイト数だけを正確にコピーすることを約束しますcbData。これは必ずしも問題ではありませんが、後で文字列を読むときに注意する必要があります。s他のプロセスからコピーされた文字列を保持するように割り当てるには、次のSetStringように使用します。

    SetString(s, PAnsiChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
    
  3. 何が何であるかを示していませんTCopyDataTypeが、整数または整数部分範囲型以外の場合は、間違って使用しています。dwDataフィールドはすでに であるため、DWord数値が必要な場所であればどこでも使用できます。

  4. あなたはStrLCopy間違って呼んでいます。3 番目のパラメーターは、ソースではなく、宛先バッファーのサイズである必要があります。これは、コピー先に収まる以上の文字をコピーしないことで、バッファ オーバーフローを防ぐためのものです。この関数は、終端のヌル文字を見つけることによってソース バッファーのサイズを検出できることを期待しています (ただし、それが利用できないことは既に確立されています)。次のように修正できます。

    StrLCopy(sText, Msg.CopyDataStruct.lpData,
      Min(Length(sText), Msg.CopyDataStruct.cbData));
    

    (Min数学ユニットにあります。)

于 2011-04-05T14:53:11.317 に答える