Author |
Topic: WM_COPYDATA (Read 2801 times) |
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
WM_COPYDATA
« Thread started on: Sep 6th, 2011, 10:02pm » |
|
Hi,
Regarding WM_COPYDATA
Do you know of any BBC4W programmes which use this function to move data to/from other apps?
I am presuming that this function copies a given amount of data to the memory heap of the target application. You have to pass to the target a pointer to a COPYDATASTRUCT comprising:
dwData ULONG_PTR The data to be passed to the receiving application.
cbData DWORD The size, in bytes, of the data pointed to by the lpData member.
lpData PVOID The data to be passed to the receiving application. This member can be NULL.
So in BBC4W terms, ULONG_PTR would be set to the start address of the data in memory to be copied, cbData is the number of bytes - but what is lpData?
How can it be simultaneously "The data to be passed..." and "This member can be NULL"?
Thanks
Nick
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: WM_COPYDATA
« Reply #1 on: Sep 7th, 2011, 08:20am » |
|
on Sep 6th, 2011, 10:02pm, Nick wrote:Regarding WM_COPYDATA, Do you know of any BBC4W programmes which use this function to move data to/from other apps? |
|
Yes, the Module Viewer add-in utility uses it. When you say "other apps" obviously both 'ends' of the link must coöperate - one sending the WM_COPYDATA message and the other receiving it - so you can't use it to transfer data to or from an app you haven't written yourself unless you happen to know it processes that message.
Quote:what is lpData? How can it be simultaneously "The data to be passed..." and "This member can be NULL"? |
|
It can't be NULL if you're actually passing some data in memory! The situation in which it can be NULL is if you're using WM_COPYDATA only to send (up to) 32 bits of data in cbData.
The big advantage of WM_COPYDATA over rolling your own 'custom' message is that it takes care of marshalling the data between the two independent address spaces of the two processes.
Richard.
|
|
Logged
|
|
|
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
Re: WM_COPYDATA
« Reply #2 on: Sep 7th, 2011, 09:21am » |
|
on Sep 7th, 2011, 08:20am, Richard Russell wrote:Yes, the Module Viewer add-in utility uses it. |
|
Is there any chance of getting the source code - at least of the PROC/FN that builds your COPYDATASTRUCT?
Quote: so you can't use it to transfer data to or from an app you haven't written yourself |
|
Noted - I am writing both sender and receiver apps.
Thanks for the clarification with lpData!
Am I right to assume that if you get a TRUE response to sending a WM_COPYDATA message, it means that windows has managed to understand your DATACOPY struct and has copied the data to the receiver's memory space?
That is the point in my present code where it is not working! I just get a 0 returned from the WM_COPYDATA message.
Thanks again for BBC4W - it is fabulous.
Nick
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: WM_COPYDATA
« Reply #3 on: Sep 7th, 2011, 12:58pm » |
|
on Sep 7th, 2011, 09:21am, Nick wrote:Is there any chance of getting the source code - at least of the PROC/FN that builds your COPYDATASTRUCT? |
|
Couldn't be simpler, really:
Code: DIM cds{dwData%, cbData%, lpData%}
cds.dwData% = pAddress%
cds.cbData% = codesize%
cds.lpData% = code% Quote:Am I right to assume that if you get a TRUE response to sending a WM_COPYDATA message, it means that windows has managed to understand your DATACOPY struct and has copied the data to the receiver's memory space? |
|
That seems unlikely. MSDN implies that it works like any other 'sent' message - the returned value is whatever the receiving application returns.
Quote:That is the point in my present code where it is not working! I just get a 0 returned from the WM_COPYDATA message. |
|
Does your receiving application see the message, and if so what does it return? Are you using assembler code to handle the receipt of the message, or the SUBCLASS library? Neither is exactly straightforward. :(
Richard.
|
|
Logged
|
|
|
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
Re: WM_COPYDATA
« Reply #4 on: Sep 8th, 2011, 12:15pm » |
|
on Sep 7th, 2011, 12:58pm, Richard Russell wrote: [quote]Does your receiving application see the message, and if so what does it return? |
|
Yes, it most definitely does. The wparam indeed points to the SENDER Hwin, and the lparam is non-zero and the @msg% bit is 74 (WM_COPYDATA). The routine returns the value I state when it returns form processing the COPYDATA message. That value is correctly returned to the sender app.
BUT (and this is where i am struggling), I am unsure how to access the pointer to the copied data (the lparam value).
I presume that during the message processing, I have to set up a structure identical to the one sent (ie the COPYDATA structure). Once this is filled it will give me individual access to the three structure components. Then I can get the data, copy it and exit the message processing.
But I can's simply equate the lparam to my (e.g.) RECEIVED_COPIEDDATASTRUCT
How do I pass the 'pointer' contained in the lparam to my structure? Is the lparam value simply the start address in the receivers' memory to the identical DATASTRUCT that was sent? or is it a "pointer" in some other sense?
Sorry to sound lame 
Nick
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: WM_COPYDATA
« Reply #5 on: Sep 8th, 2011, 1:13pm » |
|
on Sep 8th, 2011, 12:15pm, Nick wrote:How do I pass the 'pointer' contained in the lparam to my structure? |
|
You have to use this piece of BB4W 'magic':
Code: What this does is to change the structure's data pointer so that it points to the data in the received message.
Richard.
|
|
Logged
|
|
|
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
Re: WM_COPYDATA
« Reply #6 on: Sep 8th, 2011, 1:37pm » |
|
on Sep 8th, 2011, 1:13pm, Richard Russell wrote:You have to use this piece of BB4W 'magic': |
|
That makes a lot of sense now. - thank you.
So like this?:
DEF FN_copydata(m%,w%,l%) REM This has to be fast - just get the data and return REM m% is the WM_COPYDATA value (74) REM w% is sender handle REM l% points to COPYDATASTRUCT DIM RECEIVED_COPYDATA{dw%,cb%,lpdata%} !(^RECEIVED_COPYDATA{}+4) = l% return_value%=97 REM arbitrary choice! = return_value%
(this is my FN that handles the subclassed COPYDATA message)
And: will it need similar 'magic' on the sending function?
SYS "SendMessage", target_hwnd%, WM_COPYDATA, @hwnd%, COPYDATASTRUCT {} ?
Nick
|
« Last Edit: Sep 8th, 2011, 3:09pm by Nick » |
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: WM_COPYDATA
« Reply #7 on: Sep 8th, 2011, 4:07pm » |
|
on Sep 8th, 2011, 1:37pm, Nick wrote: Bear in mind that, as a rule, any pointers sent in a message are only valid until the receiving end returns. So make sure you do everything you need with the values contained in the COPYDATASTRUCT before the '= return_value%'. Arguably you would be better off making it a LOCAL structure rather than a Global structure, to guarantee this.
Quote:return_value%=97 REM arbitrary choice! = return_value% |
|
MSDN says you should return TRUE (=1), so it's not really an "arbitrary choice".
Richard.
|
|
Logged
|
|
|
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
Re: WM_COPYDATA
« Reply #8 on: Sep 8th, 2011, 4:33pm » |
|
on Sep 8th, 2011, 4:07pm, Richard Russell wrote:Bear in mind that, as a rule, any pointers sent in a message are only valid until the receiving end returns. |
|
Yes, I was going to add that once the IPC bit of it was working properly.
Unfortunately mine still doesn't work. Does the COPYDATA statement at the sending end need similar 'magic'?
At present:
SYS "SendMessage", target_hwnd%, WM_COPYDATA, @hwnd%, COPYDATASTRUCT {}
Thanks Nick
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: WM_COPYDATA
« Reply #9 on: Sep 8th, 2011, 9:34pm » |
|
on Sep 8th, 2011, 4:33pm, Nick wrote:At present: SYS "SendMessage", target_hwnd%, WM_COPYDATA, @hwnd%, COPYDATASTRUCT {} |
|
That looks OK to me (except that there's a space between COPYDATASTRUCT and the opening brace, which isn't allowed). Anyway, you said your receiving application was seeing the message successfully so it must be working.
Incidentally, I presume you realise that COPYDATASTRUCT is the name of the generic structure; typically not of a particular instantiation (of which there could be several in a program). Although there's nothing stopping you calling your structure that, I would normally use a more succinct name such as cds{}.
Richard.
|
|
Logged
|
|
|
|
Nick
New Member
member is offline


Gender: 
Posts: 33
|
 |
Re: WM_COPYDATA
« Reply #10 on: Sep 10th, 2011, 05:30am » |
|
on Sep 8th, 2011, 9:34pm, Richard Russell wrote:That looks OK to me (except that there's a space between COPYDATASTRUCT and the opening brace, which isn't allowed). Anyway, you said your receiving application was seeing the message successfully so it must be working. |
|
Yes, after some tidying up, it works nicely.
Quote:Incidentally, I presume you realise that COPYDATASTRUCT is the name of the generic structure; typically not of a particular instantiation |
|
Yes, I did. I have it like this while authoring - it helps me to see more clearly which variable is what.
Thanks again - your help is much appreciated.
Nick
|
|
Logged
|
|
|
|
|