- PR -

C# .Net SendMessageで他のアプリに文言を送信したい

1
投稿者投稿内容
もも
常連さん
会議室デビュー日: 2005/07/25
投稿数: 46
投稿日時: 2005-07-25 12:05
はじめまして。Netなどで調べたのですが、解決方法が見つからないため、
こちらのお力を借りたいと思います。

いま、A.exeからB.exeへメッセージを送信することを考えています。
C++でしたら、
送信元(A.exe)
HWND hWnd = 0;
char msg[256];
strcpy(msg,"hello");
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = strlen(msg) + 1;
cds.lpData = (LPVOID)msg;
hWnd = ::FindWindow(NULL,"B");
if(hWnd != 0){
::SendMessage(hWnd,WM_COPYDATA, 0, (LPARAM)&cds);
}
受信側(B.exe) WindowProc内
COPYDATASTRUCT *pdat = (COPYDATASTRUCT*)lParam;
m_edit = (char*)pdat->lpData;

で受信側で「hello」と受け取ることができます。
しかし、C#で記述に変換しようと試みたのですが・・・・
送信元(A.exe)
[DllImport("USER32.dll")]
private static extern IntPtr SendMessage (IntPtr hWnd , int msg , IntPtr wp, IntPtr lp);

struct COPYDATASTRUCT
{
public long dwData;
public long cbData;
public string lpData;
}

private void button1_Click(object sender, System.EventArgs e)
{
int hWnd = 0;
COPYDATASTRUCT st = new COPYDATASTRUCT();

string msg = "hello";

st.dwData = 0;
st.cbData = msg.Length+1;
st.lpData = msg;

hWnd = FindWindow(null,"B");
if(hWnd != 0)
{
IntPtr lparam;
lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(st));
SendMessage((System.IntPtr)hWnd, 0x004A, this.Handle, lparam);
}
}
受信側(B.exe)
struct COPYDATASTRUCT
{
public long dwData;
public long cbData;
public string lpData;
}
protected override void WndProc(ref Message m)
{
// Listen for operating system messages.
if(m.Msg == 0x004A)
{
COPYDATASTRUCT st = new COPYDATASTRUCT();
st = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

textBox1.Text = st.lpData;
}
base.WndProc(ref m);
}
とすると、「U駆d。」こんな文字化けしたものが送信されてしまいます。
何か足りない処理や、間違った処理などがあるのでしょうか。

お知恵を貸して頂けませんでしょうか。

Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-07-25 12:19
Marshal.AllocCoTaskMem/AllocHGlobalは、文字通りメモリを確保するメソッドです。
勝手に構造体の中身をコピーしたりする機能はありません。
構造体インスタンスを確保したメモリ領域にコピーするにはMarshal.StructureToPtrメソッドを使用します。
またAllocした領域をFreeCoTaskMem/FreeHGlobalするのを忘れないで下さい。リークします。

追記:
実は、SendMessageの宣言を
static extern uint SendMessage(IntPtr window, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
のようにしてやるとMarshalクラスの出番が無くなったりします。

[ メッセージ編集済み 編集者: Hongliang 編集日時 2005-07-25 12:40 ]
もも
常連さん
会議室デビュー日: 2005/07/25
投稿数: 46
投稿日時: 2005-07-25 12:54
Hongliangさんありがとうございます。
コピーする機能はないんですね・・・・。勉強になります。
早速、追記の宣言で動作を確認させてもらいました。

Marshalの出番をなくすことができました〜〜
しかし、受信側では、相変わらず、文字化けしてしまっています。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-07-25 13:29
手元ではできるのになー、と思って改めてももさんのコードをチェックしてみました。

で、はたと気付きました。
COPYDATASTRUCTUREの定義ですね。
MSDNのをそのままコピーしますが、
コード:
typedef struct tagCOPYDATASTRUCT { 
    ULONG_PTR dwData; 
    DWORD     cbData; 
    PVOID     lpData; 
} COPYDATASTRUCT, *PCOPYDATASTRUCT; 


まず、DWORDは32ビット値です。.NETならUInt32(Int32)に相当しますね。
またULONG_PTRはプラットフォーム依存のポインタ、つまり32bitOSなら32ビットですから、こちらはIntPtrで宣言すべきでしょう。
もも
常連さん
会議室デビュー日: 2005/07/25
投稿数: 46
投稿日時: 2005-07-25 14:13
Hongliangさんありがとうございます。
構造体の宣言を
struct COPYDATASTRUCT
{
public IntPtr dwData;
public UInt32 cbData;
public string lpData;
}
と変えたところ・・・・
文字を送信することができました〜〜〜〜〜〜〜!!
丁寧に教えて頂きありがとうございました。

1

スキルアップ/キャリアアップ(JOB@IT)