ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ã«ããããã»ã¹ééä¿¡(WM_COPYDATA)
WM_COPYDATAã¡ãã»ã¼ã¸ãå©ç¨ããããã»ã¹ééä¿¡å¦çãä½æããã
WM_COPYDATAã¯ããã»ã¹ééä¿¡ãç®çã¨ããã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ã§ä»»æã®ãµã¤ãºã®ãã¼ã¿ãã°ãã¼ãã«ãã¼ãã¡ã¢ãªãéãã¦å¥ããã»ã¹ã«ä¼ãããã¨ãã§ããã使ç¨ã«å½ãã£ã¦ã¯ã以ä¸ã®èª²é¡ãæ´çããä¸ã§å®è£ ããå¿ è¦ãããã
ã»WM_COPYDATAã¨ããååã ãã³ãã¼å¦çèªä½ã¯èªåã§è¡ãå¿
è¦ãããã
ã»ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ã§è»¢éãããã®ã¯ãã¼ã¿ã®ãã¤ã³ã¿ã§ãã¼ã¿èªä½ã¯è»¢éãããªãããã¼ã¿ã¯ã°ãã¼ãã«ãã¼ãã¡ã¢ãªã«ä¿åããã
ã»ã¡ãã»ã¼ã¸ãéä¿¡ããåã«Marshal.GlobalHAllocã使ç¨ãã¦ã°ãã¼ãã«ãã¼ãã¡ã¢ãªã確ä¿ããã転éãçµãã£ããMarshal.FreeHGlobalã§è§£æ¾ããã
ã»ã¡ã¢ãªã®ç¢ºä¿ã¨è§£æ¾ã®ã¿ã¤ãã³ã°ãã³ã³ããã¼ã«ããããã«PostMessageã§éåæå¦çãããã¨ã¯åºæ¥ãªããWM_COPYDATAã¯SendMessageã§ã®ä½¿ç¨ãã«ã¼ã«ã
ã»SendMessageã使ã£ãåæå¦çãªã®ã§ãã¼ã¿åä¿¡å´ã®ã¦ã¤ã³ãã¦ãã¦ã¤ã³ãã¦ããã·ã¼ã¸ã£ã§æéã®ãããå¦çãããã¨éä¿¡å´ããããã¯ãããã
ã»åãåãå´ã¯ããã»ã¹å
ã®ã¡ã¢ãªã«ã°ãã¼ãã«ãã¼ãã¡ã¢ãªãéããã«ã³ãã¼ãã¦å¦çãè¿ãã®ãããã¼ãã³ãã¼å¾ã¯ãã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ã®ãªããã£ã³ã°å¦çãè¡ã£ã¦å¦çãé
延ãããã
ã»PostMessageããã¾ãã«SendMessageãè¤æ°åå®è¡ãããå¯è½æ§ãããã両æ¹ãå¦çããå¿
è¦ããããªãåä¿¡å´ã¯ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ããã¥ã¼ã§ç®¡çããå¿
è¦ãããã
ã»ä»»æã®ãµã¤ãºã®ãã¼ã¿ã転éã§ããã
ã»éä¿¡å
ã®ã¦ã¤ã³ãã¦ãã³ãã«ãç¥ãããã«FindWindowExã使ç¨ãã¦ã¦ã¤ã³ãã¦ããã¹ãããæ¤ç´¢ãããã¦ã¤ã³ãã¦ããã¹ãã¯éä¿¡ãããããã»ã¹éã§ä¸è¬çã«ä½¿ç¨ãããªãæååãåã決ãã¦ãããï¼GUIDãªã©ãããããï¼
ã»WindowsVistaã§ã¯ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ããã£ã«ã¿ãªã³ã°ãããã®ã§ãChangeWindowMessageFilterã使ç¨ãã¦ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ãåä¿¡ã§ããããè¨å®ããå¿
è¦ãããã
ã»ã¦ã¤ã³ãã¦ã¡ãã»ã¼ã¸ã®å¦çã®ããã«ãSystem.Windows.Forms.NativeWindowãç¶æ¿ããã
ã»ã¯ãªãããã¼ãã®å¦çãªã©ã¨ã¯é¢ä¿ãªã
ã»Windows Vista ã Windows 2008 ã§ã¯é©åã«åã渡ããã¼ã¿ãMarshal.GlobalHAllocãªã©ã§ç¢ºä¿ãã¦ãããªãã¨ã¡ãã»ã¼ã¸èªä½ããã£ã«ã¿ãªã³ã°ãããå ´åããããChangeWindowMessageFilterã®åé¡ã¨èª¤è§£ããããã®ã§æ³¨æã
ä¸è¨ãèæ ®ããå®è£ ä¾
Public Class Form1Private _ipc As IPCUtils = Nothing
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As New IPCUtils.TransferMessage
a.MessageType = IPCUtils.MessageType.TextMessage
a.Message = "Hello"
a.ItemData = Now_ipc.SendMessage(a)
End Sub
Public Sub OnReceiveMessage(ByVal item As IPCUtils.TransferMessage)
MsgBox(item.Message)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
IPCUtils.ChangeMessageFileter()
_ipc = New IPCUtils("{662BA774-2658-4439-9CFE-AFE58CDBCC40}")
AddHandler _ipc.ReceiveMessage, AddressOf Me.OnReceiveMessage
End Sub
End Class
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Runtime.Serialization.Formatters.BinaryPublic Class IPCUtils
Inherits System.Windows.Forms.NativeWindowPublic Enum MessageType
TextMessage
End Enum
_
Public Class TransferMessage
Public MessageType As MessageType = IPCUtils.MessageType.TextMessage
Public Message As String = String.Empty
Public ItemData As Object = Nothing
End ClassPublic Event ReceiveMessage(ByVal item As TransferMessage)
Public CommunicationName As String = CS_DEFAULT_IPC_NAME
Private Const CS_DEFAULT_IPC_NAME As String = "{4F5E5E74-7405-4809-BF67-581842E65D14}"
_
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
_
Private Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal Msg As UInteger, _
ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As IntPtr
End Function
_
Private Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean
End FunctionPrivate Const WM_USER As UInteger = &H400
Private Const WM_IPC_MESSAGE As UInteger = WM_USER + 1
Private Const WM_COPYDATA As UInteger = &H4APrivate Const WS_BORDER As Int32 = &H800000
Private Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cbData As Int32
Public lpData As IntPtr
End StructurePrivate _messageQueue As Queue(Of TransferMessage)
Private _isCreatedWindow As Boolean = FalsePrivate Delegate Function ChangeWindowMessageFilter(ByVal message As UInteger, ByVal dwflag As Int32) As Boolean
Private Const MSGFLT_ADD As Integer = 1
Private Const MSGFLT_REMOVE As Integer = 2Public Sub New(ByVal communicationName As String)
MyBase.New()
_messageQueue = New Queue(Of TransferMessage)
Me.CommunicationName = communicationNameMe.CreateMessageOnlyWindow()
End Sub
Public Shared Sub ChangeMessageFileter()
Dim loader As New DynamicLibraryLoader
Dim result As Boolean = loader.Load("user32.dll")
If result = True Then
Try
Dim procPtr As [Delegate] = loader.GetDelegate("ChangeWindowMessageFilter", GetType(ChangeWindowMessageFilter))
If Not procPtr Is Nothing ThenDim funcPtr As ChangeWindowMessageFilter = CType(procPtr, ChangeWindowMessageFilter)
Dim funcResult As Boolean = FalsefuncResult = funcPtr(WM_COPYDATA, MSGFLT_ADD)
funcResult = funcPtr(WM_IPC_MESSAGE, MSGFLT_ADD)End If
Finally
loader.Free()
End Try
End IfEnd Sub
Protected Overrides Sub Finalize()
Me.DestroyMessageOnlyWindow()
MyBase.Finalize()
End SubPrivate Sub CreateMessageOnlyWindow()
Dim cp As New CreateParams
cp.Caption = Me.CommunicationName
cp.X = 0
cp.Y = 0
cp.Height = 0
cp.Width = 0cp.Style = WS_BORDER
Me.CreateHandle(cp)
_isCreatedWindow = True
End Sub
Private Sub DestroyMessageOnlyWindow()
If _isCreatedWindow = True Then
Me.DestroyHandle()
_isCreatedWindow = False
End IfEnd Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_COPYDATADim data As Object = Marshal.PtrToStructure(m.LParam, GetType(COPYDATASTRUCT))
Dim copyData As COPYDATASTRUCT = CType(data, COPYDATASTRUCT)Dim bytes(copyData.cbData) As Byte
Marshal.Copy(copyData.lpData, bytes, 0, copyData.cbData)Dim mem As New System.IO.MemoryStream()
Try
mem.Position = 0
mem.Write(bytes, 0, copyData.cbData)Dim b As New BinaryFormatter
mem.Position = 0
Dim item As TransferMessage = Nothing
item = CType(b.Deserialize(mem), TransferMessage)
_messageQueue.Enqueue(item)PostMessage(Me.Handle, WM_IPC_MESSAGE, IntPtr.Zero, IntPtr.Zero)
Finally
mem.Close()
End Try
Case WM_IPC_MESSAGE
If _messageQueue.Count > 0 Then
Dim item As TransferMessage = Nothing
item = _messageQueue.DequeueRaiseEvent ReceiveMessage(item)
Else
RaiseEvent ReceiveMessage(Nothing)
End If
End Select
MyBase.WndProc(m)
End Sub
Public Sub SendMessage(ByVal item As TransferMessage)
Dim mem As New System.IO.MemoryStream()
Dim bytes() As ByteTry
Dim b As New BinaryFormatter
b.Serialize(mem, item)bytes = mem.ToArray
Finally
mem.Close()
End Try
Dim ptr As IntPtr = Marshal.AllocHGlobal(bytes.Length)
Try
Marshal.Copy(bytes, 0, ptr, bytes.Length)
Dim copyData As COPYDATASTRUCT
copyData.dwData = IntPtr.Zero
copyData.cbData = CType(bytes.Length, Int32)
copyData.lpData = ptrDim copyDataPtr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(copyData))
Marshal.StructureToPtr(copyData, copyDataPtr, False)Try
Dim destHandle As IntPtr = IntPtr.Zero
destHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, vbNullString, Me.CommunicationName)Do While destHandle <> IntPtr.Zero
Dim messageResult As IntPtr = IntPtr.Zero
If destHandle <> Me.Handle Then
messageResult = SendMessage(destHandle, WM_COPYDATA, Me.Handle, copyDataPtr)
End If
destHandle = FindWindowEx(IntPtr.Zero, destHandle, vbNullString, Me.CommunicationName)
Loop
Finally
Marshal.FreeHGlobal(copyDataPtr)
End TryFinally
Marshal.FreeHGlobal(ptr)
End Try
End Sub
End Class