And how do I convert it back to a string again??
Use LParam(PChar(MyString)) or WParam(PChar(MyString)) in D2 and higher.
To convert back: MyOtherString := PChar(LParam);
--
Rudy Velthuis
It cannot be done at all with PostMessage if the target window is in
another process, since pointers are not valid outside the source
process. Even if the target window is in your application you have a
problem: PostMessage is asynchronous, the function returns before the
target window has processed the message and you have to make sure that
the pointer you send with the message is still valid when the target
finally gets to processing the message. That would not be the case if
you a local String variable, for instance.
A way to solve this dilemma is to use a dynamically created buffer to
hold the string and make it the responsibility of the receiver to free
this buffer:
Var
S: String; // string to send
pBuf: PChar;
S:= ...
pBuf := StrAlloc( Length(S)+1 );
StrCopy( pBuf, PChar(S));
PostMessage( targetWnd, UM_SETText, 0, lparam( pBuf ));
The receiver would do this
procedure TFormx.UMSetText(Var msg: TMessage );
Var
S: String;
Begin
S:= Pchar(msg.lparam);
StrDispose( Pchar( msg.lparam ));
...work with S
Drawback: if the message should go astray for some reason you have a
memory leak. So for communication inside your own application you should
use SendMessage instead of PostMessage, if possible. With that you could
indeed use lparam( SomeStringVar ) to pass a string with the message and
on the receivers end String(msg.lparam) to get it back. Do not modify
the string on the receiver side, make a copy instead. This typecasting
stuff derails the reference management for AnsiStrings.
Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitely requested!
Sender:
uses
.... ActiveX, ShlObj;
function SendMyString(s: String): Boolean;
var
Malloc: IMalloc;
HR : HResult;
ps: PChar;
begin
Result := False
HR := SHGetMalloc(Malloc);
if Failed(HR) then
Exit;
try
OLECheck(SHGetMalloc(Malloc));
ps := Malloc.Alloc(Length(s));
StrCopy(ps, PChar(s));
PostMessage( ........LPARAM(ps); {From Rudy's reply}
Result := True;
finally
{No need to free the Malloc interface as this is done by Delphi when it
goes out of scope}
end;
end;
Receiver:
function ProcessMyIncomingMessage(ps: PChar): Boolean;
var
Malloc: IMalloc;
HR : HResult;
begin
Result := False
HR := SHGetMalloc(Malloc);
if Failed(HR) then
Exit;
try
{Do something with the string}
Result := True;
finally
Malloc.Free(ps); {frees the memory allocated by the sender}
{No need to free the Malloc interface as this is done by Delphi when it
goes out of scope}
end;
end;
This is one way of skinning the inter-process messaging cat. Another would
be to pass around offsets into a shared memory-mapped file, but that might
be overkill for the simpler situations.
--
Regards, Stephen Walter
Peter Below (TeamB) <10011...@compuXXserve.com> wrote in message ...
What I do is, I have a PChar (P), which I convert to an integer:
PostMessage(Handle, messageCall, Integer(P), 0);
On the other side I do the following (S: String; I: Integer):
S := String(PChar(I));
But are you sure you really want to do that? Read Peter Belows post about
the risks and pitfalls, please.
--
Rudy Velthuis
Rudy Velthuis wrote:
I did, but as far as I know, there is no other way for a internal DLL to
notify my main form of a string. I need to exchange data between many forms
and call messages as standard to perform certain tasks. However it works fine
for now... If you have any other idea's to accomplish the above, please tell
me...
I don't know if it would work. You assume that the shell allocator uses some
kind of "shared" memory pool to allocate from, so the pointer returned would
be valid in any process. I doubt that it works this way (but this is outside
my area of expertise, so i may be wrong).
Peter, your point is well taken. That is essentially my assumption and I now
realise that while this assumption is definitely the case for shell
extensions, which are always in-process serverrs (i.e. DLL's which happen to
be loaded by explorer.exe), that doesn't address the original issue raised,
which was after a inter-process solution.
I do think (though with less conviction) that IMalloc is the way of getting
memory allocations for all of COM (i.e. for inter-process or standalone
servers), and so would be valid here.
I'll post a message over in oleautomation to resolve this. The folks who
live there are up on this stuff, I think.
This begs the issue that, by involving COM as per my suggestion, it makes
the implementation lack the "lightness of being" that the original
questioner was probably after by using inter-process messaging. However, if
not that, then the general advice is to use memory-mapped files for
communicating buffers between processes under Win32.
>This begs the issue that, by involving COM as per my suggestion, it makes
>the implementation lack the "lightness of being" that the original
>questioner was probably after by using inter-process messaging. However, if
>not that, then the general advice is to use memory-mapped files for
>communicating buffers between processes under Win32.
There is a demo for IPC in the demos directory of Delphi. It has classes
for using shared memory (TSharedMem), which uses memory mapped files, and
other means of communication between processes and/or threads.
--
Rudy Velthuis
rvel...@gmx.net
http://members.xoom.com/RVelthuis
>I don't know if it would work. You assume that the shell allocator uses some
>kind of "shared" memory pool to allocate from, so the pointer returned would
>be valid in any process. I doubt that it works this way (but this is outside
>my area of expertise, so i may be wrong).
Peter,
I'm not into DLLs yet so I may be off the mark, but why isn't the
solution to have resource strings or constants in the DLL with the
error messages and attending message numbers.
I think the VCL does this in part. The message posted carries the
error number and there exists a call to fetch the string. Why can't a
DLL do this?
Phil
--
See thread "Is IMalloc'ated memory valid across processes" for full details,
but in summary:
a) The shell allocator's implementation if IMalloc produces local (i.e.
intraprocess) memory blocks, so it's not a solution for inter-process. Sorry
for misleading anyone.
b) Solutions that would work include
- memory-mapped files (as suggested)
- passing handles to globally allocated memory
- named pipes (but these can only be created under NT, although can be
used by '95 clients once created
- mailslots.
Apologies again for leading anyone astray.
--
Regards, Stephen Walter
Peter Below (TeamB) <10011...@compuXXserve.com> wrote in message ...
>In article <7etv55$cc...@forums.borland.com>, Stephen Walter wrote:
>> or the case of sending the message inter-process, could not the sender
use
>> memory provided by the shell's allocator, with the responsibility of
>> deallocation left with the receiver as follows (treat as pseudocode ... I
>> haven't tested this code, though the bits I cut from the VListView demo
>> should work fine :-):
>>
>
>I don't know if it would work. You assume that the shell allocator uses
some
>kind of "shared" memory pool to allocate from, so the pointer returned
would
>be valid in any process. I doubt that it works this way (but this is
outside
>my area of expertise, so i may be wrong).
>
The original question was rather hazy about who would be the recipient
of the message. The post you quoted evolved out of a reply for the case
that the recipient is a window in another process. That is a problem
different from messaging between windows in the same process, since we
now have to deal with two different address spaces. If you send a kind
of string code (type integer, probably a resource ID) in the message
then the receiver needs to use the same DLL the sender is using to be
able to fetch the string from a resource in the DLL. This is certainly
a possible solution but it *only* works if the strings are constants,
not if they are dynamically assembled at run-time.