[서론]
이전에 W.O.W 접속유지 프로그램을 만든적은 있지만 그때는 WOW 캡션이 정해져 있었고, 키입력만으로(방향키를 사용했음) 접속유지가 됐기때문에 단순한 키입력 메시지 전달만 하면 끝이었다.
다만.. W.O.W 에서 SendMessage를 먹어버려서 PostMessage로 처리했었다.
(W.O.W 접속유지 프로그램 링크:http://blueasa.tistory.com/527)
이번에는 서로(현재는 C# -> C++ 만 되는거 보고 정리함.. 나중에 업뎃 할지도..) SendMessage를 보내서 뭔가 일을 꾸밀(?) 수 있게 해보고 싶은마음에 시작.. 물론 양쪽 프로그램은 내가 직접 만든다는 가정하에..
세상에 선구자는 많으니 역시나..자료를 찾기 시작.. 이전에 간단하나마 만든 것도 있고..
말재주는 없으니 본론으로 들어가서 그냥 소스 정리..
[사용된 WinAPI 함수 및 중요 키워드]
FindWindow, SendMessage, WM_COPYDATA
[Send : C#]
[Source]
public class MessageHelper
{
[DllImport("User32.dll")]
private static extern int RegisterWindowMessage(string lpString);
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false, EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false, EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
//For use with WM_COPYDATA and COPYDATASTRUCT*
[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
public static extern bool SetForegroundWindow(int hWnd);
public const int WM_USER = 0x400;
public const int WM_SENDER = WM_USER + 4444;
public const int WM_COPYDATA = 0x4A;
//Used for WM_COPYDATA for string messages
//[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
//[MarshalAs(UnmanagedType.LPStr)]
public IntPtr lpData;
}
public bool BringAppToFront(int hWnd)
{
return SetForegroundWindow(hWnd);
}
public int SendWindowsStringMessage(int hWnd, int wParam, string command)
{
int result = 0;
if (hWnd != 0)
{
byte[] sarr = System.Text.Encoding.Default.GetBytes(command);
int len = sarr.Length;
COPYDATASTRUCT cds = new COPYDATASTRUCT();
//cds.dwData = (IntPtr)100;
cds.dwData = 0;
cds.cbData = len + 1;
//cds.cbData = Marshal.SizeOf(cds);
cds.lpData = Marshal.StringToHGlobalAnsi(command);
//cds.lpData = Marshal.StringToCoTaskMemAnsi(command);
result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}
return result;
}
public int SendWindowsMessage(int hWnd, int Msg, int wParam, int lParam)
{
int result = 0;
if (hWnd != 0)
{
result = SendMessage(hWnd, Msg, wParam, lParam);
}
return result;
}
public int GetWindowID(string className, string windowName)
{
return FindWindow(className, windowName);
}
}
[Use]
int hWnd = messageHelper.GetWindowID(null, windowCaption);
messageHelper.SendWindowsStringMessage(hWnd, 0, String);
[Receive : C++]
[Source]
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch ( msg )
{
case WM_COPYDATA:
{
//Used for WM_COPYDATA for string messages
struct COPYDATASTRUCT
{
int dwData;
int cbData;
PVOID lpData;
};
COPYDATASTRUCT* cp = (COPYDATASTRUCT*)lParam;
if( NULL != cp )
{
String strCommand = "";
char szCommand[256] = {0,};
memcpy( szCommand, cp->lpData, cp->cbData );
if(NULL != szCommand)
{
/// ToDo
/// 여기서 받은 문자열로 할 일 하면 됨.
/// dwData는 여기선 의미가 없긴한데 enum이나 int 그대로 써서
/// switch문 등으로 분기시켜서 여러가지 다양한 처리를 하려고
/// 처음 소스 짠사람이 만든 것 같다.
/// 다른 일도 분류해서 처리하려면 사용하자.
}
}
}
break;
}
}
[주의]
WM_COPYDATA 는 PostMessage로 날릴 수 없다고 한다. SendMessage를 사용하자.
(상대쪽에서 받기 전에 이쪽에서 메모리 해제 되있으면 AV뜨기때문에..)
참고 링크 : http://lunapiece.net/?mid=Tips&listStyle=webzine&document_srl=3780&sort_index=readed_count&order_type=desc
P.s. 마음대로 되지 않고 삽질도 많이해서 여기저기 쓰이지 않는 주석이 남아있긴 하지만.. 삽질기념(?) 그냥 냅두기..
하도 검색하고 다녀서 참조한 곳을 다 찾기엔 좀 걸리거나 빼먹을 수 도 있을 것 같다. 출처를 찾으러 가야지..
[참조]
- http://boycook.wordpress.com/2008/07/29/c-win32-messaging-with-sendmessage-and-wm_copydata/
- http://kofmania.tistory.com/45
- http://xarfox.tistory.com/45
- http://jacking.tistory.com/134
- http://www.hoons.kr/board.aspx?Name=qacshap&Mode=2&BoardIdx=10465&Key=&Value=
- http://lunapiece.net/?mid=Tips&listStyle=webzine&document_srl=3780&sort_index=readed_count&order_type=desc
- 그 외 못 적은 곳은.. 죄송합니다..;;