 |
|
|
 |
|
 |
The example given has a slight error which only occurs under certain circumstances:
Private Function ProcessWindowMessages(ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
The last parameter should be a long, not an int. If you lock your workstation with this set as an int, a negative value is shown which blows out the app with a win32 exception. Taken me months to track it down!
|
|
|
|
 |
|
 |
You can download it from the following link:
Just type the link in the browser and download it
Download link: http://w17.easy-share.com/1700679295.html
Delete link: http://w17.easy-share.com/1700679295/del_6dkt4bvbdlua2o4n
|
|
|
|
 |
|
 |
Does this work in Vista? I thought Vista dropped some stuff (of course later they added some stuff back in).
|
|
|
|
 |
|
 |
hay this is the best IPC thing i've ever read !!
But ,....
can i pass anything other than this with windows message . like a parameter..etc
wndproc does have parameters like wparam and lparam . how can i pass any string from first application to second using this IPC ?
is there any scope of using WM_COPYDATA or something simillar (please describe it.)
Kedar
|
|
|
|
 |
|
|
 |
|
 |
thats really fine.
I'd like to send a structure{no,name} as a parameter .
how to do that using WM_COPYDATA ?
"You can do any thing you set to your mind" - theGhost_k8
|
|
|
|
 |
|
 |
I have not had to copy a structure through the method I used (so long ago), so have not used WM_COPYDATA method. This page seems to have a good code listing
http://www.codeguru.com/forum/printthread.php?t=231750
I also thought you could use a comma-delimited string, or something along those lines to transfer a heap of strings. I guess there would be a size limitation on the parameters of the SendMessage function though..
Hope that helps!!!
Angus
3 out of every 4 people make up 75% of the worlds' population
-- modified at 23:48 Wednesday 21st June, 2006
|
|
|
|
 |
|
 |
hi ! glad to see your immediate reply to the post.
Now about the problem.
Yes ! The real reson of passing a structure is not to pass a string but an object. As u've suggested about comma-delimited string, thats of no use in that case. Check what i've tried here is:- pass a structure like
Structure PT
Dim x As Integer
Dim y As Char
Dim xy As String
End Structure
Dim MyVariable As PT
MyVariable.X = 125
MyVariable.y = "c"
MyVariable.xy = "String is here"
Dim MyPointer As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(MyVariable))
Marshal.StructureToPtr(MyVariable, data.lpData, True)
and then used sendMessage to pass this structure. and on the other side at wndProc i listen to WM_COPYDATA unmarshall this and get this structure like this:
Dim MyPoint As PT
MyPoint = Marshal.PtrToStructure(CType(m.GetLParam(GetType(CopyData)), CopyData).lpData, GetType(PT))
MsgBox("->" & MyPoint.y & "<--->" & MyPoint.x & "<----->" & MyPoint.xy & "<-")
NOW THE PROBLEM !! :- i'm not able to get all values of the structure , only the first parameter. i.e. x. remaining vaules are "junk-values".. so i think this may be a marshalling problem. If u want i can mail you the code.
-------------------------------xxxxxx--------------------------------
-------:FYI:-----
WHAT I AM DOING ??
While i click on "Save" button of any office-document i want to save it using my application.. not using windows-save-dialogbox..
I HAVE FAILED TO DO:-
capture the event of "Save_Button" of "Word" AND call my_dialogbox to save. and pass this doc.'s object by applicationObject. But Cant get handle to that "save" button of "File" menu or track event of that click...
SO WHAT WAY I'M FOLLOWING??
I've created an addin to word. [VB.NET]
By clickin that addin-button i want to pass this word's object to my application (My_Save_dlgBox) to save this word.
HOPE:- ONLY YOU
- Thank You Very Much
[Kedar V]
Least I aspect:- any thoughts/Ideas from your side that i may have missed-out..
"You can do any thing you set to your mind" - theGhost_k8
|
|
|
|
 |
|
 |
Hmm, after some googling I think the following link may help you, assuming add-in and receiving application are both in .Net. It deals with serialising objects and then passing them through WM_COPYDATA, but with a wrap-around class. It has some samples there so hope that helps.
http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows_Messages/Simple_Interprocess_Communication/article.asp
I must admit I have not gone any further with inter-process communication than this article, and am not actually using that code any more. Everything has been converted across to VB.Net now.
Angus.
Angus
3 out of every 4 people make up 75% of the worlds' population
-- modified at 3:33 Saturday 1st July, 2006
|
|
|
|
 |
|
 |
how do you pass paramters as part of the windows message?
ex.I want to send a message from a VB app to a VB.NEt app but LOAD_CUSTOMER with a customer number 12345
|
|
|
|
 |
|
 |
You can pass integers through window messaging using the wParam and lParam parameters. Note the new MessageBox in VB.Net to show the wParam value. Also note the new "12345" value in the VB6 code to pass through the value. This should help you on your way.
Example below:
VB.Net (clsWindowMessaging.vb)
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case VB6_TO_VBNET_MessageId().ToInt32
MessageBox.Show("Windows Message from VB6 Environment", "VBNETMessaging")
MessageBox.Show(m.WParam.ToString)
Case CSHARP_TO_VBNET_MessageId().ToInt32
MessageBox.Show("Windows Message from C# Environment", "VBNETMessaging")
MessageBox.Show(m.WParam.ToString)
End Select
MyBase.WndProc(m)
End Sub
VB6 (modMessaging.bas)
Public Function SendMessageToVBNET()
Dim hwndTarget As Long
Dim MessageId As Long
If WindowMessagingInitialised = False Then
InitWindowMessaging
End If
hwndTarget = VBNET_WindowHandle
MessageId = VB6_TO_VBNET_MessageId
If hwndTarget <> 0 Then
Call PostMessage(hwndTarget, MessageId, 12345, 0)
End If
End Function
Angus
3 out of every 4 people make up 75% of the worlds' population
|
|
|
|
 |
|
 |
HWND_BROADCAST not working for u?
All your source are belong to us!
|
|
|
|
 |
|
 |
Hi Guys,
Great Tutorial. I like it and I like the code.
I have one question though. How can you make this work to pass messages from one VB6 application on a PC to another VB6 application on another PC. I have to place a small VB app on the server that triggers a refresh on the client side everytime the database is updated.
I appreciate any help on the subject.
Thanks
Salim
|
|
|
|
 |
|
 |
What you need to be looking for is client-server communications in VB6. Having never done this (ewww), I can't really be much help besides googling some results for you.
-> http://www.vbip.com/winsock/winsock_control_ssahmed_01.asp
-> http://www.codeproject.com/Purgatory/winsock.asp
Book from Amazon: http://www.amazon.com/gp/product/1571691545/103-0165782-9268656?v=glance&n=283155
Hope they start you on a road to a solution.
Angus
3 out of every 4 people make up 75% of the worlds' population
|
|
|
|
 |
|
 |
Thanks minja. I have already looked up these pages myself and I am working on it. Hope this leads to where I want to be.
I will try to use winsock along with windows messaging for a better result but then again I might just stick to winsock.
Thanks again,
Salim
|
|
|
|
 |
|
 |
Hi,
first at all thanks for this how-to. It is realy nice.
Going to the point, I'm trying to send a string through the LParam argument of the message. After doing some search in google, I found that you can even pass objects if you want; the trick is that instead of passing a string to the PostMessage function, you have to call it with a pointer to a memory address (IntPtr in other words) and change the declaration of PostMessage to reflect this.
I have tried several things, but it seams that either the contents of the memory address are deleted after doing the PostMessage or I'm doing something wrong in the other side of the comunication. Have you ever tried to do this?
Before posting my code here, I have to explain that I have two applications coded in C#: a server and a client which send messages each other (If you are interested, I could send the complete source to you). I modify your code a little bit to do a C# Server to C# Client communication and viceversa; messages are received, but the string in the memory address is lost. So here is the code:
[DllImport("user32.dll")]
//I replaced the lParameter type by an IntPtr
//in order to be able to pass a pointer to a
//string as a message. I found some messages
//in google, which says that you can do that
public static extern IntPtr PostMessage (IntPtr hwnd,
IntPtr wMsg, Int32 wParam, IntPtr lParam);
protected override void WndProc(ref Message m)
{
if (m.Msg == CSHARP_SERVER_TO_CLIENT_MessageId.ToInt32())
{
MessageBox.Show("Windows Message from Server environment", "C#ClientMessaging");
//Here I will try to get the contents of the memory
//address referenced by m.LParam. I checked this value
//in both: the client and the server and it has the same
//value, but the string returned by PtrToStringAuto is
//either empty or has garbage on it.
string test = Marshal.PtrToStringAuto(m.LParam);
MessageBox.Show(test);
}
base.WndProc(ref m);
}
public void SendMessageToServer()
{
IntPtr hwndTarget;
IntPtr MessageId;
//This is a pointer to a memory address I
//create to store a string
IntPtr messagePointer;
//The local variable to assign the string
string msgStr;
hwndTarget = this.SERVER_WindowHandle;
MessageId = CSHARP_CLIENT_TO_SERVER_MessageId;
//Assign some message to send
msgStr = "test";
//Allocate memory to the string and store it somewhere
//on the heap. messagePointer will get the memory
//address, where the string was stored
messagePointer = Marshal.StringToHGlobalAuto(msgStr);
//As a test, I read the string from the memory address
//on another variable and it works, I get "test"
string test = Marshal.PtrToStringAuto(messagePointer);
MessageBox.Show(test);
if (!System.IntPtr.Zero.Equals(hwndTarget))
{
//messagePointer is used as LParam for the PostMessage function
PostMessage(hwndTarget, MessageId, 0, messagePointer);
}
}
The client application is almost the same, the only thing that changes are the method and variable names.
I even tried to test it with your example by modifying the VB.Net and C# examples but it didn't work as well. Do you know how to solve it?
Thanks in advanced,
Josef Meile
|
|
|
|
 |
|
 |
Ah, by the way, before I found your code, I was trying to get it working with the WM_COPYDATA how to you mention in the "Confused... " thread, the problem here is that I'm working with Excel and Visio COM Objects and they can't be accessed from the WM_COPYDATA handler, I get:
An outgoing call cannot be made since the application is dispatching an input-synchronous call.
So, I search on google and found a delphi message, where the solution was to send a message with PostMessage and not *SendMessage*, which will throw the same exception as well. Unfortunatelly, all the messages I have found, not many, suggest diferent things, but none of them have a complete solution to the problem.
Regards,
Josef
|
|
|
|
 |
|
 |
Ok, I found the answer to my question:
It seems like I can't do what I want with PostMessage. As I have read, the difference with SendMessage is that the later sends a message to a window inmediately and waits for an answer; while PostMessage sends the message to the forms' message queue and exits. So, the memory location I stored in my SendMessageToServer method will be lost because it is local. To solve this problem I found that I could used something called FileMap, which creates a memory that can be shared between different processes. I guess it will work, but something more direct would have being better
The other issue I had with the COM Objects is that they only can be used by the thread that originated then, so, there will be problems with the How-To you mentioned: WM_COPYDATA because it uses SendMessage, which creates a new thread whenever a new message arrives. Here I also tried the Invoke and BeginInvoke functions of DotNet, but I had the same error messages
Thanks anyway,
Josef
|
|
|
|
 |
|
 |
I am interested on VB.Net sample... let me get things straight....
You use CreateParams() to create some sort of fake form and then use FindWindow() from say VB6 to get this fake form's handle in order to finally use PostMessage() to send the message (which is actually a pointer)?
This is quite interesting but I cant seem to think of a way to use it
Its like having a pager in the age of cell phones... you just page the other app but cant actually send something usefull to it... let say a string or at least a pointer to a string (dont really know how to access the string from that pointer lol)... Will this baby work on a windowless application? Like an application that just sits on the tray? I figured out how to use a mutex to see if my app is already running and now i am trying to have the second 'copy' of the app deliver all the command line arguments it started with to the first app... that would be usefull Any tips?
Thanks in advance
John
|
|
|
|
 |
|
 |
What I was searching is here. This article explains how to send simple datatypes between processes. I combined it with your 'fake' form code and I got the job done!
|
|
|
|
 |
|
 |
cool, just as I was about to try to answer your question.
yep, that is a nice way to combine. The way we were using it was just as a notifier between VB.Net app and VB6 app when a certain process finished. We didn't need any data, just needed to know that something had finished.
maybe you should write up an extension article to mine!!
Angus
3 out of every 4 people make up 75% of the worlds' population
|
|
|
|
 |
|
 |
Due to a reader request, I have now updated source and demos to include VB6 to VB6 communication. There are plenty of demos of this around the web, but it was a 5 minute job because I have everything setup already.
Angus
3 out of every 4 people make up 75% of the Worlds' population
|
|
|
|
 |
|
 |
I am experimenting with your code and seem to have gotten myself into the jam you describe below.
Now, when I run a VB6 project that initiates messaging, it blows out of VB as soon as I click on any other window. How can I undo the damage?
VB6: One thing to note that is VITALLY IMPORTANT is that you need to disconnect your custom Message Handler before the application closes, otherwise it starts to handle messages in the VB IDE. It was quite hard to track this problem down because it would work nicely when I ran the executable, but once inside the IDE, it would crash VB.
|
|
|
|
 |
|
 |
Is it crashing when you start the VB app, and then click on another window? If so, then I am guessing you have a mistake in the modMessaging.ProcessWindowMessages function. Make sure that if the Window Message is not one of your custom messages, then it is handed back down to the default message handler via the CallWindowProc Win32 function.
If it is passing to this, then I guessing that the address of the original handler has been set incorrectly.
If it is crashing when you quit the VB app back to VB6 and then click on another app, then your custom Window handling is never being set back to the original handler. Call the modMessaging.StopWindowMessaging function to reset the handler back to the original (usually MainForm).
Try these and if it does not work, get back to me. Do the compiled app's work for you?
Angus
3 out of every 4 people make up 75% of the Worlds' population
|
|
|
|
 |