home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgwps.zip / drgpmwps.doc < prev    next >
Text File  |  1993-08-03  |  10KB  |  180 lines

  1. DRGPMWPS.EXE is a sample program that demonstrates a mechanism for allowing
  2. OS/2 Drag/Drop facilities (aka Direct Manipulation) to work between a normal
  3. PM window and the WorkPlace Shell. Normally only WPS objects descended from the
  4. WPFileSystem class (any objects that are 'Drives-folder descendents') are able
  5. to convey enough information to normal PM programs to make Drag/Drop work
  6. correctly. This sample program shows a way around that limitation. It is by no
  7. means meant as the definitive way around this problem.
  8.  
  9. First, what are the reasons why the other WPS objects don't communicate well
  10. with normal PM programs during Drag/Drop?
  11.  
  12. Let's take the simplest example: Using the DRM_OS2FILE Rendering mechanism,
  13. Drag/Drop is brought down to the level of filenames. If an item is being dropped
  14. on a PM window, that PM window can look at the DRAGITEM structure provided on
  15. the drop and get the filename of the file being dropped. That's all it needs to
  16. complete the drop in most cases. If you drag a file from a WPFileSystem folder
  17. (let's say the config.sys icon from the C:\ folder opened from the Drives
  18. folder), and drop it onto a PM window, that PM window will be able to get
  19. C:\CONFIG.SYS as the file that's being dropped. That's what it would want.
  20.  
  21. Now let's say you are dragging a Program Object (a WPS object descended from the
  22. WPProgram class). Let's say the Program Object represents the Lotus Freelance
  23. program (FLG.EXE) which is located in the C:\LOTUS directory. You would expect
  24. to be able to get the C:\LOTUS\FLG.EXE information when the program was dropped
  25. on your PM window, right? Wrong. The directory path for a Program Object is
  26. considered to be in the folder that contains it. The folder's location is in
  27. relation to d:\Desktop where d: is your boot drive. So if your Program Object is
  28. in the 'OS2Programs' folder and the Program title (the text under the icon) is
  29. 'Lotus Freelance', the only directory information that you could get
  30. about the program would be 'd:\Desktop\OS2Programs\Lotus Freelance'. This
  31. doesn't do much for a normal PM program which needs access to the
  32. 'C:\LOTUS\FLG.EXE' information.
  33.  
  34. So, how do you get that information? In the DRAGITEM structure associated with
  35. an object being dragged is a field called ulItemID. That field is meant to
  36. contain application-specific information. If a WPS object initiates the drag,
  37. it places in ulItemID a pointer that is useful only to WPS objects. A normal PM
  38. program cannot not do anything with that pointer because the memory that it
  39. points to was allocated in the WPS process itself and it is not shared memory.
  40. A WPS program can use ulItemID to get all kinds of information about the object
  41. being dragged. If you've used containers, you know that a container record is
  42. represented by a MINIRECORDCORE structure. The ulItemID field contains a
  43. pointer to the MINIRECORDCORE structure of the Program Object within the folder
  44. (the folder is a container). The MINIRECORDCORE address in the ulItemID field
  45. is an address in memory that is right after some other information that is used
  46. by the WPS. One piece of information stored here is a 'SOMAny' pointer that is
  47. a pointer to a SOM object. To get that information from the ulItemID pointer, a
  48. macro is used called OBJECT_FROM_PREC. So you would do this:
  49.  
  50.     SOMAny *somObject = OBJECT_FROM_PREC( pDragItem->ulItemID );
  51.  
  52. This macro subtracts a value from ulItemID (effectively stepping backwards
  53. through memory) in order to obtain the SOMAny pointer. In other words, if the
  54. SOMAny pointer is right before the MINIRECORDCORE structure in memory (which I
  55. don't think it is), this is something like how the memory would look:
  56.  
  57.      ADDRESS  Value
  58.  
  59.      00000005 SOMAny pointer
  60.      00000008 PMINIRECORDCORE structure pointer  (ulItemID)
  61.  
  62. The OBJECT_FROM_PREC macro would subtract 4 from ulItemID to get the SOMAny
  63. pointer. This is assuming it is directly before the PMINIRECORDCORE. I traced it
  64. at one time but I forget what the actual layout is.
  65.  
  66. <In actuality, it differs slightly from this but I think you get the point>
  67.  
  68. Anyway, once you get the SOMAny pointer, you have a pointer to the Program
  69. Object and you can use this to do all sorts of things, including getting
  70. information about the object.
  71.  
  72. The way you know that ulItemID contains such a pointer is that the Rendering
  73. Mechanism used in the drag is DRM_OBJECT which is exclusively used by WPS
  74. objects. Since ulItemID is really an application-defined field, you obviously
  75. don't want to assume that every ulItemID that is dropped contains that value.
  76.  
  77. So at this point, if I haven't totally confused you, you should be seeing why
  78. a regular PM program can't access the information. If it got the PDRAGITEM
  79. pointer and did an OBJECT_FROM_PREC( pDragItem->ulItemID ) and tried to do
  80. anything with the pointer returned, it would trap because that address is not
  81. in its address space.
  82.  
  83. DRGPMWPS uses a mechanism to try and circumvent this. It creates a WPS 'agent'
  84. object which is a full-fledged, albeit simple, WPS object. That object lives
  85. in drgagent.dll. When DRGPMWPS.EXE comes up, it registers the DrgAgent class
  86. (which loads drgagent.dll) and creates an object of that class. This object will
  87. be an 'agent' for the normal PM window created by DRGPMWPS.EXE. Whenever the PM
  88. window needs information about an object being dropped on it, it will ask
  89. DrgAgent to help translate. All DRGPMWPS needs to pass DrgAgent is
  90. pDragItem->ulItemID. When DrgAgent gets a UM_DRAGINFO_REQUEST message with this
  91. ulItemID and the requesting window handle, it uses SOM/WPS methods to obtain
  92. the information, copies the information to a suballocated shared memory chunk
  93. and posts a UM_DRAGINFO message to the requesting window with that chunk.
  94.  
  95. Of course getting the communication going between the PM window and the WPS
  96. object is not a simple task. This sample program uses a shared memory heap and
  97. window messages. DrgAgent creates an object window whose window handle is made
  98. available to the PM window via shared memory. When the PM window wants to pass
  99. data to the WPS object or vice-versa, a chunk of memory is allocated from a
  100. shared heap and its pointer is passed via a PM message to the other window.
  101.  
  102. Here is the conversation that happens when a WPS object is being dragged and
  103. dropped on the PM window.
  104.  
  105.     PM Window                                 WPS object (DrgAgent)
  106.     ─────────                                 ─────────────────────
  107.  
  108.  1) DM_DRAGOVER (allow the drop)
  109.  2) DM_DROP (send the UM_DRAGINFO_REQUEST)
  110.                                            3) UM_DRAGINFO_REQUEST
  111.                                                 get the info
  112.                                                 post the results to requestor
  113.                                                    with the UM_DRAGINFO message
  114.  4) UM_DRAGINFO (contains the data)
  115.  
  116.  
  117.  
  118. This sample program also attempts to show Drag/Drop working the other way (PM
  119. Window initiates the drag and an icon is dropped on a WPS object). If the WPS
  120. object is a WPProgram object, that WPProgram object's icon is changed to the
  121. one that was dropped on it. Kinda cute. It uses other WPS methods to accomplish
  122. this. Basically this is how it works:
  123.  
  124. When the PM window initiates a drag, it has DrgAgent format the DRAGITEM
  125. structure so that it puts in ulItemID the MINIRECORDCORE pointer for the
  126. DrgAgent object. When WPProgram objects get a DM_DRAGOVER message, they see
  127. that the DRM_OBJECT Rendering Mechanism is being used and they use ulItemID to
  128. get the somObject pointer for DrgAgent and call DrgAgent's wpDraggedOverObject
  129. method. When the item is dropped on the object, it calls DrgAgent's
  130. wpDroppedOnObject method. Therefore, DrgAgent then has enough information about
  131. the dropped-on object (the dropped-on object's somObject pointer is passed to
  132. the method) to get an HOBJECT pointer which it passes to the PM window which
  133. does a WinSetObjectData to set the object's icon to the one that was dropped.
  134.  
  135. Whew!
  136.  
  137. There are problems if you try to drop onto a folder rather than a program. The
  138. WPFolder object doesn't do the wpDraggedOverObject and wpDroppedOnObject stuff
  139. so instead it copies the DrgAgent object into the folder. A better way to
  140. implement this would have been to do a WinReplaceObjectClass of the WPFolder
  141. class and override its wpDrop method, but alas this is just a sample program
  142. and that would have caused you to have to 'install' the replacement class - a
  143. little bit much for a sample program.
  144.  
  145. The DRGPMWPS sample is both DRGPMWPS.EXE and DRGAGENT.DLL. There are 6 .c
  146. programs that comprise this sample:
  147.  
  148. DRGPMWPS.C - base code that creates the PM container window.
  149. DRGAGENT.C - generated by the SOM emitter from DRGAGENT.CSC. Contains the
  150.              code for the overridden WPS methods used by the DrgAgent object
  151.              class.
  152. DRAG.C     - contains all Drag/Drop related code.
  153. COMMDATA.C - contains the code used to create and handle the shared memory that
  154.              contains the common variables between the PM window and the
  155.              DrgAgent object window.
  156. HEAP.C     - contains the code used to implement the shared heap used by both
  157.              the PM window and the DrgAgent object window.
  158. COMMWIN.C  - contains the code used to implement DrgAgent's object window.
  159.  
  160. Note that this sample is a little lacking in comments. It would help to be a
  161. little familiar with SOM/WPS. If not, it may help you get into it a little. I
  162. basically ran out of time. This sammple was going to be very elaborate at one
  163. time...
  164.  
  165. Hope this sample program helps someone.
  166.  
  167. ===============================================================================
  168. GLOBAL HISTORY
  169.  
  170. 8-02-93 - Completed coding.
  171.  
  172. ===============================================================================
  173.  
  174. Rick Fishman
  175. Code Blazers, Inc.
  176. 4113 Apricot
  177. Irvine, CA 92720
  178.  
  179. CIS ID: 72251,750
  180.