home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgthr.zip / drgthrnd.doc < prev    next >
Text File  |  1993-07-27  |  12KB  |  240 lines

  1. DRGTHRND.EXE (DRaG THread ReNDering) is a sample program that demonstrates
  2. OS/2's Drag/Drop facilities (aka Direct Manipulation). It implements source
  3. rendering after the drop. This sample does its rendering in secondary threads
  4. so as not to hold up the User Interface. If you are looking for something a
  5. little simpler that is single-threaded, try and find my DRGRENDR.EXE sample. It
  6. also implements rendering and is exactly like this program except for the
  7. additional threads.
  8.  
  9. DRGTHRND creates 2 frame windows with containers as their client windows. One
  10. of the windows plays the role of a 'drag' window, the other plays the role of a
  11. 'drop' window. Their roles are not interchangeable, not because it was a problem
  12. to program, rather because the roles of the dragger (called the source window)
  13. and the droppee (called the target window) are 2 different ones and it is
  14. easier to understand their roles if they cannot mix.
  15.  
  16. The reason that containers are used is not to make the program more complex. On
  17. the contrary, containers make Drag/Drop easier to program because the app does
  18. not have to draw representations of things that can be dragged and dropped. The
  19. container provides simple facilities to place draggable icons into its window.
  20. Listboxes were considered but containers are visually easier to understand.
  21.  
  22. NOTE THAT THE TOOLKIT HAS A DRAG/DROP SAMPLE CALLED 'DRAGDROP' THAT IS A VERY
  23. GOOD DRAG/DROP SAMPLE PROGRAM.
  24.  
  25. To run this sample program, type DRGTHRND on the command line. The 2 windows
  26. will appear on the bottom of your display. The left-hand container is the 'drag'
  27. container, the right one is the 'drop' container. Drag one or more icons from
  28. the 'drag' container to the 'drop' container. Then double-click on any of the
  29. icons that are created in the 'drop' container. A listbox window will be
  30. displayed that lists the contents of a 'database table'.
  31.  
  32. This is what happens on the drag/drop:
  33.  
  34. First, there are 2 files that are in the .zip file that represent a database of
  35. sorts (a very simple representation). The files are named dbase_?.db. Have a
  36. look at one of them. Here is part of dbase_1.db:
  37.  
  38. TABLEKEY=>table_1
  39. This is row 1 for the table_1 table in dbase_1
  40. This is row 2 for the table_1 table in dbase_1
  41. This is row 3 for the table_1 table in dbase_1
  42. This is row 4 for the table_1 table in dbase_1
  43. This is row 5 for the table_1 table in dbase_1
  44. TABLEKEY=>table_2
  45. This is row 1 for the table_2 table in dbase_1
  46. This is row 2 for the table_2 table in dbase_1
  47. This is row 3 for the table_2 table in dbase_1
  48. This is row 4 for the table_2 table in dbase_1
  49. This is row 5 for the table_2 table in dbase_1
  50. TABLEKEY=>end_of_database
  51.  
  52.  
  53. DRGTHRND scans all dbase_?.db files at startup. Every time it finds a
  54. TABLEKEY=> record, it creates an icon in the 'drag' container that represents
  55. the table whose name follows the TABLEKEY=> literal. When it encounters an
  56. 'end_of_databse' record it assumes end-of-file. So the simulation here is of
  57. multiple databases each with multiple tables. The text under each icon is
  58. created by concatenating the database name with the table name. For instance,
  59. the table_2 table in the dbase_1.db file would be represented by an icon with
  60. 'dbase_1:table_2' as its text.
  61.  
  62. When you drag an icon from the 'drag' container (hereafter referred to as the
  63. 'source' window) to the 'drop' container ('target' window) and drop it,
  64. rendering takes place. This rendering causes the source window to copy the rows
  65. from the specified table to a file whose name was provided by the target. When
  66. the source indicates that the rendering is complete, the target inserts an icon
  67. into its container that now represents that file. Double-clicking on an icon in
  68. the 'drop' window will bring up a listbox that displays the contents of the
  69. file.
  70.  
  71. This is meant to simulate a real-world scenario where the source represents its
  72. contents by icons and its contents are really in a database that most targets
  73. would not be able to read on their own (i.e. they don't know the format, don't
  74. know SQL, etc.)
  75.  
  76. Here is the message flow once the user has begun to drag an icon from the
  77. source window:
  78.  
  79.     SOURCE                                    TARGET
  80.     ──────                                    ──────
  81.  
  82.     CN_INITDRAG .............................
  83.     ......................................... CN_DRAGOVER
  84.     ......................................... CN_DROP (send DM_RENDERPREPARE)
  85.     DM_RENDERPREPARE ........................
  86.     ......................................... CN_DROP (send DM_RENDER to source)
  87.     DM_RENDER ...............................
  88.     (do the rendering) ......................
  89.     (send DM_RENDERCOMPLETE to target)....... DM_RENDERCOMPLETE
  90.                                                 (send DM_ENDCONVERSATION to src)
  91.     DM_ENDCONVERSATION.......................
  92.  
  93.  
  94. To show the thread interaction, this is a further breakdown:
  95.  
  96.         MAIN THREAD
  97.         ───────────                        SOURCE RENDER       TARGET RENDER
  98. SOURCE               TARGET                    THREAD              THREAD
  99. ──────               ──────                ─────────────       ─────────────
  100.  
  101. CN_INITDRAG ........
  102. .................... CN_DRAGOVER
  103. .................... CN_DROP .... (start thread) ............... CN_DROP
  104. DM_RENDERPREPARE ................ (start thread) ....
  105.                                            DM_RENDER
  106.                                                                DM_RENDERCOMPLETE
  107.                                            DM_ENDCONVERSATION
  108.  
  109. This is basically it. Of course it is more complicated than this in real life
  110. as problems can happen in any of these steps that alter the flow of control.
  111.  
  112. Note that until DM_RENDER time, everything is done as a group of items, i.e.
  113. all DRAGITEM's are lumped together with a DRAGINFO structure and the DRAGINFO
  114. structure is passed with the messages. When the target gets the CN_DROP, at that
  115. point all messages are on an individual DRAGITEM basis. If the user is only
  116. dragging one icon, there is no difference. With multiple icons this really
  117. comes into play.
  118.  
  119. Note also that the CN_ messages are WM_CONTROL messages sent by the container
  120. to its owner when it gets the normal PM messages. The reason for this is so that
  121. the container can provide its owner with more information than it would normally
  122. get with the regular PM messages. The mapping goes like this:
  123.  
  124.   PM message (container gets this)       Message sent by container to owner
  125.   ────────────────────────────────       ──────────────────────────────────
  126.  
  127.   WM_BEGINDRAG ......................... CN_INITDRAG
  128.   DM_DRAGOVER .......................... CN_DRAGOVER
  129.   DM_DROP .............................. CN_DROP
  130.  
  131. The ValueSet control also provides this type of interface to its owner.
  132. Obviously if your program just uses a normal client window you would use the
  133. messages on the left-hand side.
  134.  
  135. THE MOST IMPORTANT THING that you need to know about Drag/Drop is that the
  136. information passed between the source and target is in shared memory so it has
  137. to be freed by both sides when they are done with it. Since you don't allocate
  138. the shared memory (PMDRAG.DLL does), it is more difficult to think in terms of
  139. freeing it. The memory that has to be freed is the DRAGINFO structure and all
  140. the string handles in it and its attached DRAGITEM structures, and any
  141. DRAGTRANSFER structures that were used (during rendering) and their string
  142. handles.
  143.  
  144. You use DrgFreeDraginfo() to free the DRAGINFO structure and
  145. DrgFreeDragtransfer() to free the DRAGTRANSFER structures. The DRAGINFO
  146. structure is allocated by the source when it starts the drag (using the
  147. DrgAllocDraginfo() API), and PM takes care of disbursing this memory to
  148. processes that need it when they call DrgAccessDraginfo(). The DRAGTRANSFER
  149. structures are allocated by the target (using the DrgAllocDragtransfer() API)
  150. when drop processing starts. Whenever it communicates with the source, it uses
  151. DrgSend/PostTransferMsg() API's that cause PM to give their process access to
  152. the DRAGTRANSFER structure.
  153.  
  154. Here are the documented times for freeing these structures when rendering is
  155. involved (as in this sample program):
  156.  
  157. SOURCE
  158. ──────
  159.  
  160. If DrgDrag() returns NULLHANDLE (which it will if the user hits F1 or Esc during
  161. the drop so that there is no target window), it should make the following calls:
  162.  
  163.     DrgDeleteDraginfoStrHandles();
  164.     DrgFreeDragInfo();
  165.  
  166. DrgDeleteDraginfoStrHandles() deletes all the string handles in all the
  167. DRAGITEMs associated with the DRAGINFO structure. DrgFreeDraginfo() frees the
  168. DRAGINFO structure.
  169.  
  170. If DrgDrag() doesn't return NULLHANDLE, that means a drop occurred and the
  171. return value is the target's window handle. In this case, it is the target's
  172. responsibility to delete the string handles but the source needs to free the
  173. DRAGINFO structure and the DRAGTRANSFER structures. Here's what it should do:
  174.  
  175.   When the source is done rendering, it posts the DM_RENDERCOMPLETE message to
  176.   the target. After it posts this message it needs to call DrgFreeDragtransfer()
  177.   for the DRAGITEM that it just rendered.
  178.  
  179.   Under DM_ENDCONVERSATION, when the DM_ENDCONVERSATION for the *last* DRAGITEM
  180.   comes thru, the source needs to call DrgFreeDraginfo(). Keep in mind that
  181.   this means a global counter must be used (or store it in a window word like
  182.   this program does) so it can keep track of when the last one comes thru.
  183.  
  184.  
  185. TARGET
  186. ──────
  187.  
  188. If rendering does not take place for some reason, the target needs to make the
  189. following calls under the CN_DROP (or DM_DROP if not a container owner) message:
  190.  
  191.     DrgDeleteDraginfoStrHandles();
  192.     DrgFreeDraginfo();
  193.  
  194. If rendering does take place:
  195.  
  196.   After the target completes processing the DM_RENDERCOMPLETE message it will
  197.   send the source a DM_ENDCONVERSATION message. At this point it should call
  198.   DrgFreeDragtransfer() for the DRAGITEM that it just processed. It must also
  199.   call DrgDeleteStrHandle() for all HSTR's in the DRAGTRANSFER structure. These
  200.   would normally be DRAGTRANSFER.hstrSelectedRMF and
  201.   DRAGTRANSFER.hstrRenderToName.
  202.  
  203.   If the last DRAGITEM is being processed (also must be implemented with a
  204.   counter), DrgDeleteDraginfoStrHandles() and DrgFreeDraginfo() must be called.
  205.  
  206.  
  207. DRGTHRND frees these structures when the documentation recommends freeing them
  208. (as illustrated above). Unfortunately the documentation isn't real clear on
  209. this and you have to search to find it. REMEMBER THAT IF YOUR APPLICATION DOES
  210. NOT FREE THESE STRUCTURES WHEN IT IS SUPPOSED TO THAT YOUR APP COULD SCREW UP
  211. OTHER APPS IF IT ALLOWS DIRECT MANIPULATION TO OCCUR WITH OTHER APPS. This is
  212. an important thing to note. If direct manipulation is not done properly it
  213. could lead to a PM resource leak because shared memory might never be freed
  214. that should be freed.
  215.  
  216.  
  217. DRGTHRND.EXE is built from 5 source modules:
  218.  
  219. DRGTHRND.C - base code that creates all windows and contains the window procs
  220. DBACCESS.C - functions that access the 'databases'
  221. DRAG.C     - contains the main-thread basic Drag/Drop related code.
  222. SRCRENDR.C - contains the secondary-thread rendering code for the source window.
  223. TRGRENDR.C - contains the secondary-thread rendering code for the target window.
  224.  
  225. Hope this sample program helps someone.
  226.  
  227. ===============================================================================
  228. GLOBAL HISTORY
  229.  
  230. 7-19-93 - Completed coding.
  231.  
  232. ===============================================================================
  233.  
  234. Rick Fishman
  235. Code Blazers, Inc.
  236. 4113 Apricot
  237. Irvine, CA 92720
  238.  
  239. CIS ID: 72251,750
  240.