
excelのVBAから文字列をsendmessageで
C#のプログラムに文字列を渡せないかと考えています。
ネットで調べつつなんとか作ってみたのですが、
どうしてもうまく動作しません。
変な文字列が表示されてしまいます。
どこがおかしいか教えて頂けないでしょうか。
windows7、Excel2010、.netFramework4になります。
※※※excel VBA側プログラム※※※※※※※※※※※※
//外部functionを使いますよ
Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
(ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, lpara As COPYDATASTRUCT) As Long
//構造体
Public Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As String
End Type
//メッセージを送信するsub
Public Sub sousin()
Dim result As Longv
Dim hWnd As Long
Dim cds As COPYDATASTRUCT
Dim str As String
Dim strby() As Byte
Dim length As Long
~ ウィンドウハンドルの取得 ~
str = "test"
strby = StrConv(str, vbFromUnicode)
length = UBound(strby) - LBound(strby) + 1
cds.dwData = 0
cds.lpData = str
cds.cbData = length
result = SendMessage(hWnd, WM_COPYDATA, 0, cds)
End Sub
※※※C#側プログラム※※※※※※※※※※※※※※※
//構造体
public struct COPYDATASTRUCT
{
public long dwData;
public long cbData;
public string lpData;
}
//WndProc関数
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT mystr = new COPYDATASTRUCT();
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
label1.Text = mystr.lpData; ←※無茶苦茶な文字列になります
break;
}
base.WndProc(ref m);
}
No.1ベストアンサー
- 回答日時:
Win32 APIをあまり使ったことないんで自信ない。
なお、俺の環境はVista(32 bit)である。
C言語の知識があると尚可
http://codezine.jp/article/detail/1718
を参考に、SendMessageAではなくSendMessageWを呼んでみた。
一応手元では成功している。(ハンドルを調べるためにC#のプログラムを先に起動している)
'===========VBA側プログラム=============
Option Explicit
' このVBのプログラムからは以下の引数のSendMessageという関数を呼び出した時、
' user32.dllにあるSendMessageWを呼び出すものとする、というものだと思っているので
' ぶっちゃけわかればAliasの後ろはなんだっていいんだと思う。
Declare Function SendMessage Lib "user32.dll" Alias "SendMessageW" _
(ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, lpara As COPYDATASTRUCT) As Long
'構造体の定義
'64bit環境ではどうなるんだろうね(Windows 7の人とかだと多そう)
Public Type COPYDATASTRUCT
dwData As Long ' 32 bit
cbData As Long ' 32 bit
lpData As Long ' 変更: 文字列へのポインタを格納することに
End Type
'元のコードから抜けてた。
Public Const WM_COPYDATA As Integer = &H4A
Public Sub Send()
Dim result As Long
Dim hWnd As Long
Dim cds As COPYDATASTRUCT
Dim str As String
'ハンドルを調べる方法を調べるのが面倒だったので
'先にC#のプログラム起動して調べた。
'起動毎に変わるので注意。> 俺
hWnd = 657792
str = "あいう"
cds.dwData = 0
cds.lpData = StrPtr(str)
'サロゲートペア文字とか考慮しなければUTF-16は1文字2バイト固定
'Wの場合null文字の分要らないっぽい?。
cds.cbData = 2 * Len(str)
result = SendMessage(hWnd, WM_COPYDATA, 0, cds)
End Sub
//============================C#側プログラム================
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class Hoge:System.Windows.Forms.Form{
public const int WM_COPYDATA = 0x4A;
// 自信ないけど、多分メモリの構造とか合わせないといけないと思うので
// この属性をつけておく
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
// VBのLongは32bitだけど、.NET FrameworkのLongは64bit
// だと思う。一応uintを使っておく。
public uint dwData;
public uint cbData;
// SendMessageWでUnicode文字列を送ってくるのでこの属性を一応つけてみる。
//あってるか自信なし。
[MarshalAs(UnmanagedType.LPWStr)]
public string lpData;
}
//WndProc関数
protected override void WndProc(ref Message m){
// Textプロパティを書き換えて何度もここが走ったりしないか不安だったので
// デバッグのため、一応ファイルに書き出すことに。
// 前のものを書き換えないよう、追記で。
// 自信があるなら別になくて良い処理
using(System.IO.StreamWriter sw = new System.IO.StreamWriter("D:\\logging.txt",true)){
sw.WriteLine ("test:" + m.Msg);
sw.WriteLine ("wanted:" + WM_COPYDATA);
switch (m.Msg){
case WM_COPYDATA:
COPYDATASTRUCT mystr = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
sw.WriteLine (mystr.lpData + mystr.lpData.Length);
break;
}
}
base.WndProc(ref m);
}
}
class Fuga{
public static void Main(){
Hoge f = new Hoge();
// 先に起動して調べておく
f.Text = f.Handle.ToString ();
f.ShowDialog ();
}
}
=======================================
とまぁこんな感じにしておいて、
WM_COPYDATAに該当する74(=0x4A)を探したら
test:74
あいう3
になっていた。

ありがとうございました!
おかげさまで上手いこと動きました!
C#側のlongをuintに変えて、
VBA側の文字列の長さをLen(str)に変えたらうまく動きました。
また、その他にもいろいろと私のしらないテクニックを見ることができて、
非常に興味深かったです!
本当にありがとうございました!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) Vbaで数式をポーランド記法に変換するコードを作って実行しようとするとフリーズします。 1 2022/05/24 17:53
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
- Visual Basic(VBA) VBA 別ブックからの転記の高速化について VBA 別ブックからの転記の高速化についてご教授下さい。 19 2022/07/26 13:07
- Visual Basic(VBA) VBAで質問ですが、皆さんはどの様に導き出しているのでしょうか? 6 2022/05/03 21:53
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAにてメール作成した際、一部...
-
XnViewにwebpを「いつも開く」...
-
あるプログラムのコマンドライ...
-
ポケコンについて
-
「Outlookが他のプログラムによ...
-
c#でGUIプログラム
-
ウイルスセキュリティ メッセー...
-
セルフイメージを高める21日...
-
じゃんけん 勝ち負けアイコ回...
-
ニュースサイトの更新の仕組み
-
.netプログラミングで全画面表...
-
プログラムから開く・・・DPP
-
デスクトップからワードが消えた
-
リンカとリンカスクリプトの違...
-
main関数を先頭に置くデメリット
-
仮想ベクタテーブルについて
-
何人目?
-
Googleのスパイダープログラム
-
PICマイコンのコピー(クローン...
-
javaで特定の文字のカウントを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
あるプログラムのコマンドライ...
-
VBAにてメール作成した際、一部...
-
Excelで4096点以上のFFTの方法
-
ドロップダウンリストの文字を...
-
PICマイコンのコピー(クローン...
-
Vba UserFormを前面に出す方法...
-
XnViewにwebpを「いつも開く」...
-
読み込み中にアクセス違反が発...
-
未使用の変数を一括検索する方法
-
VBAでユーザーフォームが自動的...
-
画像を読み込むのと取り込むの...
-
「Outlookが他のプログラムによ...
-
WORD印刷できるがEXCE...
-
Excelに埋め込んだVBAのプログ...
-
UWSCで指定のフォルダを開きたい。
-
テキストボックスのエンターキ...
-
自動クエリとはどういうもので...
-
javaで特定の文字のカウントを...
-
AutoCADを用いて板金展開図を自...
-
powered byの表記について
おすすめ情報