home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / EDMI5.ZIP / CNR2.ZIP / CNR2.IPF < prev    next >
Text File  |  1993-06-18  |  10KB  |  182 lines

  1. :h2.Programming the Container Control (Part II)
  2. :p.Written by Larry Salomon, Jr.
  3. :h3.Where were we?
  4. :p.Last month I briefly introduced (in that oh-so-poor writing style that
  5. makes me unique) the container control and some of the programming basics
  6. that everyone should know.  This month, we will continue this trek into the
  7. unknown by describing the :hp2.tree:ehp2. view as well as some other nifty
  8. things.  Also, we will write our first application using the container, on
  9. which we will build in next month&apos.s installment.
  10. :p.:hp2.From Another Viewpoint:ehp2.
  11. :p.As a quick note, the :hp2.name:ehp2. and :hp2.text:ehp2. views were omitted
  12. last month because they are - from a programmer&apos.s perspective - identical
  13. to the icon view.
  14. :h3.The Wood Nymph&apos.s Delight
  15. :p.The :hp2.tree:ehp2. view should be a highly familiar one; it parallels
  16. nicely with the directory structure of a hard disk and has been used in the
  17. File Manager (from OS/2 1.x) and the Help Manager as well as many other
  18. applications.  It also has three subviews that can be specified in the
  19. :hp2.CM_SETCNRINFO:ehp2. message&colon.  tree :hp2.icon:ehp2. view, tree
  20. :hp2.name:ehp2. view, and tree :hp2.text:ehp2. view (these are specified by
  21. &odq.or-ing&cdq. the CV_ICON, CV_NAME, or CV_TEXT flags with the CV_TREE flag
  22. in the :hp1.flWindowAttr:ehp1. field, respectively).  The difference between
  23. these views is in the way the data is represented&colon.  icon view displays
  24. an icon with the text to the right and to the left is a separate bitmap
  25. indicating whether the item is expanded or collapsed (if applicable); name
  26. view is the same as icon view except that the expanded/collapsed indicator is
  27. indicated in the icon; the text view provides only the text string with the
  28. expanded/collapsed indicator as a separate bitmap to the left.
  29. :p.Note the difference between icon and name view.  Remember when, in the
  30. beginning of the series, it was mentioned that there are a few differences
  31. between using the :hp2.MINIRECORDCORE:ehp2. and :hp2.RECORDCORE:ehp2.
  32. structure?  This is one of those differences; since only the
  33. :hp2.RECORDCORE:ehp2. structure has different fields for the expanded and
  34. collapsed icons, the name view cannot be used with the
  35. :hp2.CCS_MINIRECORDCORE:ehp2. style.
  36. :p.When inserting records into the container, the parent record is specified
  37. in the :hp1.pRecordParent:ehp1. field of the :hp2.RECORDINSERT:ehp2.
  38. structure.  In the icon view, we specified this as :hp2.NULL:ehp2., since
  39. there is not parent/child relationships in that view.  However, in the tree
  40. views, this is particularly important because it specifies how the records are
  41. to be displayed.  All records that have children will be displayed by adding
  42. an expanded/collapsed indicator to its left.  If, by some action of the user,
  43. you switch to any other non-tree view, all but the top-level records are
  44. hidden.
  45. :p.:hp2.Notifications:ehp2.
  46. :p.In addition to the &odq.normal&cdq. notifications, the container provides 2
  47. notifications specific to the tree view&colon.
  48. :dl tsize=20 break=fit.
  49. :dt.CN_COLLAPSETREE
  50. :dd.This is sent to the owner after the container collapses a subtree.
  51. :hp1.mpParm2:ehp1. points to the record that was collapsed.
  52. :dt.CN_EXPANDTREE
  53. :dd.This is sent to the owner after the container expands a subtree.
  54. :hp1.mpParm2:ehp1. points to the record that was expanded.
  55. :edl.
  56. :h3.CNR2 - A Sample Application
  57. :p.Now let us delve into the depths of our first sample application; it not
  58. only showcases the container control, but it also contains some nifty tricks
  59. that I think you&apos.ll find useful.  The structure is that of a
  60. &odq.typical&cdq. PM application and it should not be new to you.  In the
  61. code, I have placed several &odq.landmarks&cdq.; these are marked by placing a
  62. comment of the form &odq.@n&cdq. (where &osq.n&csq. is the landmark number)
  63. starting at column 55.  These landmarks are used to point out things of
  64. interest and are discussed in more detail later.
  65. :p.The application does nothing more than add a record for each month of each
  66. year for the number of years specified in :hp2.NUM_YEARS:ehp2..  This is to
  67. show how the tree view is used.  A popup menu is displayed whenever the system
  68. key/mouse sequence is pressed, allowing to you switch between icon and tree
  69. views, etc.
  70. :p.:hp2.Landmark 1:ehp2.
  71. :p.This is simply to point out the typedefs used.
  72. :font facename=Courier size=14x14.
  73. :xmp.
  74. typedef struct _CLIENTDATA &lbrc.                          // @1
  75.    USHORT usSzStruct;         // Size of the structure
  76.    HAB habAnchor;             // Anchor block of the window
  77.    HWND hwndFrame;            // Frame of the client (== parent)
  78.    HWND hwndCnr;              // Container window
  79.    HPOINTER hptrYear;         // Icon for the year records
  80.    HPOINTER hptrMonth;        // Icon for the month records
  81.    HWND hwndWndMenu;          // Menu window
  82. &rbrc. CLIENTDATA, *PCLIENTDATA;
  83.  
  84. typedef struct _MYCNRREC &lbrc.
  85.    MINIRECORDCORE mrcCore;    // Base structure
  86.    CHAR achText&lbrk.64&rbrk.;          // Icon text
  87. &rbrc. MYCNRREC, *PMYCNRREC;
  88.  
  89. //-------------------------------------------------------------------------
  90. // PFNSRCH is used by searchCnr().  The parameters are:  container window
  91. // handle, record pointer, and user-data pointer, respectively.
  92. //-------------------------------------------------------------------------
  93. typedef BOOL (*PFNSRCH)(HWND,PVOID,PVOID);
  94. :exmp.
  95. :font facename=default.
  96. :p.:hp2.CLIENTDATA:ehp2. is the instance data for the client window.  Granted,
  97. we could have used global variables, but that is poor programming practice so
  98. we avoid doing this (the only global we use is an constant array of pointers
  99. to the names of the months).
  100. :p.:hp2.MYCNRREC:ehp2. is the definition for the container records.  Note that
  101. we are using the :hp2.MINIRECORDCORE:ehp2. structure.
  102. :p.:hp2.PFNSRCH:ehp2. is a pointer to a function accepting three parameters
  103. and returning a boolean.  It is used in a very interesting way that
  104. you&apos.ll see later.
  105. :p.:hp2.Landmark 2:ehp2.
  106. :p.This is only to point out that while it is highly recommended that you
  107. allocate and insert as many records as possible each time sometimes it simply
  108. isn&apos.t possible.  We :hp2.have:ehp2. to allocate/insert each year
  109. separately followed by the twelve months.
  110. :p.:hp2.Landmark 3:ehp2.
  111. :p.Since we specified :hp2.FALSE:ehp2. in the :hp1.fInvalidateRecord:ehp1.
  112. field of the :hp2.RECORDINSERT:ehp2. structure, we have to send a
  113. :hp2.CM_INVALIDATERECORD:ehp2. message to update the container.
  114. :p.:hp2.Landmark 4:ehp2.
  115. :p.This entire procedure is useful, since (as described in a previous issue of
  116. the magazine) you cannot specify :hp2.MIS_CONDITIONALCASCADE:ehp2. in a
  117. resource file.  It should also be noted that since the cascade button takes up
  118. a bit more space, it is helpful to add a few blank spaces in the menu template
  119. to account for this.  As a general rule, I use three blanks.
  120. :p.:hp2.Landmark 5:ehp2.
  121. :p.Here is another useful procedure; it performs a recursive, post-traversal
  122. search of the container, calling a user-specified procedure at each record to
  123. see if it matches the criteria also specified by the caller.  If you&apos.ve
  124. ever wondered what a use for reserved parameter is, here is one.  We use the
  125. reserved parameter to specify the record we are currently checking; by having
  126. the user specify :hp2.NULL:ehp2., we can check to see if this is the initial
  127. call.
  128. :p.Of course, we could have eliminated the reserved parameter and had this
  129. procedure call another procedure with a reserved parameter to remove the
  130. burden from the caller, but that&apos.s too easy.  (* grin *)
  131. :p.:hp2.Landmark 6:ehp2.
  132. :p.This is to point out the allocation and initialization of the client
  133. instance data.  Note that the cleanup is done in the :hp2.WM_DESTROY:ehp2.
  134. processing.
  135. :p.:hp2.Landmark 7:ehp2.
  136. :p.This is to show a bug in the container - if the user uses the mouse to
  137. invoke the popup menu, the container sends us a :hp2.WM_CONTROL:ehp2. message.
  138. Not so if the user uses the keyboard, thus we duplicate the code and check for
  139. the :hp2.WM_CONTEXTMENU:ehp2. message.
  140. :p.:hp2.Landmark 8:ehp2.
  141. :p.Finally, we invoke the :hp2.searchCnr():ehp2. function specifying a pointer
  142. to a boolean that contains the desired select state.  The
  143. :hp2.searchSelect():ehp2. function is an interesting one.
  144. :font facename=Courier size=14x14.
  145. :xmp.
  146. BOOL searchSelect(HWND hwndCnr,PMYCNRREC pmcrRecord,PBOOL pbSelect)
  147. //-------------------------------------------------------------------------
  148. // This function is used to select/deselect all records.  Note that it
  149. // always returns FALSE, so that searchCnr() will traverse the entire
  150. // record list.
  151. //
  152. // Input:  hwndCnr - handle of the container window
  153. //         pmcrRecord - pointer to the container record
  154. //         pbSelect - pointer to a BOOL specifying whether to select the
  155. //                    record or not
  156. //-------------------------------------------------------------------------
  157. &lbrc.
  158.    WinSendMsg(hwndCnr,
  159.               CM_SETRECORDEMPHASIS,
  160.               MPFROMP(pmcrRecord),
  161.               MPFROM2SHORT(*pbSelect,CRA_SELECTED));
  162.    return FALSE;
  163. &rbrc.
  164. :exmp.
  165. :font facename=default.
  166. :p.See how it simply sets the record&apos.s select state and always returns
  167. :hp2.FALSE:ehp2. - indicating that this record does not match - forcing
  168. :hp2.searchCnr():ehp2. to traverse the entire container.
  169. :p.:hp2.That&apos.s It!:ehp2.
  170. :p.That is all there is to it!  Note that while there is a lot of setup
  171. involved, the container is no more difficult to use than any of the other
  172. &odq.standard&cdq. controls.
  173. :h3.Summary
  174. :p.We have seen how tree views can be used for hierarchical structures and how
  175. they are not much different that the icon, name, and text views described last
  176. month.  We have used these concepts and introduced new ones in a sample
  177. application which will be used as a scaffold to add new features in future
  178. installments of this series.
  179. :p.Next month we will describe the details view, selection states, direct
  180. editing, and possibly other ideas and will incorporate these concepts into our
  181. sample application.
  182.