DOBON.NET DOBON.NETプログラミング掲示板過去ログ

VBAからC#にSendMessageしてもキャッチ出来ない

環境/言語:[VS 2012]
分類:[.NET]

☆やりたいこと
ExcelVBAからSendMessageで、プロセス間通信を行いたい

☆問題
・C#アプリ間(同一アプリ・別アプリ)は行えています
・ExcelVBA→C#の場合、WndProcのメッセージID振り分け直後にブレークをしてもキャッチ出来ない

☆環境
・Win7 x64
・Excel 2007
・VS 2012

☆仕様
・WM_COPYDATAメッセージを利用して、構造体の受け渡しを行う。(dwDataの値により型を指定)
・上記の検証として、文字列(Unicode)の受け渡しを行う。(dwData=0)

☆注意点
・FindWindow及び、SendMessageはAではなくW
・APIの型はStringやAnyではなくLongにし、StrPtrやVarPtrを使用
・C#のコンストラクタで出力しているウインドウハンドルと、ExcelのA2セルの値は10進で同一の為FindWindowは正常

☆C#

public WinProc(AppSetting app)
{
InitializeComponent();

this.Text = app.APIWindowName;
this.textBox1.Text = "";

#if DEBUG
textBox1.Text += string.Format("{0:yyyy/MM/dd HH:mm:ss} {1}{2}", DateTime.Now, this.Handle.ToString(), System.Environment.NewLine);
#endif
}

public delegate void receiveMsgHandler(object sender, receiveMsgEventArgs e);
public event receiveMsgHandler recMsg;

public void OnReceiveMsg(receiveMsgEventArgs e)
{
if (recMsg != null)
{
recMsg(this, e);
}
}

public struct COPYDATASTRUCT
{
public IntPtr dwData;
public UInt32 cbData;
public IntPtr lpData;
}
public const int WM_COPYDATA = 0x4A;
public const int WM_USER = 0x400;
public const int WM_SETTEXT = 0xC;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
{
// 受信データ
COPYDATASTRUCT data = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));

//String msg = Marshal.PtrToStringUni(data.lpData);
byte[] bytes = new byte[data.cbData];
Marshal.Copy(data.lpData, bytes, 0, (int)data.cbData);
string msg = Encoding.Unicode.GetString(bytes);

// イベント
OnReceiveMsg(new receiveMsgEventArgs(msg));

#if DEBUG
textBox1.Text += string.Format("{0:yyyy/MM/dd HH:mm:ss} {1}{2}", DateTime.Now, msg, System.Environment.NewLine);
#endif
m.Result = new IntPtr(1);
break;
}

}
base.WndProc(ref m);
}

☆Excel VBA(標準モジュール)
Option Explicit
Public Declare Function FindWindow Lib "User32.dll" Alias "FindWindowW" _
(ByVal lpClassName As Long, _
ByVal lpWindowName As Long) As Long

Public Declare Function SendMessage Lib "User32.dll" _
Alias "SendMessageW" _
(ByVal hWnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Public Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type

Public Const WM_COPYDATA As Integer = &H4A
Public Const WM_USER As Integer = &H400

☆Excel VBA(テストシート)
Option Explicit
Private Sub CommandButton1_Click()
SendMsg (Sheet1.Range("D5").Value)
End Sub

Private Sub SendMsg(Msg As String)
Dim ret As Long

Dim hWnd As Long: hWnd = 0
Dim sClass As String: sClass = vbNullString
Dim sWindow As String: sWindow = "ReceiverMsg"

Dim data As COPYDATASTRUCT
Dim MsgBytes() As Byte

hWnd = FindWindow(StrPtr(sClass), StrPtr(sWindow))
If (hWnd = 0) Then
MsgBox "起動してください"
Exit Sub
End If

' debug
Sheet1.Range("A2").Value = hWnd

MsgBytes = StrConv(Msg, vbUnicode)

data.dwData = 0
data.lpData = VarPtr(MsgBytes(1))
data.cbData = UBound(MsgBytes)

ret = SendMessage(hWnd, WM_COPYDATA, Me.Application.hWnd, VarPtr(data))

' debug
Sheet1.Range("A1").Value = ret

End Sub


不足が無いようにしたつもりですが、VB6ライクな言語(及びAPIの使用)は久しぶりのため
根本的な勘違いがあるかもしれませんが、よろしくお願いします。
この投稿はマルチポストです。

●マルチポストされている場所
http://bbs.wankuma.com/index.cgi?mode=al2&namber=65664

----------
この掲示板ではマルチポストが禁止されています。詳しくは、「書き込みのマナーについて」をお読みください。

●書き込みのマナーについて
http://dobon.net/vb/bbs/index.html
No31406 の投稿は悪質ないたずらの投稿です。無視するようにして下さい。

DOBON.NET | プログラミング道 | プログラミング掲示板