Hallo Marcel,
----- Original Message ----- >
>>>> The problem is that you have to come up with some sort of tracking when
>>>> the DnD is accomplished for all objects.
>>>> Then you can free the whole shared memory block.
>>>
>>> DRM_ENDCONVERSATION should do the job.
>>
>> Yes, but it needs to be called by the target for EACH drag object.
>
> You are right. But I didn't see the wood for the trees. It seems that I
> can pass a group of objects in /one/ DRAGITEM structure while still
> showing several icons. So there is only one object to clean up at exactly
> one DRM_ENDCONVERSATION.
No, at least it's not the original intention of the DnD designer.
Principally:
1) the DRAGINFO structure describes the Drag as such, including one or more
drag items
2) the DRAGITEM structure describes one item being part of the drag
3) the DRAGIMAGE structure describes one picture of possible multiple
pictures which are cascaded on top of each other. It's only a visual
representation of the drag and nothing else. You can have an arbitrary
number of pictures associated with a drag. You could have only one picture
even if you drag several items, you could have a picture per drag item or
any other number. OS/2 will do its best to properly cascade (and even limit
the number of ?) pictures to get a good visual representation.
4) the DRAGTRANSFER structures describes one item being part of the drag
much like 2) but for the needs of source rendering
Of course you can "misuse" this mechanism and only use one DRAGITEM
structure and somehow implement your own "private protocol" to jam multiple
items into just one DRAGITEM structure.
>> I think you misunderstood me. "hstrRenderToName" is just a 4 byte
>> location.
>> You may place a pointer to shared memory into this field and I seem to
>> remember this is what EPM does if you ask it to source render with the
>> "shared memory" RMF.
>
> You say that there is no need that it has to be a string handle at all?
Yes, exactly. There is no need to use DrgAddStrHandle. I guess what
DrgAddStrHandle really does is allocate shared memory/reserve some room in
the shared DnD exchange structure, copy the string from private memory to
that shared memory and return a pointer or handle to this shared memory
location so that it can be found by DrgQueryStrName.
The only thing you have to make sure is that if you pass a memory address in
hstrRenderToName or any other hstr for direct use by your source application
then you better make sure it points to SHARED memory and that you either use
the "give" or the "get" mechanism to allow the source application to
actually access this shared memory.
Thinking about it: you don't need source rendering to do that. You could
also use target rendering and specify a RMF for the target to understand.
> Fortunately it is not that hard. Once the DnD completed there is no need
> for further synchronization. It may only happen that unsaved objects are
> dragged to another application instance. And since they only exist in the
> source's private memory I must use source rendering.
See above. If you want to pass something in memory it needs to be in SHARED
memory.
>>>> There are issues in properly freeing the DnD
>>>> resources, the PM REF description is a mess ...
>>>
>> That's why I offered the code sample. It is based on what Rich Walsh
>> found about the topic.
>
> I see. Currently I use some article at ARTofOS2.
Unfortunately this doc might also be wrong at least concerning source
rendering. What I remember from the top of my head:
1) DrgAllocDragInfo and DrgFreeDragInfo must be called as a pair by the
source.
2) DrgAccessDragInfo and DrgFreeDragInfo must be called as a pair by the
target for DM_DRAGOVER and also DM_DROPHELP. For DM_DROP you only call
DrgAccessDragInfo (unless you want to abort in case of error in which case
you also have to call DrgFreeDragInfo). The source will then eventually call
DrgFreeDragInfo. For DM_RENDERCOMPLETE you only call DrgFreeDragInfo.
DrgFreeDragInfo is particularly problematic on source rendering: as said, it
needs to be freed on a DM_RENDERCOMPLETE and only once the last drag item is
processed. But there is no good field to store the drginfo pointer and the
DrgDrgInfoFrom... routines DO NOT work for this purpose (they only work for
lazy drag). The solution was to use "ulTargetInfo" field to jam in the
pointer.
3) DrgAllocDragTransfer and DrgFreeDragTransfer must be called as a pair by
the target
4) I would need to check of how to handle DrgAddStrHandle /
DrgDeleteStrHandle / DrgDeleteDraginfoStrHandles and where to free them
(maybe even at source AND target). And then DrgDeleteDraginfoStrHandles has
a flaw in that it aborts when it finds an invalid handle (and therefore will
not free all handles) and therefore you should implement a replacement
routine.
There must be some complicated reference counting for the source and target
buried in the DnD engine.
Rich had explored deeply into this mess when he added/extended DnD support
to/for Mozilla. I trust him more than any documentation ...
Lars