Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sending @String PostMessage

909 views
Skip to first unread message

The Patrician

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
How can I send a pointer to a string with PostMessage... Do I just use
Integer(@S) where S is a String??

And how do I convert it back to a string again??


Rudy Velthuis

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
In article <3711F663...@Hotmail.com>, The Patrician wrote...

>How can I send a pointer to a string with PostMessage... Do I just use
>Integer(@S) where S is a String??
>
>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

Peter Below (TeamB)

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
In article <3711F663...@Hotmail.com>, The Patrician wrote:
> How can I send a pointer to a string with PostMessage... Do I just use
> Integer(@S) where S is a String??
>

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!


Stephen Walter

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
For 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 :-):

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 ...

Stephen Walter.vcf

The Patrician

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Just to check if this is OK:::

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));


Rudy Velthuis

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
In article <3713A26B...@Hotmail.com>, The Patrician wrote...
No need for the String(..) typecast, but yes, that's how you do it.

But are you sure you really want to do that? Read Peter Belows post about
the risks and pitfalls, please.
--
Rudy Velthuis

The Patrician

unread,
Apr 14, 1999, 3:00:00 AM4/14/99
to

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...

Peter Below (TeamB)

unread,
Apr 14, 1999, 3:00:00 AM4/14/99
to
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).

Stephen Walter

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to

Peter Below (TeamB) <10011...@compuXXserve.com> wrote in message ...

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.

Rudy Velthuis

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to
In article <7f4h0j$ih...@forums.borland.com>, Stephen Walter wrote...

>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

Philip Cain

unread,
Apr 16, 1999, 3:00:00 AM4/16/99
to
"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote:

>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
--

Stephen Walter

unread,
Apr 16, 1999, 3:00:00 AM4/16/99
to
Got a response in the oleautomation group from Joel Milne.

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).
>

Stephen Walter.vcf

Peter Below (TeamB)

unread,
Apr 16, 1999, 3:00:00 AM4/16/99
to
In article <3717841...@forums.inprise.com>, Philip Cain wrote:
> 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.
>

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.

0 new messages