|
|
Comments and Discussions
|
|
 |

|
I did conversion, but I am still getting some errors, I am to new to VB and to this to know how to resolve them. A VS2012 version would be awesome!
- Intellilogic
|
|
|
|

|
Can we have c# version of your code also ?
Regards
Prashant
|
|
|
|

|
You know, it would be far easier to just use a GlobalAllocation to CopyMemory your string to and send the handle for that to the other application, ...
|
|
|
|

|
Great article.
Is it possible to send a string from a Windows service to Win Form application ?
thanks
|
|
|
|

|
for parrameter "as Any" you can use "as Object"
<MarshalAs(UnmanagedType.AsAny)> param As Object
|
|
|
|

|
I want to paste data from windows based application to any currently running application whether its Notepad or visual studio - code will paste the text automatically. how can i do this??
Regards,
Harry
|
|
|
|

|
ok, first step you need a tool called Spy4win, you can search internet and donwload it. This tool lets you find out the handle of control which you wanna send data to. After you get the handle, you can easily use SENDMESSAGE API function with wparameter 'WM_SETTEXT' to send data.
warm,
Tom
|
|
|
|

|
Send to same instance work fine but when sent to another instance, they cannot get the message. (may be dotnet have protected each applications memory space) any ways to put the string into some global memory space? here's my code: on the form i have 3 textbox 1. change name of this instance 2. set target window name 3. messages to be sent and received and some related buttons ------------ vb code -------------- Public Class Form1 Private Sub btnSetMyName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSetMyName.Click If Me.txtMyName.Text.Trim.Length < 1 Then Exit Sub End If Me.Text = Me.txtMyName.Text End Sub Private Sub btnCreateWin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateWin.Click Dim codebase As String = System.Reflection.Assembly.GetExecutingAssembly.Location Process.Start(codebase, "") End Sub Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click If Me.txtTargetName.Text = "" Then MessageBox.Show("Target Name Empty") End If XWMessaging.Messager.SendStringMessage(Me.txtTargetName.Text, Me.txtMsg.Text) End Sub Private Sub Form1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.TextChanged Me.txtMyName.Text = Me.Text End Sub Private Sub txtMsg_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtMsg.Enter txtMsg.SelectAll() End Sub Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) Select Case m.Msg Case &H400 Dim a As String = XWMessaging.Messager.GetStringMessage(m.LParam, Runtime.InteropServices.CharSet.Auto) Me.txtMsg.AppendText(a & vbNewLine) Case &H401 'Dim a As SENDSTRUCT = CopyStructure(m.LParam) 'TextBox1.AppendText(a.var1 & vbNewLine) 'TextBox1.AppendText(a.str1 & vbNewLine) Case Else MyBase.WndProc(m) End Select End Sub End Class Imports System.Runtime.InteropServices Imports System.Text Public Class Messager <DllImport("user32.dll", CharSet:=CharSet.Unicode, entrypoint:="SendMessageW")> _ Private Shared Function SendMessage(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer End Function <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr End Function Public Shared Function SendStringMessage(ByVal winname As String, ByVal msg As String) As Integer Dim hwnd As Integer = FindWindow(vbNullString, winname) Dim i As IntPtr = Marshal.StringToHGlobalUni(msg) Return SendMessage(hwnd, &H400, 0, i) End Function Public Shared Function GetStringMessage(ByVal i As IntPtr, ByVal chrset As CharSet) As String Select Case chrset Case CharSet.Ansi Return Marshal.PtrToStringAnsi(i) Case CharSet.Unicode Return Marshal.PtrToStringUni(i) Case Else Return Marshal.PtrToStringAuto(i) End Select End Function End Class Jason Lam
|
|
|
|

|
Dear Jason,
The problem is in the window handle, maybe you send message to a wrong window.
Since you have 2 window with same caption, you can not use findwindow function to find the window handle, becoz findwindow will only find the first window with specified caption, which will be itself.
you need to modify your code:
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Messager
_
Public Shared Function SendMessage(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
_
Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
Public Shared Function SendStringMessage(ByVal winname As String, ByVal msg As String) As Integer
Dim hwnd As Integer = FindWindow(vbNullString, winname)
Dim i As IntPtr = Marshal.StringToHGlobalUni(msg)
Return SendMessage(hwnd, &H400, 0, i)
End Function
Public Shared Function GetStringMessage(ByVal i As IntPtr, ByVal chrset As CharSet) As String
Select Case chrset
Case CharSet.Ansi
Return Marshal.PtrToStringAnsi(i)
Case CharSet.Unicode
Return Marshal.PtrToStringUni(i)
Case Else
Return Marshal.PtrToStringAuto(i)
End Select
End Function
End Class
Public Class Form1
Private Sub btnSetMyName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSetMyName.Click
If Me.txtMyName.Text.Trim.Length < 1 Then
Exit Sub
End If
Me.Text = Me.txtMyName.Text
End Sub
Private Sub btnCreateWin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateWin.Click
If XWMessaging.Messager.FindWindow(vbNullString, "Receive") = 0 Then
Dim a As Form1
a = New Form1
a.Text = "Receive"
a.Show()
End If
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
If XWMessaging.Messager.FindWindow(vbNullString, "Receive") = 0 Then
btnCreateWin_Click(Me, e)
End If
XWMessaging.Messager.SendStringMessage("Receive", Me.txtMsg.Text)
End Sub
Private Sub Form1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.TextChanged
Me.txtMyName.Text = Me.Text
End Sub
Private Sub txtMsg_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtMsg.Enter
txtMsg.SelectAll()
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case &H400
Dim a As String = XWMessaging.Messager.GetStringMessage(m.LParam, Runtime.InteropServices.CharSet.Auto)
Me.txtMsg.AppendText(a & vbNewLine)
Case &H401
'Dim a As SENDSTRUCT = CopyStructure(m.LParam)
'TextBox1.AppendText(a.var1 & vbNewLine)
'TextBox1.AppendText(a.str1 & vbNewLine)
Case Else
MyBase.WndProc(m)
End Select
End Sub
End Class
and try again. good luck!
|
|
|
|

|
Thanks for your quick reply. but it would be more flexible if it can let 2 completely different programs to communicate with each other. therefore i tried to create a new process instead of a new form and i have successfully send integer the each other, so it seems got the right window by replacing Dim i As IntPtr = Marshal.StringToHGlobalUni(msg) with Dim i As IntPtr = new IntPtr(100) even when sending text they sometimes got the garbage text and sometimes my personal firewall say access to protected memory, so i guess there's difficulties for dotnet to send string to another program Jason Lam
|
|
|
|

|
the reason why you can not send data is you got a wrong window handle. If you can get the correct window handle, and send message to the correct handle, the program will surely catch the data you just send.
be noticed that I used findwindow function in the demo project to get the window handle, the "lpWindowName" parameter is very important, it's the parameter to let you to specify the aim window's caption. if u do want to use the same form to catch the message, you need to change the destination window's caption at run-time, then use findwindow to get the handle, and send message to this window.
or you can try to create 2 projects, 1 is send, another is receive, they are totally independent programs, and the data can be exchanged.
-----------------------------
Marshal.StringToHGlobalUni(msg) will copy the contents to memory and return the memory address, so you may not change it otherwise you will get a wrong address and if you use this wrong address to read data, of coz it will be rubbish.
|
|
|
|

|
i have maded the following changes
Public Shared Function SendStringMessage(ByVal winname As String, ByVal msg As String) As Integer
Dim hwnd As Integer = FindWindow(vbNullString, winname)
Dim i As IntPtr = Marshal.StringToHGlobalUni(msg)
System.Windows.Forms.MessageBox.Show("Message Address:" & i.ToString & vbCrLf & GetStringMessage(i, CharSet.Auto)) ' Debug Message Added
Return SendMessage(hwnd, &H400, 0, i)
End Function
'and also
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case &H400
Dim a As String = XWMessaging.Messager.GetStringMessage(m.LParam, Runtime.InteropServices.CharSet.Auto)
Me.txtMsg.Text = ("from:" & m.LParam.ToString & vbNewLine & "Length:" & a.Length & vbNewLine & a & vbNewLine) ' Debug Message Added
Case &H401
'Dim a As SENDSTRUCT = CopyStructure(m.LParam)
'TextBox1.AppendText(a.var1 & vbNewLine)
'TextBox1.AppendText(a.str1 & vbNewLine)
Case Else
MyBase.WndProc(m)
End Select
End Sub
and confirmed that
1. the target window is correct as the textbox content changed by [WndProc]
2. the pointer is correct as the value of m.LParam are the same
but the same pointer address address means different things in different instance
i send the same message ,"default message", 3 times result as follow
(every time the debug message box on the own instance can get the correct message , and the pointers sent and received are always the same.)
1.garbage text
from:1702632
Length:9
Ǥ輸秪䅍䥎
2.empty
from:1541304
Length
3.garbage text
from:1753600
Length:2
녜
Jason Lam
|
|
|
|
|

|
understandable,
i hate those so call "security" features
Jason Lam
ps.
yet a nice demo on cross window messaging,
sending flags can be enough for many applications
|
|
|
|

|
hi Jason, I've changed concept and rewritten the whole program. Now can work as interprocesscommunication as well.
yours,
Tom
|
|
|
|

|
I have since found this article. Thanks
http://www.codeproject.com/useritems/ipc_wmcopy.asp
|
|
|
|

|
Hi, I have converted this to c# and have found that I can only send upto 7 characters, any more and the recieve window does not capture the sent string! Does any one have any ideas ?
|
|
|
|

|
Dear rippo,
I'm not familiar with C# so may answer uncorrectly. But I guess the problem is the buffer size.
Anyway I have found a much better way to copy sting and structure, you can take a look at my updated article, it may work properly in C#.
|
|
|
|

|
very nice and simplistic approach..
keep it up..
Ruchit S.
http://ruchitsurati.net
*********************************************
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
A way to send strings to another application by using Windows messages instead of Remoting.
| Type | Article |
| Licence | CPOL |
| First Posted | 24 Jul 2007 |
| Views | 84,734 |
| Downloads | 1,877 |
| Bookmarked | 61 times |
|
|