Hook and sub classing

CdRsKuLL

Active member
Joined
Sep 26, 2006
Messages
40
Programming Experience
Beginner
I'm trying to port a application over from vb to vb.net 2005, the application uses the sendmessage and windows hooks to talk to other apps.. I am working on receiving the messages at the moment. Now I have found a bit of code that hooks my app into windows and I do get a message box up when something has been received, but I dont know how to display the message thats been received as a string.

Below is the code I have started to adapt..

In the Form1 I have..
VB.NET:
'The Object of Subclassing to SubClass any Control
    Dim WithEvents abc As theAngrycodeR.SubClassing

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        abc = New theAngrycodeR.SubClassing(Me.Handle)
        abc.SubClass = True
End Sub

    Private Sub abc_CallBackProc(ByRef m As System.Windows.Forms.Message) Handles abc.CallBackProc
        Dim bytes() As Byte

        Select Case m.Msg
            Case WM_COPYDATA
                MsgBox(m.LParam)

        End Select
    End Sub

In a Subclass Form I have..

VB.NET:
Imports System.Windows.Forms

Namespace theAngrycodeR
    'To Subclass any Control, You need to Inherit From NativeWindow Class

    Public Class SubClassing
        Inherits System.Windows.Forms.NativeWindow

        'Event Declaration. This event will be raised when any Message will be posted to the Control
        Public Event CallBackProc(ByRef m As Message)

        'Flag which indicates that either Event should be raised or not
        Private m_Subclassed As Boolean = False

        'During Creation of Object of this class, Pass the Handle of Control which you want to SubClass
        Public Sub New(ByVal handle As IntPtr)
            MyBase.AssignHandle(handle)
        End Sub

        'Terminate The SubClassing
        'There is no need to Create this Method. Cuz, when you will create the Object
        'Of this class, You will have the Method Named ReleaseHandle.
        'Just call that as you can see in this Sub

        'Public Sub RemoveHandle()
        '    MyBase.ReleaseHandle()
        'End Sub

        'To Enable or Disable Receiving Messages
        Public Property SubClass() As Boolean
            Get
                Return m_Subclassed
            End Get
            Set(ByVal Value As Boolean)
                m_Subclassed = Value
            End Set
        End Property

        Protected Overrides Sub WndProc(ByRef m As Message)
            If m_Subclassed Then 'If Subclassing Enabled then RaiseEvent
                RaiseEvent CallBackProc(m)
            End If
            MyBase.WndProc(m)
        End Sub

        Protected Overrides Sub Finalize()
            MyBase.Finalize()
        End Sub
    End Class

End Namespace

Now I know the message should in the m.LParam but its not...

Also I am unsure about unloading this hook as in VB you needed to do it, but as there doesnt seem to be a Form_Unload here where would I cancel the hook on ending the program ?

hope someone can help..

Steve
 
You can use the closing event to remove the handle from the native window. As for the message as you know the lParam is usually an Intptr or an integer, so as for a string message all you will get is a number.

VB.NET:
m.lParam.Tostring


Thats it unless you are expecting a structure type in the lParam in which case you will need to marshall the lParam Intptr to the desired structure using the marshall class..

VB.NET:
MarshallPtrToStructure(......)
 
Hi, thanks I have had a look at the Marshal.PtrToStructure but I'm getting completely lost.. how is it, when I was coding in VB and I did a search in google.. everything that came up was for vb.net... now when I search everything comes up for VB.. hmm

ok the code in vb that I've been using is..

VB.NET:
Private Sub ReceiveMsg(lParam As Long)
Dim sString As String
Dim cds           As COPYDATASTRUCT
Dim buf() As Byte

' Copy the data sent to this application
' into a local structure.
Call CopyMemory(cds, ByVal lParam, Len(cds))

'Reply message to release processing
Call ReplyMessage(1)

Select Case cds.dwData
    Case 1 ' A string was passed.
        
        ' Copy the string that was passed into a byte array.
        ReDim buf(cds.cbData)
        Call CopyMemory(buf(0), ByVal cds.lpData, cds.cbData)
        
        ' Convert the ASCII byte array back to a Unicode string.
        sString = StrConv(buf, vbUnicode)
        sString = Left$(sString, Len(sString) - 1)

        ' Set our data
        SDKReceive sString

End Select

End Sub

I want to do something similar in vb.net,
VB.NET:
        Protected Overrides Sub WndProc(ByRef m As Message)
            Dim sString As String
            Dim buf() As Byte
            Select Case m.Msg
                
                Case Is = WM_COPYDATA
                   'get lParam into a string to process..
  '#### need this bit #### 

            End Select

            MyBase.WndProc(m)

        End Sub

sorry for my newbieness.. once I have a working code then I can normally understand whats going on.

thanks

Steve
 
You can drop the SubClassing class you posted above if you only receive message to application window, subclassing the application is done with the Overrides WndProc.

You don't need to Marshal the structure, the m.GetLParam method will give you the object which for WM_COPYDATA message is a COPYDATASTRUCT (CD). You still need Marshal to copy the bytes from CD.lpData pointer.

I have here some code I used before so there may be pieces that don't apply to you specifically - for example the data I received in the byte array was a string. Also the m.WParam is the window handle of the application that sent the data, you don't have to check this, but you can use it to verify/distinguish several different senders.
VB.NET:
[SIZE=2][COLOR=#0000ff]Protected [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Overrides [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] WndProc([/SIZE][SIZE=2][COLOR=#0000ff]ByRef[/COLOR][/SIZE][SIZE=2] m [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.Message)[/SIZE]
[SIZE=2][COLOR=#008000]'check for right type of message[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] m.Msg = WM_COPYDATA [/SIZE][SIZE=2][COLOR=#0000ff]Then[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'check if it's from our expected 'sender'[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] m.WParam.ToInt32 = wndh [/SIZE][SIZE=2][COLOR=#0000ff]Then[/COLOR][/SIZE]
 
[SIZE=2][COLOR=#008000]'get the standard message structure from lparam[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] CD [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] COPYDATASTRUCT = m.GetLParam([/SIZE][SIZE=2][COLOR=#0000ff]GetType[/COLOR][/SIZE][SIZE=2](COPYDATASTRUCT))[/SIZE]
[SIZE=2][COLOR=#008000]'setup byte array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] B(CD.cbData) [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'copy data from memory into array[/COLOR][/SIZE]
[SIZE=2]Runtime.InteropServices.Marshal.Copy([COLOR=#0000ff]New[/COLOR][SIZE=2] IntPtr(CD.lpData)[/SIZE], B, 0, CD.cbData)[/SIZE]
[SIZE=2][COLOR=#008000]'get as string and display in label[/COLOR][/SIZE]
[SIZE=2]Label1.Text = System.Text.Encoding.Default.GetString(B)[/SIZE]
[SIZE=2][COLOR=#008000]'empty array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Erase[/COLOR][/SIZE][SIZE=2] B[/SIZE]
[SIZE=2][COLOR=#008000]'set message result to 'true', meaning message handled[/COLOR][/SIZE]
[SIZE=2]m.Result = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IntPtr(1)[/SIZE]
 
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'pass on result and all messages not handled by this app[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].WndProc(m)[/SIZE]
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
If you want to turn listening on/off you can use a Boolean in the WndProc method. (same way done in that class)
 
thanks LOADS :) I got it in all but had to do a bit of looking around as type is no longer used in vb.net ... but this works a treat

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

again thanks very much, now I need to suss out how to send a string to a app..

Thanks

Steve
 
now I need to suss out how to send a string to a app..
Is that a question? :) Anyway here is the code used on the other end to send:
VB.NET:
[SIZE=2][COLOR=#0000ff]Private [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Button1_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) _[/SIZE]
[SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] Button1.Click[/SIZE]
[SIZE=2][COLOR=#008000]'get handle to app window to send message to[/COLOR][/SIZE]
[SIZE=2][COLOR=blue]Dim[/COLOR] wndh [COLOR=blue]As Integer[/COLOR] = FindWindow(vbNullString, "WM_receive")[/SIZE]
[SIZE=2][COLOR=#008000]'get string from textbox[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] str [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2] = TextBox1.Text[/SIZE]
[SIZE=2][COLOR=#008000]'string to byte array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] B() [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE][SIZE=2] = System.Text.Encoding.Default.GetBytes(str)[/SIZE]
[SIZE=2][COLOR=#008000]'allocate memory space for byte array, and get a pointer to it[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] lpB [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] IntPtr = Marshal.AllocHGlobal(B.Length)[/SIZE]
[SIZE=2][COLOR=#008000]'copy the byte array into memory[/COLOR][/SIZE]
[SIZE=2]Marshal.Copy(B, 0, lpB, B.Length)[/SIZE]
[SIZE=2][COLOR=#008000]'setup a standard structure for the WM_COPYDATA message[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] CD [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] COPYDATASTRUCT[/SIZE]
[SIZE=2][COLOR=#0000ff]With[/COLOR][/SIZE][SIZE=2] CD[/SIZE]
[SIZE=2].dwData = 0 [/SIZE][SIZE=2][COLOR=#008000]'can be used for custom indexing between apps[/COLOR][/SIZE]
[SIZE=2].cbData = B.Length [/SIZE][SIZE=2][COLOR=#008000]'length of data[/COLOR][/SIZE]
[SIZE=2].lpData = lpB.ToInt32 [/SIZE][SIZE=2][COLOR=#008000]'pointer to the data[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]With[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'clean up array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Erase[/COLOR][/SIZE][SIZE=2] B[/SIZE]
[SIZE=2][COLOR=#008000]'allocate memory space for structure, and get a pointer to it[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] lpCD [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] IntPtr = Marshal.AllocHGlobal(Len(CD))[/SIZE]
[SIZE=2][COLOR=#008000]'copy structure to allocated memory place[/COLOR][/SIZE]
[SIZE=2]Marshal.StructureToPtr(CD, lpCD, [/SIZE][SIZE=2][COLOR=#0000ff]False[/COLOR][/SIZE][SIZE=2])[/SIZE]
[SIZE=2][COLOR=#008000]'send message[/COLOR][/SIZE]
[SIZE=2]SendMessage(wndh, WM_COPYDATA, [/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].Handle.ToInt32, lpCD.ToInt32)[/SIZE]
[SIZE=2][COLOR=#008000]'free memory[/COLOR][/SIZE]
[SIZE=2]Marshal.FreeHGlobal(lpCD)[/SIZE]
[SIZE=2]Marshal.FreeHGlobal(lpB)[/SIZE]
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
Also, COPYDATASTRUCT.dwData is Integer (Int32). Plus the other declarations used:
VB.NET:
[SIZE=2][COLOR=#0000ff]Private [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Structure[/COLOR][/SIZE][SIZE=2] COPYDATASTRUCT[/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] dwData [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] cbData [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] lpData [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Structure[/COLOR][/SIZE]
 
[SIZE=2][COLOR=#0000ff]Const[/COLOR][/SIZE][SIZE=2] WM_COPYDATA [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32 = &H4A[/SIZE]
 
[SIZE=2][COLOR=#0000ff]Declare [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Function[/COLOR][/SIZE][SIZE=2] SendMessage [/SIZE][SIZE=2][COLOR=#0000ff]Lib[/COLOR][/SIZE][SIZE=2] "user32.dll" [/SIZE][SIZE=2][COLOR=#0000ff]Alias[/COLOR][/SIZE][SIZE=2] "SendMessageA" ( _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] hwnd [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32, _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] wMsg [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32, _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] wParam [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32, _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] lParam [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32) [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32[/SIZE]
 
[SIZE=2][COLOR=#0000ff]Declare [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Function[/COLOR][/SIZE][SIZE=2] FindWindow [/SIZE][SIZE=2][COLOR=#0000ff]Lib[/COLOR][/SIZE][SIZE=2] "user32.dll" [/SIZE][SIZE=2][COLOR=#0000ff]Alias[/COLOR][/SIZE][SIZE=2] "FindWindowA" ( _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] lpClassName [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2], _[/SIZE]
[SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] lpWindowName [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2]) [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32[/SIZE]
 
cant thankyou enough.. I had to change a few things to get it to work with the app that its sending messages too, but its all working great :) now onto the background apartment to allow a mta form and a sta form to talk :)

cheers m8

Steve
 
I am glad to finally have found something, I can actually use
Is this the standardprocedure to send a string to another application?

I'm asking, because I have never seen it on any other forum
Is it always, nessasary to convert the string into bytes?


It's possible I can actually learn something from this after 4 days of going threw all forums!

thanks a lot, Richard
 
Yes, the conversion is necessary from IntPtr to Integer. The structure was defined long before there was something called .Net and IntPtr. You have to convert the string to bytes in order to copy the bytes to an allocated memory space.

SendMessage with WM_COPYDATA is a very old way of InterProcess Communication, common with C++ and classic VB. Today you would perhaps rather use Sockets (that has become much easier available for the .Net developer) and Remoting (new thing). check into the Net/Sockets and Remoting forums for this.
 
yes, I could do that
In general discussions they always say that sendmessage is the easiest way. And sockets are used for remote networking.
And remoting has a lot of overhead.

Honestly, I think it's worth checking out later on
But I want to make sure I understand this mechanism first
I spent already 4 days on it

I need it for a windows service to talk to an application in the background that works like a popup window on the same computer.

I am not even shore anymore if that's a possibillity with WM_copydata because I heard somebody say the string is getting scrambled?

You can drop the SubClassing class you posted above if you only receive message to application window, subclassing the application is done with the Overrides WndProc.
Does it need to be altered a lot, if you want to talk back to the sender?
Also in the code on the receiving part
If m.WParam.ToInt32 = wndh Then

where does wndh come from?


Is the protected overides sub just getting pasted in the windowsform?
What am I missing here, on the receiver end, getting an empty label?

I have this code, I added the inherit forms.form, is that a good thing?
VB.NET:
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=2][COLOR=#000000] Form1[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Inherits[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.Form[/SIZE]
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Structure[/COLOR][/SIZE][SIZE=2] COPYDATASTRUCT[/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] dwData [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] cbData [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2] lpData [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Structure[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Const[/COLOR][/SIZE][SIZE=2] WM_COPYDATA [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int32 = &H4A[/SIZE]
 
[SIZE=2][COLOR=#0000ff]Protected[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Overrides[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] WndProc([/SIZE][SIZE=2][COLOR=#0000ff]ByRef[/COLOR][/SIZE][SIZE=2] m [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.Message)[/SIZE]
[SIZE=2][COLOR=#008000]'check for right type of message[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] m.Msg = WM_COPYDATA [/SIZE][SIZE=2][COLOR=#0000ff]Then[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'check if it's from our expected 'sender'[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'If m.WParam.ToInt32 = wndh Then[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'get the standard message structure from lparam[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] CD [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] COPYDATASTRUCT = m.GetLParam([/SIZE][SIZE=2][COLOR=#0000ff]GetType[/COLOR][/SIZE][SIZE=2](COPYDATASTRUCT))[/SIZE]
[SIZE=2][COLOR=#008000]'setup byte array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] B(CD.cbData) [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'copy data from memory into array[/COLOR][/SIZE]
[SIZE=2]Runtime.InteropServices.Marshal.Copy([/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IntPtr(CD.lpData), B, 0, CD.cbData)[/SIZE]
[SIZE=2][COLOR=#008000]'get as string and display in label[/COLOR][/SIZE]
[SIZE=2]Label1.Text = System.Text.Encoding.Default.GetString(B)[/SIZE]
[SIZE=2][COLOR=#008000]'empty array[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Erase[/COLOR][/SIZE][SIZE=2] B[/SIZE]
[SIZE=2][COLOR=#008000]'set message result to 'true', meaning message handled[/COLOR][/SIZE]
[SIZE=2]m.Result = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] IntPtr(1)[/SIZE]
[SIZE=2][COLOR=#008000]'End If[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=2][COLOR=#008000]'pass on result and all messages not handled by this app[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].WndProc(m)[/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
 
Last edited:
Richnl said:
I want to make sure I understand this mechanism first
Does it need to be altered a lot, if you want to talk back to the sender?
wndh:
Also the m.WParam is the window handle of the application that sent the data, you don't have to check this, but you can use it to verify/distinguish several different senders.
You can find window with FindWindow function. (see post 4)

To send you need the code in post 6, to receive the code in post 4.

Sockets is TCP networking, remote or local. Remoting can use several different transport layers, including TCP.

Type "overrides"+[space key] and the intellisense editor give the list of overridables. This code I posted here is correct and can be copied.

Windows Services doesn't have GUI, no windows, so they also don't get windows messages and don't use WM_COPYDATA. Instead for two-way communication they use other IPC options like sockets, remoting, file-based message drops (.Net FileSystemWatcher can be used to check for file changes), named pipes, or a combination. .Net ServiceController class can be used to send integer value commands one-way to a Windows Service.
 
I read you,

pipes was also my very first idea, but I moved on, because I could,t get proper documentation about it. And the code on msdn, couldn't make heads or tails with it. So I moved on to WM_copydata.

Leaves me with the Question, If I press send
The label on the second form gets blanked??
I don't know, It's the code above, same as yours except for the inherit'

What could be wrong, Its basicly copypaste ?? maybe some stupid beginnerstuf, you tell me
I would like to post both samples, but it's not possible here
 
Last edited:
It doesn't look like you copied the code from post 4 wrong, but I don't understand why you wrote 'Inherits System.Windows.Forms.Form'. With .Net 2.0 the inheritance is done in the partial form class that designer generates, just add new form to project or use the default one when you created a new windows application project.

Further, sure both apps are windows applications?
You used the code in post 6 to send?
You are sure you got the correct window handle to send to? (check this with other app, same as Me.Handle there).
 
It doesn't look like you copied the code from post 4 wrong, but I don't understand why you wrote 'Inherits System.Windows.Forms.Form'. With .Net 2.0 the inheritance is done in the partial form class that designer generates, just add new form to project or use the default one when you created a new windows application project.

Further, sure both apps are windows applications?
You used the code in post 6 to send?
You are sure you got the correct window handle to send to? (check this with other app, same as Me.Handle there).
Yes, I will remove it
It's typical that a lot of the tutorials do everything, and I don't know it's done automaticly for me.

I will check the handle where it's being send too, but if there is a default text in the label, and then it blanks, doesn't that mean it arrives at the handle it's supposed too?
 
It's definitivly the same handle?

I have posted the samples here

I also solved the problem
I had lParam in sendmessage declared as - byref lparam as object
My fault, thanks for your patience
 
Last edited:
Back
Top