Enabling Direct Manipulation

OS/2 Presentation Manager (PM) implements direct manipulation using a set of window events specific to that task. The Windows operating system uses callbacks that are used to generate the analogous events. If your Open Class Library applications support drag and drop, you must attach handlers to your windows to process those events. The direct manipulation handlers implement each of the handler virtual functions to compose a functional framework you can use as provided or you can extend. You do not derive from these classes but you derive from the other classes in the direct manipulation framework.

IDMSourceHandler and IDMTargetHandler are derived from IDMHandler. They handle the Presentation Manager direct manipulation window messages. Objects from these classes pick up the WM_* and DM_* messages for the source and target objects and translate them into virtual function calls to the handler.

In addition to translating messages to virtual function calls, these handlers also manage renderers.

The following sections discuss how to add direct manipulation to your applications.


Enabling a Control as a Drop Target

To enable other controls as drop targets, you must specifically create the drag items and item providers that the Open Class Library generates automatically for entry field, MLE, and container controls. Do the following:

  1. Derive a class from the base class IDMItem and override the targetDrop member function and the following IDMItem constructor:
       IDMItem ( const Handle&       item );
    
  2. Write a drag item provider class for the customized item class using the IDMItemProviderFor template class, overriding provider functions when necessary:
    provideEnterSupport
    Override to provide drag item and target verification that is not supplied by default and provide target emphasis.
    provideLeaveSupport
    Override to provide additional cleanup not supplied by default and remove target emphasis.
    provideHelpFor
    Override to provide help support (OS/2 only).
  3. Use the default target handler and renderer for the customized object.
  4. Use the static function, IDMHandler::enableDropOn to enable the control as a drag target as shown in line 35 of the .CPP sample file that follows.
  5. Instantiate and set the drag item provider for for the control as shown in lines 40, 41, and 46 of the .CPP sample file below.
Note: When implementing a specialized drop target for a container, entry field, or MLE control, derive from that control-specific class instead of IDMItem.

The following example adds drop support to a bitmap control. The header file dmsamp2.hpp defines two classes, ABitmapItem and ABitmapProvider, and overrides the IDMItem::targetDrop and IDMItem::provideEnterSupport member functions in both classes, respectively.

1 #include <idmprov.hpp>  
2 #include <idmitem.hpp>  
3 #include <idmevent.hpp>  
4  
5 class ABitmapItem : public IDMItem {  
6 /****************************************************************************  
7 * Objects of this class provide "bitmap control" drop behavior when a       *  
8 * source bitmap file is dropped on a bitmap control properly configured     *  
9 * with a target handler and an ABitmapProvider.                             * 
10 ****************************************************************************/ 
11 public: 
12 /*------------------------------- Constructor ------------------------------- 
13 | Objects of this class are constructed from a generic item handle.         | 
14 ---------------------------------------------------------------------------*/ 
15   ABitmapItem ( const IDMItem::Handle &item ); 
16 
17 /*------------------------------ Drop Behavior ------------------------------ 
18 | targetDrop - Take the dropped file, create a PM bitmap object,            | 
19 |              and set it into the target window.                           | 
20 ---------------------------------------------------------------------------*/ 
21 virtual bool 
22   targetDrop ( IDMTargetDropEvent & ); 
23 }; 
24 
25 class ABitmapProvider : public IDMItemProviderFor< ABitmapItem > { 
26 /**************************************************************************** 
27 * Objects of this class are attached to bitmap controls in order to have    * 
28 * ABitmapItem objects created when a bitmap file is dropped on such a       * 
29 * control.                                                                  * 
30 ****************************************************************************/ 
31 public: 
32 /*------------------------------- Target Support ---------------------------- 
33 |provideEnterSupport - Verify that we're dealing with a bitmap object before| 
34 |                      allowing a drop, as well as draw the target emphasis.| 
35 |provideLeaveSupport - Remove the target emphasis.                          | 
36 |drawEmphasis        - Draw or remove the target emphasis.                  | 
37 ---------------------------------------------------------------------------*/ 
38 virtual bool 
39   provideEnterSupport ( IDMTargetEnterEvent& event ), 
40   provideLeaveSupport ( IDMTargetLeaveEvent& event ); 
41 
42 virtual ABitmapProvider 
43  &drawEmphasis        ( IBitmapControl*      bitmapControl, 
44                         IDMTargetEvent&      event, 
45                         bool              draw=true ); 
46 private: 
47 static bool 
48   bAlreadyDrawn; 
49 
50 };.

Lines 5 through 23 declare IDMItem as the base class for objects of a specialized class named ABitmapItem. Objects of this class provide bitmap control drop behavior when a source bitmap file is dropped on a bitmap control that is properly configured with a target handler and an ABitmapProvider.

Lines 25 through 50 define a drag item provider for a bitmap control and override IDMItemProvider::provideEnterSupport so that it verifies that the dragged object is a bitmap.

The .CPP file adds the drag item provider and the target handler, and it uses the default target renderer.

The following code continues this same example:

 21 int main()
 22 {
 23   ICoordinateSystem::setApplicationOrientation(
 24          ICoordinateSystem::originLowerLeft );
 25
 26   IResourceLibrary reslib;
 27
 28   /***********************************************************************/
 29   /* Create a generic frame window.                                      */
 30   /***********************************************************************/
 31   IFrameWindow
 32     frame ( reslib.loadString(WND_MAIN), WND_MAIN );
 33
 34   /***********************************************************************/
 35   /* Create an empty bitmap control.                                     */
 36   /***********************************************************************/
 37   IBitmapControl
 38     bmpControl ( 0, &frame, &frame );
 39
 40   /***********************************************************************/
 41   /* Create a target handler for the bitmap control and use default      */
 42   /* C Set++ UI renderers.                                               */
 43   /***********************************************************************/
 44   IDMHandler::enableDropOn( &bmpControl );
 45
 46   /***********************************************************************/
 47   /* Create bitmap drag item provider.                                   */
 48   /***********************************************************************/
 49   ABitmapProvider
 50     itemProvider;
 51
 52   /***********************************************************************/
 53   /* Attach provider to the bitmap control.                              */
 54   /***********************************************************************/
 55   bmpControl.setItemProvider( &itemProvider );
 56
 57   /***********************************************************************/
 58   /* Set the bitmap's control as the frame's client                      */
 59   /* and display the frame.                                              */
 60   /***********************************************************************/
 61   bmpControl.setText( "Drop .bmp files here." );
 62   bmpControl.setFocus();
 63
 64   frame.sizeTo( ISize( 400, 350 ) );
 65   frame.setIcon (frame.id() )
 66        .setClient( &bmpControl )
 67        .show();
 68   IApplication::current().run();
 69   return 0;
 70 }
 71
 72 /*-------------------------------------------------------------------------
 73 | ABitmapItem::ABitmapItem                                                |
 74 |                                                                         |
 75 | Constructor.                                                            |
 76 -------------------------------------------------------------------------*/
 77 ABitmapItem :: ABitmapItem ( const IDMItem::Handle& item )
 78   : IDMItem( item )
 79 {
 80 }
 81
 82 /*-------------------------------------------------------------------------
 83 | ABitmapItem::targetDrop                                                 |
 84 |                                                                         |
 85 | Take the dropped file, create a PM bitmap object,                       |
 86 | and set it into the target window.                                      |
 87 -------------------------------------------------------------------------*/
 88 bool ABitmapItem :: targetDrop ( IDMTargetDropEvent& event )
 89 {
 90   /*********************************************************************/
 91   /* Get pointer to the target bitmap control.                         */
 92   /*********************************************************************/
 93   IBitmapControl
 94    *bmpControl = (IBitmapControl *)targetOperation()->targetWindow();
 95
 96   /***********************************************************************/
 97   /* Turn off target emphasis.                                           */
 98   /***********************************************************************/
 99   ABitmapProvider
100    *provider = (ABitmapProvider *)bmpControl->itemProvider();
101   provider->drawEmphasis( bmpControl, event, false );
102
103   /***********************************************************************/
104   /* Construct dropped .BMP file name from this drag item and attempt to */
105   /* load the bitmap from a system file                                  */
106   /***********************************************************************/
107   IString
108     fname = containerName() + sourceName();
109   IGBitmap
110     bitMap( fname );
111
112   /***********************************************************************/
113   /* If bitmap was successfully loaded, then set it.  Note that the old  */
114   /* one will be automatically deleted.                                  */
115   /***********************************************************************/
116   if (bitMap.handle())
117   {
118     bmpControl->setBitmap( bitMap.handle() );
119
120     /********************************************************************/
121     /* Indicate name of dropped file.                                   */
122     /********************************************************************/
123     bmpControl->setText( fname );
124   }
125   else
126   {
127     bmpControl->setText( "Couldn't create bitmap!" );
128   }
129
130   return( true );
131 }
132
133 /*-------------------------------------------------------------------------
134 | ABitmapProvider::provideEnterSupport                                    |
135 |                                                                         |
136 | Verify that we're dealing with a bitmap object before                   |
137 | allowing a drop, as well as draw the target emphasis.                   |
138 -------------------------------------------------------------------------*/
139 bool ABitmapProvider :: provideEnterSupport ( IDMTargetEnterEvent& event )
140 {
141   /***********************************************************************/
142   /* Get handle to the drag target operation                             */
143   /***********************************************************************/
144   IDMTargetOperation::Handle targetOp = IDMTargetOperation::targetOperation();
145
146   /***********************************************************************/
147   /* Get pointer to the target bitmap control.                           */
148   /***********************************************************************/
149   IBitmapControl
150    *bmpControl = (IBitmapControl *)event.window();
151
152   /***********************************************************************/
153   /* Draw the target emphasis.                                           */
154   /***********************************************************************/
155   drawEmphasis( bmpControl, event );
156
157   /***********************************************************************/
158   /* Filter the types of items that we allow to be dropped.              */
159   /***********************************************************************/
160   IDMItem::Handle pTgtDIH = targetOp->item(1);
161   IString strTypes = pTgtDIH->types();
162
163   /***********************************************************************/
164   /* If type is either "Bitmap" or "Plain Text" (used by WPS), we can    */
165   /* display the drag item.  If type is "Plain Text", then filter based  */
166   /* upon the ".bmp" extension.                                          */
167   /***********************************************************************/
168   if (strTypes.indexOf( IDM::bitmap ))
169   {
170     return( true );
171   }
172   else
173   {
174     if ((strTypes.includes( IDM::plainText ))  &&
175         (pTgtDIH->sourceName().lowerCase().includes( ".bmp" )))
176     {
177       return( true );
178     }
179   }
180
181   /***********************************************************************/
182   /* Type is not recognized - set the drop indicator to prevent a drop!  */
183   /***********************************************************************/
184   event.setDropIndicator( IDM::neverOk );
185   return( false );
186 }
187
188 /*-------------------------------------------------------------------------
189 | ABitmapProvider::provideLeaveSupport                                    |
190 |                                                                         |
191 | Remove the target emphasis.                                             |
192 -------------------------------------------------------------------------*/
193 bool ABitmapProvider :: provideLeaveSupport (IDMTargetLeaveEvent& event)
194 {
195   /***********************************************************************/
196   /* Get pointer to the target bitmap control.                           */
197   /***********************************************************************/
198   IBitmapControl
199    *bmpControl = (IBitmapControl *)event.window();
200
201   /***********************************************************************/
202   /* Remove the target emphasis.                                         */
203   /***********************************************************************/
204   drawEmphasis( bmpControl, event, false );
205   return(true);
206 }
207
208 /*-------------------------------------------------------------------------
209 | ABitmapProvider::drawEmphasis                                           |
210 |                                                                         |
211 | Draw/remove the target emphasis                                         |
212 -------------------------------------------------------------------------*/
213 ABitmapProvider& ABitmapProvider::drawEmphasis ( IBitmapControl* bmpControl,
214                                                  IDMTargetEvent& event,
215                                                  bool bDraw )
216 {
217   /***********************************************************************/
218   /* Return if the request is to draw the emphasis, and its already      */
219   /* drawn.                                                              */
220   /***********************************************************************/
221   if (bDraw && bAlreadyDrawn)
222     return( *this );
223
224   if (bDraw)
225     bAlreadyDrawn = true;
226   else
227     bAlreadyDrawn = false;
228
229   /***********************************************************************/
230   /* Create the graphic context and set the mix mode to cause the pen    */
231   /* color to be the inverse of the drawing surface.  Also, set the draw */
232   /* operation, so that only the frame of the rectangle is drawn.        */
233   /***********************************************************************/
234   IGraphicContext
235     graphicContext( event.presSpace() );
236
237   graphicContext.setMixMode( IGraphicBundle::invert )                       
238                 .setDrawOperation( IGraphicBundle::frame );                  
239                                                                              
240   /***********************************************************************/ 
241   /* Define the points for the emphasis rectangle and adjust their       */  
242   /* position so the rectangle will fit within the control window.       */  
243   /***********************************************************************/  
244   IPoint                                                                     
245     origin  ( bmpControl->rect().left(),  bmpControl->rect().bottom() ),     
246     topRight( bmpControl->rect().width(), bmpControl->rect().height() );    
247                                                                             
248   origin -= 2;                                                              
249   topRight -= 4;                                                            
250                                                                             
251   /***********************************************************************/ 
252   /* Create an IRectangle object based upon the points defined and use   */ 
253   /* it to construct a 2-Dimensional rectangle object: IGRectangle.      */ 
254   /* Draw the emphasis rectangle using the IGRectangle object.           */ 
255   /***********************************************************************/  
256   IGRectangle                                                                
257     graphicRectangle( IRectangle( origin, topRight ) );                      
258                                                                              
259   graphicRectangle.drawOn( graphicContext );                                 
260                                                                             
261   /***********************************************************************/  
262   /* Release presentation space and return.                              */  
263   /***********************************************************************/  
264   event.releasePresSpace();                                                  
265   return( *this );                                                           
266 }

First, the .CPP file creates an empty bitmap control object, bmpControl, and then creates and attaches the handler, provider, and renderer.

Lines 37 and 38 create the bitmap control object.

Line 44 constructs a target handler, which creates a default target renderer.

Lines 49 and 50 construct a drag item provider, itemProvider.

Line 55 attaches the drag item provider to bmpControl window.

The rest of the .CPP file defines the overridden member functions, IDMItem::targetDrop and IDMItemProvider::provideEnterSupport, for the classes declared in the .HPP file.

Lines 88 through 131 define ABitmapItem::targetDrop. This member function gets the dropped file, creates the bitmap, and displays the bitmap in the target window.

Lines 139 through 186 define ABitmapProvider::provideEnterSupport. This member function verifies that the object over the target is a bitmap.

Note: This data type verification is in addition to the RMF checking that is done by the Open Class Library default target renderer. IDM::plainText is also verified. This data type is used by the shell for its background bitmaps.

If it is not a bitmap, the drop is not allowed.

Also, on line 155, provideEnterSupport requests the drawing of the target emphasis, which is a rectangle that is drawn just inside the outer edge of the target window. This member function is called when a target enter event (IDMTargetEnterEvent) occurs on a target window.

Lines 193 through 206 define ABitmapProvider::provideLeaveSupport. This member function requests removal of the target emphasis because the object is no longer over the target window. This member function is called when a target leave event (IDMTargetLeaveEvent) occurs on a target window.

Lines 213 through 266 define drawEmphasis. This member function has been added to the derived item provider class, ABitmapProvider, to draw and remove the target emphasis from the target window.

Note: When creating a graphic context, as shown on lines 234 and 235, you must use the presentation space obtained by calling IDMTargetEvent::presSpace. You cannot use the presentation space returned by IWindow::presSpace.

The rest of this function illustrates how to draw and remove the target emphasis using the graphic support classes.


Enabling a Control as a Drag Source

To enable other controls as drag sources, you must specifically create the drag items and item providers that the Open Class Library generates automatically for entry field, MLE, and container controls. You should do the following:

  1. Derive a class from the base class IDMItem, implement the generateSourceItems static member function, and override the following IDMItem constructors:
       IDMItem ( IDMSourceOperation* sourceOperation,
                 const IString&      types,
                 const unsigned long supportedOperations = unknown,
                 const unsigned long attributes = none);
     
       IDMItem ( const Handle&       item );
    

    The second constructor, the target item constructor, is required by the IDMItemProviderFor template whether it is used or not.

  2. Write a drag item provider class for the customized item class using the IDMItemProviderFor template class.
  3. Use the default source handler and renderer for the customized object.
  4. Use the static function, IDMHandler::enableDragFrom to enable the control as a drag source as shown in line 17 of the sample that follows.
  5. Instantiate and set the drag item provider for the control as shown in lines 21 and 22 of the sample that follows.
Note: When implementing a specialized drag source for a container, entry field, or MLE control, derive from that control-specific class instead of IDMItem.

The following example enables the user to drag objects from a static text control. This example is not included in the \samples\ioc directory.

The header file defines two classes, STextItem and MyWindow, and implements the IDMItem::generateSourceItems static member function.

 9 #include "static.h"
10
11 class STextItem : public IDMItem {
12 public:
13
14   STextItem ( IDMSourceOperation    *pSrcOp );
15   STextItem ( const IDMItem::Handle &item );
16
17 static bool
18   generateSourceItems ( IDMSourceOperation *pSrcOp );
19 };
20
21 class MyWindow : public IFrameWindow {
22 public:
23
24   MyWindow();
25   ~MyWindow();
26
27 private:
28   ITitle title;
29   ISetCanvas canvas;
30   IStaticText staticText;
31 };

The .CPP file adds the drag item provider and the source handler, and it
uses the default source renderer.

 3 int  main()
 4 {
 5   MyWindow myWin;
 6   IApplication::current().run();
 7 }
 8
 9 MyWindow :: MyWindow( )  :
10             IFrameWindow( ID_MYWINDOW ),
11             title( this, "Static Control" ),
12             canvas( ID_CANVAS, this, this ),
13             staticText( ID_STEXT, &canvas, &canvas )
14 {
15    setClient (&canvas);   //Set the canvas as the frame client.
16
17    IDMHandler::enableDragFrom (&staticText);//Enable the static text for dragging from
18
19    // Use the IDMItemProviderFor template class to create a template
20    // for the static text item, and set it into the window.
21    IDMItemProvider *pSTProvider = new IDMItemProviderFor< STextItem >;
22    staticText.setItemProvider (pSTProvider);
23
24    staticText.setText ("Static Text");  //Put text into the static text control.
25    setFocus ();                         // Set the keyboard focus and show it.
26    show ();
27 }
28
29 MyWindow :: ~MyWindow() {};
30 STextItem :: STextItem (IDMSourceOperation *pSrcOp)  :
31             IDMItem (pSrcOp,
32                       IDM::text,
33                       (IDMItem::moveable | IDMItem::copyable),
34                       none)
35 {
36    IStaticText *pSText = (IStaticText *)pSrcOp->sourceWindow(); //Get a pointer to the static text
37                                   // control from the source operation
38    setContents(pSText->text());   // Store the static text within the item
39    setRMFs(rmfFrom(IDM::rmLibrary, IDM::rfText));//Use the default RMF for text
40 }
41
42 STextItem :: STextItem (const IDMItem::Handle &item) :
43                          IDMItem ( item ) {};
44
45 bool STextItem :: generateSourceItems(IDMSourceOperation *pSrcOp)
46 {
47   STextItem *pSTItem = new STextItem (pSrcOp);   //Create the static text drag item
48   pSrcOp->addItem (pSTItem);                     //and add it to the source operation.
49
50   return(true);
51 }


First, the .CPP file creates a canvas and a static text control object,
staticText, and then creates and attaches the handler, provider, and renderer.
The renderer is automatically created and attached by the handler.

Line 13 creates the static text control object.

Line 17 constructs a target handler, which creates a default target
renderer.

Lines 21 and 22 construct a drag item provider, pSTProvider, and
attach the drag item provider to the static text window.

The rest of the .CPP file implements the static member function,
STextItem::generateSourceItems, and the source and target item
constructors.

Lines 30 through 40 define the source item constructor.

Lines 42 and 43 define the target item constructor, which is required by
the IDMItemProviderFor template whether it is used or not. Note that this
constructor can also be used to construct source items but requires additional
work as shown in the drag4 sample.

Lines 45 through 51 define generateSourceItems. This member function is
used to generate the source item.

Note: This sample is not included in the
\samples\ioc directory.




Enabling a Control as a Drag Source and a Drop Object


To enable other controls as a drag source and a drop
target, you must specifically create the drag items and item providers that the Open Class Library generates automatically for entry field, MLE, and container controls.

To enable a control as both a drag source and a drop object, follow the requirements in the following sections:


Note: Enable your control as a drag source and a drop target using the static
function, IDMHandler::enableDragDropFor.

Enabling a Control to Support a Shredder Object

On OS/2, when a user drops an object on a shell recycle bin or
shredder, two events are issued: a discard event and an end event. Do
the following to enable your control to support a shredder:

  1. Add the shredder RMF, IDM::discard, IDM::rfUnknown
    to the control's derived drag item. This normally occurs within the
    derived class's source item constructor.
  2. Override the IDMItem::sourceDiscard member function in the
    control's derived drag item to remove the object from the source window.
  3. Override the IDMItem::sourceEnd member function in the
    control's derived drag item, if needed, to perform any additional
    clean-up.

The shredder sets the drag operation to a value of
IDMOperation::move. To prevent confusion with an actual move
operation, you can set a flag in the control's derived drag item, from
within the sourceDiscard override, to clearly identify the discard operation.

Note: If a user drops multiple items on a shredder, the shell issues a discard and
an end event for each item.

Enabling a Control to Support an OS/2 Printer Object

When an object is dropped on a shell printer object, it issues two events: a print event and an end event. Do the following to enable any control to support a printer object:

  1. Add the print RMF, IDM::print, IDM::rfUnknown, to
    the control's derived drag item. This normally occurs within the derived
    class's source item constructor.
  2. Override the IDMItem::sourcePrint member function in the
    control's derived drag item to print the object.
  3. Override the IDMItem::sourceEnd member function in the
    control's derived drag item, if needed, to perform any additional
    clean-up.

The shell print object does not modify the default drag operation. However,
you can set a flag in the control's derived drag item, from within the sourcePrint override, to clearly identify the print operation.

You need to implement the rest of the print logic.

Note: If a user drops multiple items on a print object, the shell issues a print
and an end event for each item.

Enabling a Control for File Support

Target Support

On OS/2, when a drag is started on an object that represents a text file,
the following information is placed in the underlying drag items:

The default target renderer provides support for the file rendering mechanism and text format. To enable a control for file support, do the following:

  1. Override IDMItemProvider::provideEnterSupport in the derived
    drag item provider class to perform drag item type verification if required.
  2. Override IDMItem::targetDrop in the derived drag item class.
  3. Obtain the file's drive and path information in the IDMItem::targetDrop override by calling the IDMItem::containerName member function.
  4. Obtain the file name in the IDMItem::targetDrop override by calling the IDMItem::sourceName member function.
  5. Perform desired processing on the file.

An example of file support is shown in the drag2 sample. Note that the dragging of a file, as shown in drag2, is supported on OS/2 only.

Source Support--Target File Rendering

To enable a control as a file source, the shell places the following requirements upon the drag item objects:

Do the following to implement source file support to allow the shell to do target rendering:

  1. In the source drag item constructor of the derived drag item class, either add or set an item type of IDM::plainText using IDMItem::addType or IDMItem::setTypes, respectively.
  2. Also, either add or set the file rendering mechanism and text format, <IDM::rmFile,IDM::rfText>, using IDMItem::addRMF or IDMItem::setRMFs, respectively.
  3. Set the source drive and path using IDMItem::setContainerName.
  4. Set the source file name using IDMItem::setSourceName.
  5. Set the suggested target file name using IDMItem::setTargetName.

These steps build the information that the shell requires to do target rendering. Create the file without further intervention from the source of the drag operation.

Source Support--Delayed or Source File Rendering

If it is not desirable to use target rendering to create the file, you can use what is known as delayed or source file rendering.

For example, you could use delayed file rendering when the file you are dragging requires dynamic modifications. By delaying the file's creation at the target, you have the opportunity to make the dynamic modifications.

Do the following to implement source file support for delayed file rendering.

Note: When the container name is set to 0, which is the default, the shell selects the delayed file rendering mechanism.
  1. In the source drag item constructor of the derived drag item class, either add or set an item type of IDM::plainText using IDMItem::addType or IDMItem::setTypes, respectively.
  2. Also, either add or set the file rendering mechanism and text format, <IDM::rmFile,IDM::rfText>, using IDMItem::addRMF or IDMItem::setRMFs, respectively.
  3. Set the source file name using IDMItem::setSourceName.
  4. Set the suggested target file name using IDMItem::setTargetName.
  5. Override IDMItem::sourceRender in the derived drag item class.
    1. Perform desired processing on the file in the override.
    2. Call IDMRenderEvent::setCompletion to set the render completion code in the override.
    3. Return from the override.



Direct Manipulation


Using Default Direct Manipulation
Adding Images to Drag Items


IDMCnrItem
IDMHandler
IDMItem
IDMItemProvider
IDMItemProviderFor
IDMSourceDiscardEvent
IDMSourceOperation
IDMTargetDropEvent
IDMTargetEvent