2010-06-17 1 views
2

두 개의 별도 프로세스에서 데이터를 보내는 데 사용하지만 실패합니다. 그것은 같은 과정에서만 작동합니다 ... 이것은 개념입니다.별도의 프로세스에서 SendMessage (..)를 사용하여 데이터 레코드를 보내는 방법

// -------------------------------------------- ---------------------------------------
MainApps
// ---- -------------------------------------------------- -----------------------------

Type 
    PMyrec = ^TMyrec; 
    TMyrec = Record 
    name : string; 
    add : string; 
    age : integer; 
end; 

:OnButtonSend 
var aData : PMyrec; 
begin 
    new(aData); 
    aData.Name := 'MyName'; 
    aData.Add := 'My Address'; 
    aData.Age : 18; 
    SendMessage(FindWindow('SubApps'),WM_MyMessage,0,Integer(@aData)); 
end; 

// ----------- -------------------------------------------------- ----------------------
하위 응용 프로그램
// --------------------- -------------------------------------------------- ------------

Type 
    PMyrec = ^TMyrec; 
    TMyrec = Record 
    name : string; 
    add : string; 
    age : integer; 
end; 

는 : OnCaptureMessage

var 
    aData : PMyrec; 
begin 
    aData := PMyrec(Msg.LParam); 
    showmessage(aData^.Name); 
end; 

답변

14

당신 말이 맞아. 주소는 단일 프로세스 내에서만 의미가 있습니다. 첫 번째 프로세스에서 작성하는 PMyRec 값은 대상 프로세스의 가비지 주소입니다.

창 메시지를 통해 임의의 메모리 블록을 다른 프로세스로 보내려면 wm_CopyData 메시지를 사용해야합니다. 해당 메시지에 데이터 및 크기의 주소를 지정하고 OS는 대상 프로세스의 주소 공간에 해당 메시지를 복사합니다.

데이터에 내부적으로 다른 포인터로 표시되는 문자열이 포함되어 있으므로 레코드의 12 바이트 만 복사하는 것으로 충분하지 않습니다. 하나의 메모리 블록에 레코드와 문자열 데이터를 저장하기 위해 추가 메모리를 할당해야하므로 wm_CopyData이 복사 할 수 있으며 대상 프로세스가 읽을 수 있습니다.

스트림을 사용하여 데이터를 단일 메모리 블록으로 수집하는 방법 중 하나가 있습니다.

procedure SendRecord(Source, Target: HWnd; const Rec: TMyRec); 
var 
    Buffer: TMemoryStream; 
    Len: Integer; 
    CopyData: TCopyDataStruct; 
begin 
    Buffer := TMemoryStream.Create; 
    try 
    Len := Length(Rec.name); 
    Buffer.Write(Len, SizeOf(Len)); 
    if Len > 0 then 
     Buffer.Write(Rec.name[1], Len * SizeOf(Char)); 
    Len := Length(Rec.add); 
    Buffer.Write(Len, SizeOf(Len)); 
    if Len > 0 then 
     Buffer.Write(Rec.add[1], Len * SizeOf(Char)); 
    Buffer.Write(Rec.age, SizeOf(Rec.age)); 
    CopyData.dwData := 0; 
    CopyData.cbData := Buffer.Size; 
    CopyData.lpData := Buffer.Memory; 
    SendMessage(Target, wm_CopyData, Source, LParam(@CopyData)); 
    finally 
    Buffer.free; 
    end; 
end; 

수신자가 각 문자에 얼마나 많은 문자가 속하는지 알 수 있도록 문자열의 문자 외에도 문자열의 길이를 씁니다. 받는 사람의 코드는 다음과 같을 것이다 : 그것은 모든 것을 쉽게 이후이 표준이 아닌 TReadOnlyMemoryStream을 사용했습니다

procedure TBasicForm.WMCopyData(var Message: TWMCopyData); 
var 
    Rec: TMyRec; 
    Len: Integer; 
    Buffer: TStream; 
begin 
    Buffer := TReadOnlyMemoryStream.Create(
    Message.CopyDataStruct.lpData, Message.CopyDataStruct.cbData); 
    try 
    if Message.CopyDataStruct.dwData = 0 then begin 
     Buffer.Read(Len, SizeOf(Len)); 
     SetLength(Rec.name, Len); 
     if Len > 0 then 
     Buffer.Read(Rec.name[1], Len * SizeOf(Char)); 

     Buffer.Read(Len, SizeOf(Len)); 
     SetLength(Rec.add, Len); 
     if Len > 0 then 
     Buffer.Read(Rec.add[1], Len * SizeOf(Len)); 

     Buffer.Read(Rec.age, SizeOf(Rec.age)); 

     // TODO: Do stuff with Rec here. 

     Message.Result := 1; 
    end else 
     inherited; 
    finally 
    Buffer.Free; 
    end; 
end; 

. 간단한 구현 방법은 다음과 같습니다.

type 
    TReadOnlyMemoryStream = class(TCustomMemoryStream) 
    public 
    constructor Create(Mem: Pointer; Size: LongInt); 
    function Write(const Buffer; Count: LongInt): LongInt; override; 
    end; 

constructor TReadOnlyMemoryStream.Create; 
begin 
    inherited Create; 
    SetPointer(Mem, Size); 
end; 

function TReadOnlyMemoryStream.Write; 
begin 
    Result := 0; 
end; 
+0

고맙습니다. – XBasic3000

관련 문제