벤자민의 블로그 2기 시작
2023년 6월 13일 갑작스러운 부친상을 격고나서 무언가를 한다라는 것에서 거의 손을 대지 않고 있었네요. 슬프다거나 그런 감정보다는 그냥 무언가 빠져버린
WM_COPYDATA AND TCOPYDATASTRUCT
위링크의 내용을 간략하게 번역해두었습니다.
WM_COPYDATA 메시지를 사용하면 한 응용 프로그램에서 다른 응용 프로그램으로 데이터를 보낼 수 있습니다. 수신 응용 프로그램은 TCopyDataStruct 레코드로 데이터를 수신합니다. TCopyDataStruct는 Windows.pas 유닛에 정의되어 있으며 전달할 데이터가 들어있는 COPYDATASTRUCT 구조체를 래핑합니다.
다음은 TCopyDataStruct 레코드의 선언과 설명입니다.
type
TCopyDataStruct = packed record
dwData: DWORD; //up to 32 bits of data to be passed to the receiving application
cbData: DWORD; //the size, in bytes, of the data pointed to by the lpData member
lpData: Pointer; //Points to data to be passed to the receiving application. This member can be nil.
end;
WM_COPYDATA 이용하여 문자열 전송하기
Sender프로세스에서 Receiver에게 데이터를 보내려면 CopyDataStruct 에 변수를 저장하여 SendMessage 함수를 사용하여 전달해야합니다. WM_CopyData에 문자열 값을 보내는 방법은 다음과 같습니다.
procedure TSenderMainForm.SendString() ;
var
stringToSend : string;
copyDataStruct : TCopyDataStruct;
begin
stringToSend := 'About Delphi Programming';
copyDataStruct.dwData := 0; //use it to identify the message contents
copyDataStruct.cbData := 1 + Length(stringToSend) ;
copyDataStruct.lpData := PChar(stringToSend) ;
SendData(copyDataStruct) ;
end;
SendData 사용자 지정 함수는 FindWindow API 호출을 사용하여 Receiver 프로세스를 찾습니다.
procedure TSenderMainForm.SendData(const copyDataStruct: TCopyDataStruct) ;
var
receiverHandle : THandle;
res : integer;
begin
receiverHandle := FindWindow(PChar('TReceiverMainForm'),PChar('ReceiverMainForm')) ;
if receiverHandle = 0 then
begin
ShowMessage('CopyData Receiver NOT found!') ;
Exit;
end;
res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct)) ;
end;
위의 코드에서 기본 폼 ( "TReceiverMainForm")의 클래스 이름과 Windows 캡션 ( "ReceiverMainForm")을 전달하여 FindWindow API 호출을 사용하여 Receiver 어플리케이션을 찾았습니다.
참고 : SendMessage는 WM_CopyData 메시지를 처리하는 코드에서 할당 한 정수 값을 반환합니다.
HANDLING WM_COPYDATA - RECEIVING A STRING
Receiver 어플리케이션은 다음과 같이 WM_CopyData 메시지를 처리합니다.
type
TReceiverMainForm = class(TForm)
private
procedure WMCopyData(var Msg : TWMCopyData) ; message WM_COPYDATA;
...
implementation
...
procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData) ;
var
s : string;
begin
s := PChar(Msg.CopyDataStruct.lpData) ;
//Send something back
msg.Result := 2006;
end;
TWMCopyData 레코드는 다음과 같이 선언됩니다.
TWMCopyData = packed record
Msg: Cardinal;
From: HWND;//Handle of the Window that passed the data
CopyDataStruct: PCopyDataStruct; //data passed
Result: Longint;//Use it to send a value back to the "Sender"
end;
문자열 전송, 일반화된 레코드 or 이미지?
아래 소스 코드는 문자열, 레코드(복합 데이터 형식) 및 그래픽 (비트맵)을 다른 어플리케이션으로 보내는 방법을 보여줍니다.
다운로드를 기다릴 수없는 경우 TBitmap 그래픽을 보내는 방법은 다음과 같습니다.
procedure TSenderMainForm.SendImage() ;
var
ms : TMemoryStream;
bmp : TBitmap;
copyDataStruct : TCopyDataStruct;
begin
ms := TMemoryStream.Create;
try
bmp := self.GetFormImage;
try
bmp.SaveToStream(ms) ;
finally
bmp.Free;
end;
copyDataStruct.dwData := Integer(cdtImage) ; // identify the data
copyDataStruct.cbData := ms.Size;
copyDataStruct.lpData := ms.Memory;
SendData(copyDataStruct) ;
finally
ms.Free;
end;
end;
받는 방법 :
procedure TReceiverMainForm.HandleCopyDataImage(
copyDataStruct: PCopyDataStruct) ;
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
ms.Write(copyDataStruct.lpData^, copyDataStruct.cbData) ;
ms.Position := 0;
receivedImage.Picture.Bitmap.LoadFromStream(ms) ;
finally
ms.Free;
end;
end;
Message in the Bottle
Monitoring Registry Changes
API hooking revealed
How to monitor directory / file changes on network share
Change Notifier Component Example
How can I increase a performance of standard TTreeView/TListView?