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.
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:
IDMItem ( const Handle& item );
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.
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:
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.
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. |
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. |
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:
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. |
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:
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. |
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:
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:
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. |
Using Default Direct
Manipulation
Adding Images to Drag
Items
IDMCnrItem
IDMHandler
IDMItem
IDMItemProvider
IDMItemProviderFor
IDMSourceDiscardEvent
IDMSourceOperation
IDMTargetDropEvent
IDMTargetEvent