- PR -

別アプリの制御について

投稿者投稿内容
だんご虫
会議室デビュー日: 2006/07/30
投稿数: 18
投稿日時: 2006-12-06 20:27
いつもお世話になっております。
だんご虫です。

SendMessageを使用して別アプリの制御を行いたいと思い、
以下のコードでテスト的にアプリを作成しました。

送り側アプリコード

Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function PostMessage _
(ByVal hWnd As IntPtr, ByVal Msg As Integer, _
ByVal wParam As IntPtr, ByRef lParam As COPYDATASTRUCT) As IntPtr
End Function

Private Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cbData As Integer
Public lpData As IntPtr
End Structure

Private Sub SendMess()
Dim hWnd As IntPtr
Dim cds As COPYDATASTRUCT
Dim s As String

hWnd = FindWindow(Nothing, "別アプリB")
If Not hWnd.Equals(IntPtr.Zero) Then
s = "ほげほげ"
cds = New COPYDATASTRUCT
cds.dwData = IntPtr.Zero
cds.lpData = Marshal.StringToHGlobalUni(s)
cds.cbData = (s.Length + 1) * 2
PostMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cds)
Marshal.FreeHGlobal(cds.lpData)
End If
End Sub


受け側あぷりコード

Private Const WM_COPYDATA As Integer = &H4A
Private Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cbData As Integer
Public lpData As IntPtr
End Structure
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_COPYDATA Then
Dim cds As COPYDATASTRUCT

cds = CType(Marshal.PtrToStructure(m.LParam, GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
MessageBox.Show(Marshal.PtrToStringUni(cds.lpData))
Else
MyBase.WndProc(m)
End If
End Sub

以上のSendMessageでの同期的な制御はできたのですが、
非同期での実装方法がいまいちわかりません。
初心者の為ちんぷんかんぷんな事を言ってるいるかもしれませんが、
ご教授お願い致します
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-12-06 22:25
引用:

非同期での実装方法がいまいちわかりません。



できないです。
WM_COPYDATA メッセージは PostMessage() することが出来ません。
だんご虫
会議室デビュー日: 2006/07/30
投稿数: 18
投稿日時: 2006-12-06 22:59
渋木宏明(ひどり)さん御回答ありがとうございます。

なるほど、できないのですね・・・。
アプリAからアプリBの非同期で制御を行う場合は、
どのような方法が一般的なのでしょうか?
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2006-12-06 23:43
こんばんは。

引用:

だんご虫さんの書き込み (2006-12-06 22:59) より:
アプリAからアプリBの非同期で制御を行う場合は、
どのような方法が一般的なのでしょうか?



「制御」というと、一方が他方に対して一方的に指示をする関係をイメージしてしまいますが、
そういうことを意図されているのでしょうか?
それともアプリ同士で「協調動作」をさせたいのでしょうか?

「非同期で制御したい」が具体的にイメージできないのですが、
画面を持つアプリ間なら、ウィンドウメッセージもあるでしょうし、
各種さまざまなプロセス間通信の方法も用意されています。
その中でやりたいことに一番適した方法を選択します。
だんご虫
会議室デビュー日: 2006/07/30
投稿数: 18
投稿日時: 2006-12-07 00:17
Tdnr_Sym様 御回答ありがとうございます。

やりたい事は、
アプリAで行ったデータ更新を
アプリBに通知し、アプリBで表示中のグリッドのデータにアプリAで
行った更新が反映される(データ再読込み)というものです。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-12-07 01:21
引用:

やりたい事は、



最初にそれを書きましょう。
手法の話から入るから、望む答えがなかなか得られないのです。

で、「データ更新があったこと」を伝えるだけなら、ユーザ定義のメッセージを PostMessage() すればいいんじゃないでしょうか。


[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-12-07 01:21 ]
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2006-12-07 03:00
引用:

アプリAで行ったデータ更新を
アプリBに通知し、アプリBで表示中のグリッドのデータにアプリAで
行った更新が反映される(データ再読込み)というものです。



DDEメッセージとして実装するのが正統的な気がしますが、面倒くさいです。
通信用に見えない(表示されない)コントロールを持たせておいて、そこ宛に
WM_SETTEXTをPostMessageで送る、とかいうのが簡単ではないかと。

引用:

で、「データ更新があったこと」を伝えるだけなら、ユーザ定義のメッセージを PostMessage() すればいいんじゃないでしょうか。


更新したファイル名等、付随するデータを送りたい場合に、それじゃダメなんですよね。

だんご虫
会議室デビュー日: 2006/07/30
投稿数: 18
投稿日時: 2006-12-07 14:46
渋木宏明(ひどり)様
coasm様
ご回答ありがとうございます。

ユーザー定義のPostMessageを行う為、
テスト的に以下のことをやったのですが、
受け側アプリのほうの
If m.Msg = WmUserTest Then
で、m.Msgが0となってしまいうまくいきませんでした。
ご教授お願い致します。


メッセージ送信側アプリ

<DllImport("user32", SetLastError:=True)> _
Private Shared Function RegisterWindowMessage(ByVal lpMessage As String) As Integer
End Function

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long _
) As Long

Private Sub PostMess()
Dim hWnd As Long
Dim msgstr As String

WmUserTest = RegisterWindowMessage("WM_USER_TEST")
hWnd = FindWindow(Nothing, "TESTB")
PostMessage(hWnd, WmUserTest, 0, 0)
End Sub

受け側アプリ
Public WmUserTest As Integer
<DllImport("user32", SetLastError:=True)> _
Private Shared Function RegisterWindowMessage(ByVal lpMessage As String) As Integer
End Function

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Static rcvmsg As String
WmUserTest = RegisterWindowMessage("WM_USER_TEST")

’ここでm.Msg=0となってしまう
If m.Msg = WmUserTest Then
MessageBox.Show("aaaaa")
Exit Sub
Else
MyBase.WndProc(m)
End If
End Sub

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