Last edit: 05-03-17 Graham Wideman |
Delphi
|
Delphi OLE and Drag and Drop: Comments on Books
Article created: 98-06-26
Major revs: 98-07-29 |
The following comments are intended to extend the material on OLE drag and drop found
in various books, and are not meant as a devaluation of the authors' valiant works!
High Performance Delphi 3 Programming (Several authors, the drag and drop
section is by Jim Mischel)
It was JM's chapters in HPD3P that got me rolling on this project in the first place,
so thanks for the head start! However, there are several pieces of code that I now
believe need revision:
- There are a number of places where Jim adds _AddRefs and _Release calls. I believe
these are unnecessary. Specifically:
- p121, 122, There is an _AddRef call in the constructors of TFileDropSource and
THDropDataObject which should not be there. These are connected with...
- p126: Jim assigns the DropSource and DataObject objects to regular Pascal objects and
then passes them in this form to DoDragDrop. This form of call fails to cause Delphi
to generate the automatic AddRef (as the GWRefCt demo shows)... perhaps that's why Jim
placed AddRef's in the constructors?
- p126: presumably because there was no auto-AddRef-Release sequence, Jim then explicitly
Frees the DropSource and DropData objects, which should be unnecessary.
- p102: Jim places an _AddRef in the constructor for FileDropTarget, then calls a couple
of API functions providing "self" as the IDropTarget parameter. I don't
think the AddRef is necessary, though I agree with Jim's comments that there is a larger
problem surrounding the issue of destroying the DropTarget object which calls for some
fudging at that time anyway.
- p104: There's an dataobj.AddRef at the beginning and dataobj.Release at the end of the
Drop function. These are not harmful, but not needed.
- In TFileDropTarget.Destroy Jim comments that there's the possibility of a Destroy loop.
TGWDropTarget deals with that. Also in that routine I believe that
RevokeDragDrop and CoLockObjectExternal(... unlock...) are called in reverse order...
though the impact may be insignificant.
Delphi
Developer's Handbook (Cantu, Gooch, Lam, OLE/COM section by John Lam)
- There's an extensive discussion of COM, elaborating numerous complexities
(informatively, but rather alarmingly) before you get to the part about how Delphi
takes care of many of them. One might easily get the impression that COM is going to be a
lot of work. In fact, Delphi language features, and supplied COM objects take care
of much of the COM complexity for you. That said it would perhaps be more
encouraging if the COM material was presented first from a Delphi point of view
(an approach that VB presentations manage to use successfully), and only then "oh by
the way, here's what's cooking behind the scenes."
- The OLE Drop example develops a non-visual VCL DropComponent that you can stick on a
form to allow some other (visual) component to accept files dropped on it. The
component includes some pretty crafty techniques, but in the process may seem rather
formidable. The deviousness is introduced in the interests of packaging the Drop
functionality as a VCL component, while dealing with some unfortunate conflicts between
the VCL and COM destroy behaviors. (It appears that D4 implements a pre-Destroy
event that might alleviate the problem that DDH's component was trying to work around.)
I
felt that COM is loaded with enough complicated conceptual baggage as it is, and I
prefered to see and manipulate only the parts that related to COM, and set aside the extra
apparatus (and elegance) of a VCL component for my example code. Along the way I
developed a suspicion that flexibility to implement a variety of OLE-drop behaviors might
actually be hard to "parametrize" in a VCL component's properties, and instead
it's perhaps easier to get what you want with ordinary objects. The jury's still out
on that one!
- p464-465: It's not clear to me why the examples show explicit use of AddRef and Release,
since so far as I can tell, Delphi handles this automatically. In fact, those examples
would seem not to work properly. The In-out example in particular doesn't make sense -- so
far as I can tell, attempting to provide an already-assigned reference to an out parameter
Releases it immediately (before it can be seen inside the function, and unlike a Var
parameter).
Inside OLE 2 (first and second editions)
It may be the bible of OLE, but it's at a level that's a tad too deep in OLE
terminology and concepts to wade into if you've never seen OLE before. It's been several
years since I bought the book, and now that I know a lot more about OLE/COM, Java and
about O-O systems in general, I can go back and see what this book is talking about.
So, if you're tempted to start here, it might be better to pick a gentler
introduction first. There's a heck of a lot of stuff here that you don't need to know if
you are going to use Delphi.
On a finer point, I was a little unnerved to see a discussion of CoLockObjectExternal
(needed for DropTarget) which amount to "no one really knows why, it has something to
do with preventing the system from killing your COM object, and we're pretty sure it's a
design flaw, but trust me, you have to use it". (Bear in mind that Kraig B's official job at MS was to
explain COM. The Second Edition does have a little more explanation.)
That, coupled with Jim M's extra AddRefs is what motivated the extra attention to the
DropTarget create and destroy process in my example code.
Go to: Drag and Drop Intro Page, or