본문 바로가기
VisualStudio.C++.C#/코딩팁,함수활용,단편

WM_COPYDATA . OnCopyData . CWnd * pWnd . WPARAM

by i.got.it 2020. 8. 31.

 

개요

2개의 프로세스 사이에 SendMessage 함수로 메시지 송/수신과 동시에 구조체자료형 COPYDATASTRUCT 를 전송가능한 것.
 
즉 메시지 송신측에서 SendMessage 함수인자를 아래처럼 호출하면 HWND(윈도우핸들) 에 해당하는 다른 프로세스에서 COPYDATASTRUCT 로 정의된 데이터 myCDS 를 수신가능하다.

 

 

SendMessage (HWND, WM_COPYDATA, 0,(LPARAM)&myCDS);  // 메시지 전송.


myCDS 로 전송하기 위한 간단한 예.

typedef struct {

 int a;
 int b;

} MySTData; 

MySTData my_stdata; // 이 구조체를 COPYDATASTRUCT 의 lpData 로 송신하고자한다.

COPYDATASTRUCT myCDS;  // COPYDATASTRUCT 형의 구조체 변수 선언.
myCDS.dwData = 1; // 통상 여러 타입의 데이터를 lpData 로 전송할때 타입 식별자 용도로 사용함.
myCDS.lpData = &my_stdata;
myCDS.cbData = sizeof(my_stdata); // lpData 로 전송하는 데이터의 바이트 사이즈 지정한다.

 

 

주의사항 

 

구조체 멤버 제한사항.

WM_COPYDATA 로 전송할 구조체의 멤버에 CString 포함  포인터 를 멤버로 갖는 구조체를  WM_COPYDATA 로 전송하는 것은 무의미. 즉, 다른 프로세스는 이곳의 프로세스와는 다른 메모리 영역을 갖는데 , 이곳의 메모리 주소를 보내봤자 상대방 프로세스는 이곳의 메모리 주소는 접근 불가하므로 의도한 데이터 송신 불가. 구조체 멤버에 문자열을 보내려면 CString 아닌  TCHAR m_tchar[100] 식으로 정의해서 송신해야함.  

 

COPYDATASTRUCT

- dwData 에만 데이터 할당하고 송신하려는 경우에도 멤버 lpData, cbData 로 전송할 데이터가 없고  값설정하지 않은 상태에서는 정상적으로 SendMessage 실행되지 못하고 통신 실패한다. 아래처럼 명시적으로 lpData, cbData 에 값설정해야 정상적으로 SendMessage 실행된다. 

COPYDATASTRUCT myCDS; 

myCDS.dwData = 999999; 

myCDS.lpData = NULL; 

myCDS.cbData = 0; 

 

 

 

 

 

 

 

구조체 COPYDATASTRUCT

 
 
구조체 COPYDATASTRUCT 타입정의는 아래와 같다.
 
typedef struct tagCOPYDATASTRUCT {
  ULONG_PTR dwData;
  DWORD     cbData;
  PVOID     lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
 

Members

dwData
Type: ULONG_PTR
The data to be passed to the receiving application.
cbData
Type: DWORD
The size, in bytes, of the data pointed to by the lpData member.
lpData
Type: PVOID
The data to be passed to the receiving application. This member can be NULL.
 
from :
   

 

 

 

 

 

 

WM_COPYDATA 메시지 수신측 메시지 핸들러 추가 방법.

 
 
 WM_COPYDATA 메시지를 수신하려는 쪽의 클래스 에 클래스 위저드 이용하여 간단 추가 가능하다.
 
 예 : 클래스 위저드(ctrl+shift+x) 실행하여,  메시지 수신할 클래스 CCySingleStrategy1_UITDlg  의 Messages 부분에서 WM_COPYDATA 선택하여 버튼 Add Handler 클릭한다.
 

위 처리에 의하여 클래스에 자동 코드 생성된다. (아래그림)
 

 
   

OnCopyData 의 인자 CWnd * pWnd 상세 

 

 메시지 수신측의 이벤트 핸들러 OnCopyData 의 첫번째 인자인 CWnd* pWnd 는  메시지 송신한 측의  CWnd* 이다. 

 

그럼 pWnd->GwtSafeHwnd() (주의 : pWnd->m_hWnd 로 접근하지 말것 프로그램 뒤진다.) 함수 반환값은 메시지 송신한 것의 윈도우 핸들이 기록되어있을 것이라 여겨지지만, 전혀 아니다. 

 

pWnd->GetSafeHwnd()  로 확보되는 값은  메시지 송신한 곳에서  SendMessage 함수 호출시 3번째 인자 WPARAM 의 값이 기록되어있다.  

 

만일, 아래처럼 WPARAM 에 0을 기록했다면 수신한 측에서 pWnd->GetSafeHwnd() 값은 0이 기록되어있다.

 

SendMessage (HWND, WM_COPYDATA, 0,(LPARAM)&myCDS);  // 메시지 전송.

 

 

송신측에서 아래 코드 처럼 WPARAM 에 자신의 윈도우핸들을 기록하여 송신했다면

 

SendMessage (HWND, WM_COPYDATA, (WPARAM)this->GetSafeHwnd(),(LPARAM)&myCDS); 

 

수신한 측에서도 송신한 윈도우의 핸들값을 pWnd->GetSafeHwnd() 로 얻을 수 있지만 송신한 측에서 윈도우 핸들을 기록하지 않고 다른 데이터를 기록했다면 수신한 측에서의  pWnd->GetSafeHwnd() 에는 윈도우 핸들이 아닌 송신시 기록한 WPARAM 값이 기록되어있다. 

 

따라서, 결론적으로 숙지하고 있어야 할 사항. 

 

SendMessage( , WM_COPYDATA, WPARAM, LPARAM ) 호출시 WPARAM 값으로  송신측의 윈도우 핸들이 아닌 다른 임의 값을 기록 가능하며, 수신한측에서  pWnd->GetSafeHwnd()  로 해당값 확보가능함. 

 

 

 

 

 

 

 

 

 

코드예 

- 코드 출처 : f https://msdn.microsoft.com/en-us/library/ms649009(v=vs.85).aspx  

다음 예제에서는 WM_COPYDATA 메시지를 사용하여 두 애플리케이션 간에 정보를 보내는 방법을 보여 줍니다.

보내는 애플리케이션은 특정 정보를 요청하는 사용자에게 대화 상자를 표시합니다. 애플리케이션은 정보를 프라이빗 데이터 구조로 패키징하고 COPYDATASTRUCT 구조체의 구조에 대한 포인터를 포함하고 WM_COPYDATA 메시지를 사용하여 수신 애플리케이션에 정보를 보냅니다. 수신 애플리케이션에는 클래스 이름이 Disp32Class인 숨겨진 창이 있습니다

 


// ************ Globals ************
//
#define MYDISPLAY 1
typedef struct tagMYREC
{
   char  s1[80];
   char  s2[80];
   DWORD n;
} MYREC;
COPYDATASTRUCT MyCDS;
MYREC MyRec;
HRESULT hResult;
BOOL CALLBACK InfoDlgProc( HWND, UINT, WPARAM, LPARAM );
// ************ Code fragment ****************
// Get data from user. InfoDlgProc stores the information in MyRec.
//
   DialogBox( ghInstance, "InfoDlg", hWnd, (DLGPROC) InfoDlgProc );
//
// Copy data into structure to be passed via WM_COPYDATA.
// Also, we assume that truncation of the data is acceptable.
//
   hResult = StringCbCopy( MyRec.s1, sizeof(MyRec.s1), szFirstName );
   if (hResult != S_OK)
        return False;
   hResult = StringCbCopy( MyRec.s2, sizeof(MyRec.s2), szLastName );
   if (hResult != S_OK)
        return False;
   MyRec.n = nAge;
//
// Fill the COPYDATA structure
// 
   MyCDS.dwData = MYPRINT;          // function identifier
   MyCDS.cbData = sizeof( MyRec );  // size of data
   MyCDS.lpData = &MyRec;           // data structure
//
// Call function, passing data in &MyCDS
//
   hwDispatch = FindWindow( "Disp32Class", "Hidden Window" );
   if( hwDispatch != NULL )
      SendMessage( hwDispatch,
                   WM_COPYDATA,
                   (WPARAM)(HWND) hWnd,
                   (LPARAM) (LPVOID) &MyCDS );
   else
      MessageBox( hWnd, "Can't send WM_COPYDATA", "MyApp", MB_OK );

 

 

수신 애플리케이션에는 WM_COPYDATA 정보를 수신하고 사용자에게 표시하는 숨겨진 창이 있습니다.

 


// ************ Globals ************
//
#define MYDISPLAY 1
typedef struct tagMYREC
{
   char  s1[80];
   char  s2[80];
   DWORD n;
} MYREC;
PCOPYDATASTRUCT pMyCDS;
void WINAPI MyDisplay( LPSTR, LPSTR, DWORD );
//
// ************ Code fragment ****************
//
case WM_COPYDATA:
   pMyCDS = (PCOPYDATASTRUCT) lParam;
   switch( pMyCDS->dwData )
   {
      case MYDISPLAY:
         MyDisplay( (LPSTR) ((MYREC *)(pMyCDS->lpData))->s1,
                    (LPSTR) ((MYREC *)(pMyCDS->lpData))->s2,
                    (DWORD) ((MYREC *)(pMyCDS->lpData))->n );
   }
   break;

 

 

 

 

 

 

연관 

 

 

메타트레이더. WM_COPYDATA

///// 메타트레이더 에서 WM_COPYDATA SendMessage 예 #property strict #define WM_COPYDATA 0x004A #define INFO 0x01 #define FindWindow FindWindowW #define SendMessage SendMessageW struct Copydatastruct..

igotit.tistory.com

 

 

 

 

 

 

 


첫 등록 : 2017.03.28

최종 수정 : 2024.05.30

단축 주소 : https://igotit.tistory.com/1312


 

댓글



 

비트코인




암호화폐       외환/나스닥/골드         암호화폐/외환/나스닥/골드
     
현물 |선물 인버스 |선물 USDT       전략매니저(카피트레이딩)         프랍 트레이더 온라인 지원가능. MT4,MT5