home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / diyctl.zip / DIYCTL.TXT
Text File  |  1994-05-06  |  31KB  |  665 lines

  1. Subject: How to create new controls
  2.  
  3. PREFACE: the detail you are about to read should be of no interest
  4. to user who wish to create applications (even very complicated ones)
  5. by reusing the parts in UICL. This detail is only necessary if you
  6. find you must write your own classes from underlying system controls;
  7. building your own classes from our classes, again you don't need to know
  8. this design detail.
  9.  
  10. Let me see if I can give you something to start with (I hope to complete
  11. a magazine article on this topic, so feedback on the example is greatly
  12. appreciated):
  13.  
  14. Your goal is to create your own class for a control (in this case, Pen)
  15. which fits the basic structure of UICL. The basic steps are:
  16.  
  17. 1) Write a class derived from IControl (typically)
  18.    whose ctor creates the underlying window system (PM) control,
  19.    with styles and other state set according to the style bits
  20.    passed into you. Certain other methods must be implemented as well
  21.    (see sample code below).
  22.  
  23. 2) Write a class derived from IHandler (typically) to handle any
  24.    events unique to your new control. You must implement the method
  25.    dispatchHandlerEvent(evt), and (optionally) a method for each event or
  26.    related set of events this handler is to process. When you add your
  27.    handler to a window, the handler will begin to receive events in the
  28.    form of IEvents. See IEvent.hpp or the doc for how to get all the
  29.    data therein. The IEvent is first passed to a handler via its
  30.    ::dispatchHandlerEvent() method. It's up to the handler if it wants
  31.    to follow our style & call itself at this point with finer-grained
  32.    methods, or if it just wants to process all the events for that
  33.    handler in dispatchHandlerEvent(). I advise our style; it makes future
  34.    reuse easier (and you WILL reuse, or wish you could).
  35.  
  36. Here is some sample code for a control and for a handler.
  37. These samples (and if you need it, a subclass of IEvent for special data) 
  38. should help you to wrapper a control of your own. For now the samples are
  39. without warrantee (except for normal forum assistance).
  40.  
  41. Hope this helps you. Again, feedback is more than welcome.
  42.  
  43.  
  44. Art Jolin, CSet++ UI Class Libraries
  45.  
  46. ============================================
  47. ===================== ctlsampl.hpp ==============================
  48. #ifndef _CTLSAMPL_
  49.   #define _CTLSAMPL_
  50. /*******************************************************************************
  51. * FILE NAME: ctlsampl.hpp                                                      *
  52. *                                                                              *
  53. * DESCRIPTION:                                                                 *
  54. *   Declaration of the class(es):                                              *
  55. *   SampleControl  - This class does neat stuff.                               *
  56. *                                                                              *
  57. *******************************************************************************/
  58.  
  59. #ifndef _ICONTROL_
  60.   #include <icontrol.hpp>
  61. #endif
  62. // Forward declarations for other classes:
  63. class IRectangle;
  64. class ISize;
  65. class IWindowHandle;
  66. #ifndef _IRECT_
  67.   #include <irect.hpp>
  68. #endif
  69. #ifndef _IBITFLAG_
  70.   #include <ibitflag.hpp>
  71. #endif
  72.  
  73. /*----------------------------------------------------------------------------*/
  74. /* Align classes on four byte boundary.                                       */
  75. /*----------------------------------------------------------------------------*/
  76. #pragma pack(4)
  77.  
  78.  
  79. class SampleControl : public IControl  {
  80. typedef IControl Inherited;
  81. /*******************************************************************************
  82. * Tell all about SampleControl as a class.        ...                          *
  83. *******************************************************************************/
  84. public:
  85. /*------------------- Style -----------------------------------------------
  86.   The following functions provide a means to set and query sample control styles
  87.  
  88.     Style - Nested class that provides static members that define the set of
  89.             valid sample control styles.  These styles can be used in
  90.             conjunction with the styles defined by the nested classes
  91.             IWindow::Style and IControl::Style.  For
  92.             example, you could define an instance of the SampleControl::Style
  93.             class and initialize it like:
  94.               SampleControl::Style
  95.                 style = SampleControl::ringading | IControl::tabStop;
  96.             An object of this type is provided when the sample control is
  97.             created.  A customizable default is used if no styles are
  98.             specified.  Once the object is constructed, SampleControl,
  99.             IWindow and IControl member functions can be used to
  100.             set or query the object's style.
  101.  
  102.             The declaration of the SampleControl::Style nested class is
  103.             generated by the INESTEDBITFLAGCLASSDEF3 macro.
  104.  
  105.   The valid sample control styles are:
  106.     classDefaultStyle - Original default style for this class, which is
  107.                         IWindow::visible.
  108.     ringading         - Does some alternative neat thing when control is rung on
  109.     whoopdedo         - Does something else when control is rung twice.
  110.  
  111.   The following functions provide a means of getting and setting the default
  112.   style for this class:
  113.     defaultStyle    - Returns the current default style.  This is the same as
  114.                       classDefaultStyle unless setDefaultStyle has been
  115.                       called.
  116.     setDefaultStyle - Sets the default style for all subsequent sample controls.
  117. -------------------------------------------------------------------------*/
  118. INESTEDBITFLAGCLASSDEF2(Style, SampleControl, IWindow,
  119.                         IControl);
  120.                                   // style class definition
  121. static const Style
  122.   classDefaultStyle,
  123.   ringading,
  124.   whoopdedo;
  125.  
  126. static Style
  127.   defaultStyle();
  128. static void
  129.   setDefaultStyle(Style style);
  130.  
  131. /*------------------------ Constructors ----------------------------------------
  132. | You can construct instances of this class in the following ways:             |
  133. |    - From a control ID, parent and owner windows, rectangle, and style.      |
  134. |      This creates the specified sample control and an object for it.         |
  135. |    - From the ID of a sample control on a dialog window.  This creates       |
  136. |      the object for the specified sample control.                            |
  137. |    - From the window handle of an existing sample control.  This             |
  138. |      creates the object for the specified sample control.                    |
  139. ------------------------------------------------------------------------------*/
  140.   SampleControl(unsigned long id,
  141.               IWindow* parent,
  142.               IWindow* owner,
  143.               const IRectangle& initial= IRectangle(),
  144.               const Style& style = defaultStyle() );
  145.  
  146.   SampleControl(unsigned long id,
  147.               IWindow* parentDialog);
  148.  
  149.   SampleControl(const IWindowHandle& handle);
  150.  
  151.   virtual ~SampleControl();
  152.  
  153. /*-------------------------------- Style Functions -----------------------------
  154. | These functions provide a means of getting and setting the default style     |
  155. | attributes of instances of this class:                                       |
  156. |            .         .          .                                            |
  157. |            .         .          .                                            |
  158. |            .         .          .                                            |
  159. ------------------------------------------------------------------------------*/
  160.  
  161.  
  162.  
  163. /*------------------------------------------------------------------------------
  164. |SampleControl :: method1                                                      |
  165. |                                                                              |
  166. | Does some neat thing which a MagicControl is capable of.                     |
  167. ------------------------------------------------------------------------------*/
  168. virtual SampleControl&
  169.   method1(Boolean turnOn);
  170.  
  171. /*------------------------------------------------------------------------------
  172. |SampleControl :: method2                                                      |
  173. |                                                                              |
  174. | Does some other neat thing which a MagicControl is capable of.               |
  175. ------------------------------------------------------------------------------*/
  176. virtual IBase::Boolean
  177.    method2(IString aNeatPieceOfData);
  178.  
  179.  
  180. protected:
  181. /*----------------------------- Layout Size ------------------------------------
  182. | calcMinimumSize - Returns the recommended minimum size of this sample        |
  183. |                   control.  The size is based on the text string length and  |
  184. |                   the current font, or figured in some other way.            |
  185. ------------------------------------------------------------------------------*/
  186. virtual ISize
  187.   calcMinimumSize() const;
  188.  
  189.  
  190. private:
  191. /*--------------------------------- PRIVATE ----------------------------------*/
  192.   SampleControl(const SampleControl&);      //copy constructor: should have one
  193.   SampleControl& operator=(const SampleControl&);  //assignment ctor: should hav
  194. static Style
  195.   currentDefaultStyle;
  196.  
  197.  
  198. };  // class SampleControl
  199.  
  200. INESTEDBITFLAGCLASSFUNCS(Style, SampleControl);
  201.                                   // global style functions
  202.  
  203. /*----------------------------------------------------------------------------*/
  204. /* Resume compiler default packing.                                           */
  205. /*----------------------------------------------------------------------------*/
  206. #pragma pack()
  207.  
  208. #endif  //  _CTLSAMPL_
  209. ===================== end of ctlsampl.hpp ==============================
  210.  
  211. ===================== ctlsampl.cpp ==============================
  212. /*******************************************************************************
  213. * FILE NAME: ctlsampl.cpp                                                      *
  214. *                                                                              *
  215. *******************************************************************************/
  216.  
  217. #ifndef _CTLSAMPL_
  218.   #include <ctlsampl.hpp>
  219. #endif
  220. #ifndef _IEXCEPT_
  221.   #include <iexcept.hpp>
  222. #endif
  223. #ifndef _IHANDLE_
  224.   #include <ihandle.hpp>
  225. #endif
  226. #ifndef _IPOINT_
  227.   #include <ipoint.hpp>
  228. #endif
  229. #ifndef _IRECT_
  230.   #include <irect.hpp>
  231. #endif
  232. #ifndef _ITRACE_
  233.   #include <itrace.hpp>
  234. #endif
  235.  
  236.  
  237. /*------------------------------------------------------------------------------
  238. | Public control     styles.                                                   |
  239. ------------------------------------------------------------------------------*/
  240. const SampleControl::Style SampleControl::ringading(256);
  241. const SampleControl::Style SampleControl::whoopdedo(007);
  242.  
  243. /*------------------------------------------------------------------------------
  244. | Default style for new objects (initial value).                               |
  245. ------------------------------------------------------------------------------*/
  246. SampleControl::Style SampleControl::currentDefaultStyle(256);
  247.  
  248.  
  249. /*------------------------------------------------------------------------------
  250. | SampleControl::SampleControl
  251. |                                                                              |
  252. | Constructor to create a sample control on a standard window.                 |
  253. ------------------------------------------------------------------------------*/
  254. SampleControl :: SampleControl(unsigned long ulId,
  255.                            IWindow* pwndParent,
  256.                            IWindow* pwndOwner,
  257.                            const IRectangle& rectInit,
  258.                            const Style& pbsStyle)
  259. {
  260.   IASSERTPARM(pwndParent!=0);
  261.      .       .        .
  262.      .       .        .
  263.      .       .        .
  264.  
  265.   IWindowHandle
  266.     hwnd = WinCreateWindow( parent,
  267.                             WC_MAGICALCONTROLIMWRAPPERING,
  268.                             text,
  269.                             style,
  270.                             initRect.left(),
  271.                             initRect.bottom(),
  272.                             initRect.width(),
  273.                             initRect.height(),
  274.                             owner,
  275.                             behind,
  276.                             id,
  277.                             (void*)ctlData,
  278.                             (void*)presParams );
  279.  
  280.    if (hwnd == 0)
  281.      ITHROWGUIERROR("Can't Create Magical Control");     //throw an exception
  282.  
  283.    // This call actually "attaches" the specified widget to this instance.
  284.    startHandlingEventsFor(hwnd);
  285.  
  286.   //If some of these bits belong to IWindow, call the inherited "setStyle" also.
  287.   if (pbsStyle != IWindow::noStyle)
  288.     {
  289.      IWindow::setStyle (pbsStyle.asUnsignedLong());
  290.     }
  291. }
  292.  
  293.  
  294. /*------------------------------------------------------------------------------
  295. | SampleControl::SampleControl                                                 |
  296. |                                                                              |
  297. | Constructor to instantiate an object for an existing control in a dialog     |
  298. ------------------------------------------------------------------------------*/
  299. SampleControl :: SampleControl(unsigned long ulId,
  300.                            IWindow* pdlgwndParent)
  301. {
  302.   // assertions on input parms
  303.   IASSERTPARM(pdlgwndParent!=0);
  304.  
  305.   IWindowHandle whMagicalWidget =
  306.                   WinWIndowFromID(pdlgwndParent->handle(), ulId);
  307.   if (whMagicalWidget == 0)
  308.     ITHROWGUIERROR("WindowFromID failed");    //or otherwise throw an exception
  309.  
  310.   // We don't want to synchronize destruction of this instance and the widget,
  311.   // since they were created independently. This call turns off synch.
  312.   setAutoDestroyWindow(false);
  313.  
  314.   // This call actually "attaches" the specified control to this instance.
  315.   startHandlingEventsFor(whMagicalWidget);
  316. }
  317.  
  318.  
  319. /*------------------------------------------------------------------------------
  320. | SampleControl::SampleControl                                                 |
  321. |                                                                              |
  322. | Constructor to instantiate from an existing control.                         |
  323. ------------------------------------------------------------------------------*/
  324. SampleControl :: SampleControl(const IWindowHandle& whMagicalWidget)
  325. {
  326.   // We don't want to synchronize destruction of this instance and the widget,
  327.   // since they were created independently. This call turns off synch.
  328.   setAutoDestroyWindow(false);
  329.  
  330.   // This call actually "attaches" the specified control to this instance.
  331.   startHandlingEventsFor(whMagicalWidget);
  332. }
  333.  
  334. /*------------------------------------------------------------------------------
  335. |SampleControl ::~ SampleControl
  336. ------------------------------------------------------------------------------*/
  337. SampleControl :: ~SampleControl()
  338. {
  339.    // Often, you don't have to do anything in a dtor. The IWindow dtor takes
  340.    // care of things like destroying the PM control (if appropriate), cleaning up
  341.    // stray IHandlers still attached, etc.
  342. }
  343.  
  344.  
  345. /*------------------------------------------------------------------------------
  346. |SampleControl ::defaultStyle
  347. ------------------------------------------------------------------------------*/
  348. SampleControl::Style  SampleControl :: defaultStyle()
  349. {
  350.   return currentDefaultStyle;
  351. }
  352.  
  353.  
  354. /*------------------------------------------------------------------------------
  355. |SampleControl ::setDefaultStyle
  356. ------------------------------------------------------------------------------*/
  357. void  SampleControl :: setDefaultStyle(SampleControl::Style pbsStyle)
  358. {
  359.   currentDefaultStyle = pbsStyle;
  360. }
  361.  
  362.  
  363. /*------------------------------------------------------------------------------
  364. |SampleControl :: method1                                                      |
  365. |                                                                              |
  366. | Does some neat thing which a MagicControl is capable of.                     |
  367. ------------------------------------------------------------------------------*/
  368. SampleControl&  SampleControl :: method1(Boolean turnOn)
  369. {
  370.   return *this;
  371. }
  372.  
  373.  
  374. /*------------------------------------------------------------------------------
  375. |SampleControl :: method2                                                      |
  376. |                                                                              |
  377. | Does some other neat thing which a MagicControl is capable of.               |
  378. ------------------------------------------------------------------------------*/
  379. IBase::Boolean  SampleControl :: method2(IString aNeatPieceOfData)
  380. {
  381.   return True;
  382. }
  383.  
  384.  
  385. /*------------------------------------------------------------------------------
  386. | SampleControl::calcMinimumSize                                               |
  387. |                                                                              |
  388. | Calculate the minimum screen size needed by the control.  The height may be  |
  389. | based on the font height and width may be based on the average font width    |
  390. | multiplied by the width of the control text. Or some other scheme may be used.
  391. |                                                                              |
  392. | This method is necessary if your control is to fit well on a canvas.         |
  393. |                                                                              |
  394. ------------------------------------------------------------------------------*/
  395. ISize  SampleControl :: calcMinimumSize() const
  396. {
  397.    unsigned long ulWidth = 10;    //arbitrary number; this is only a sample afte
  398.    unsigned long ulHeight = 25;   //arbitrary number; this is only a sample afte
  399.  
  400.   ISize sizMin(ulWidth, ulHeight);
  401.   return sizMin;
  402. }
  403.  
  404.  
  405. ===================== end of ctlsampl.cpp ==============================
  406.  
  407. ===================== samplhdr.hpp ==============================
  408. #ifndef _SAMPLHDR_
  409.   #define _SAMPLHDR_
  410. /*******************************************************************************
  411. * FILE NAME: samplhdr.hpp                                                      *
  412. *                                                                              *
  413. * DESCRIPTION:                                                                 *
  414. *   Declaration of the class(es):                                              *
  415. *      MagicHandler - Process a magic spell  event for a control.              *
  416. *                                                                              *
  417. *******************************************************************************/
  418. #ifndef _IHANDLER_
  419.   #include <ihandler.hpp>
  420. #endif
  421. #ifndef _ICTLEVT_
  422.   #include <ictlevt.hpp>    //only if you map your events into IControlEvents
  423. #endif
  424.  
  425. /*----------------------------------------------------------------------------*/
  426. /* Align classes on four byte boundary.                                       */
  427. /*----------------------------------------------------------------------------*/
  428. #pragma pack(4)
  429.  
  430. // Forward declarations for other classes:
  431. class IEvent;
  432.  
  433.  
  434. class MagicHandler : public IHandler {
  435. typedef IHandler
  436.   Inherited;
  437. /*******************************************************************************
  438. * The  MagicHandler class handles the processing of magic spell  events for    *
  439. * the following controls:                                                      *
  440. *                                                                              *
  441. *   - SomeControl                                                              *
  442. *   - SomeOtherControl                                                         *
  443. *                                                                              *
  444. * The MagicHandler class is designed to handle events that occur when a        *
  445. * control has a magic spell cast on it, such as SP_BECOMETOAD or SP_GAINWEALTH *
  446. * or user-defined spells. The MagicHandler object should be attached to the    *
  447. * control that will have the spell cast upon it, or to the owner window        *
  448. * of the control.  You can do this by passing the control or owner             *
  449. * window on the handleEventsFor function of the MagicHandler object.           *
  450. *                                                                              *
  451. * When it receives a magic spell event, the MagicHandler object constructs     *
  452. * an IControlEvent object and routes it to the appropriate virtual function.   *
  453. * These virtual functions allow you to supply your own specialized processing  *
  454. * of the event.  The return values from the virtual functions specify whether  *
  455. * the IControlEvent should be passed on for additional processing, as follows: *
  456. *                                                                              *
  457. *   Value   Meaning                                                            *
  458. *   ---------------                                                            *
  459. *   true  - The IControlEvent requires no additional processing and should     *
  460. *           not be passed to another handler.                                  *
  461. *   false - The IControlEvent should be passed to the next handler for         *
  462. *           additional processing, as follows:                                 *
  463. *           -- If there is another handler for the control or window, the      *
  464. *              IControlEvent is passed on to the next handler.                 *
  465. *           -- If this is the last handler for the control, the IControlEvent  *
  466. *              is dispatched to the owner of the control.                      *
  467. *              (See IWindow::dispatch.)                                        *
  468. *           -- If this is the last handler for the owner window, the           *
  469. *              IControlEvent is passed on a call to the owner window's         *
  470. *              defaultProcedure function.  (See IWindow::defaultProcedure.)    *
  471. *                                                                              *
  472. * Example:                                                                     *
  473. *   MyWindow::MyWindow()   // inherits from IFrame, MagicHandler               *
  474. *     : ...                                                                    *
  475. *   {                                                                          *
  476. *     ((MagicHandler*)this)->handleEventsFor(this);                            *
  477. *     ...                                                                      *
  478. *     IEntryField* ef = new IEntryField(ID_EF, this, this, IRectangle(...));   *
  479. *     IStaticText* stxtHelp = new IStaticText(ID_STXTHELP, this, this,         *
  480. *                                             IRectangle(...));                *
  481. *     ...                                                                      *
  482. *     show();                                                                  *
  483. *   }                                                                          *
  484. *   Boolean  MyWindow::becomeToad(IControlEvent& evt)                          *
  485. *   {                    // provide quick help for current owned control       *
  486. *     if (evt.controlId() == ID_EF)                                            *
  487. *     {                        // entry field becomes toad                     *
  488. *        stxtHelp->setText("Watch out for warts.");                            *
  489. *     }                                                                        *
  490. *     ...                                                                      *
  491. *     else                                                                     *
  492. *     {                        // some other control                           *
  493. *        stxtHelp->setText(" ");  // no help for this one                      *
  494. *     }                                                                        *
  495. *     ...                                                                      *
  496. *     return false;            // let another handle event also                *
  497. *   }                                                                          *
  498. *******************************************************************************/
  499. public:
  500. /*-------------------------- Constructor/Destructor ----------------------------
  501. | The only way to construct instances of this class is to use the default      |
  502. | constructor, which does not take any arguments.                              |
  503. | ----------------------------------------------------------------------------*/
  504.   MagicHandler        ( );
  505. virtual
  506.  ~MagicHandler        ( );
  507.  
  508. protected:
  509. /*---------------------------- Event Dispatching -------------------------------
  510. | This function evaluates the event to determine if it is appropriate for      |
  511. | this handler object to process.  If it is, this function calls the virtual   |
  512. | function used to process the event.                                          |
  513. |   dispatchHandlerEvent - Calls the becomeToad or gainWealth function, as     |
  514. |                          appropriate.                                        |
  515. ------------------------------------------------------------------------------*/
  516. virtual Boolean
  517.   dispatchHandlerEvent ( IEvent& event );
  518.  
  519. /*----------------------------- Event Processing -------------------------------
  520. | These functions should be supplied by a derived class to process a focus     |
  521. | change event.                                                                |
  522. |   becomeToad - grow a long tongue, turn brown and warty, learn to like flies.|
  523. |   gainWealth - build a huge house, become insufferably overbearing, dictate  |
  524. |                to your customers, marry an employee and grow a pot belly.    |
  525. ------------------------------------------------------------------------------*/
  526. virtual Boolean
  527.   becomeToad           ( IControlEvent& event ),
  528.   gainWealth           ( IControlEvent& event );
  529. }; // MagicHandler
  530.  
  531. /*----------------------------------------------------------------------------*/
  532. /* Resume compiler default packing.                                           */
  533. /*----------------------------------------------------------------------------*/
  534. #pragma pack()
  535.  
  536. #endif /* _SAMPLHDR_ */
  537. ===================== end of samplhdr.hpp ==============================
  538.  
  539. ===================== samplhdr.cpp ==============================
  540. /**************************************************************/
  541. /* CLASS NAME:  MagicHandler                                  */
  542. /*                                                            */
  543. /**************************************************************/
  544. #define INCL_WINENTRYFIELDS
  545.   .    .     .
  546.   .    .     .
  547.   .    .     .
  548. extern "C" {
  549.    #include <os2.h>
  550.    #include <stdlib.h>
  551. }
  552. #ifndef _SAMPLHDR_
  553.   #include <samplhdr.hpp>
  554. #endif
  555. #ifndef _ICTLEVT_
  556.   #include <ictlevt.hpp>
  557. #endif
  558. #ifndef _IEVENT_
  559.   #include <ievent.hpp>
  560. #endif
  561. #ifndef _IWINDOW_
  562.   #include <iwindow.hpp>
  563. #endif
  564. #ifndef _IWCNAME_
  565.   #include <iwcname.hpp>
  566. #endif
  567.  
  568. // Segment definitions
  569. #ifdef IC_PAGETUNE
  570.   #define _SAMPLHDR_CPP_
  571.   #include <ipagetun.h>
  572. #endif
  573.  
  574.  
  575. MagicHandler :: MagicHandler ( )
  576.   : MagicHandler::Inherited ( )
  577. /*******************************************************************/
  578. /* Default constructor here for page tuning.                       */
  579. /*******************************************************************/
  580. { ; }
  581.  
  582.  
  583. MagicHandler :: ~MagicHandler ( )
  584. /*******************************************************************/
  585. /* Empty destructor here for page tuning.                          */
  586. /*******************************************************************/
  587. { ; }
  588.  
  589.  
  590. Boolean  MagicHandler :: dispatchHandlerEvent ( IEvent& evt )
  591. /**************************************************************/
  592. /* Dispatch command functions for this handler.               */
  593. /**************************************************************/
  594. {
  595.    Boolean bRc = false;
  596.  
  597.    if (evt.eventId() == WM_CONTROL)
  598.    {                              // Control event
  599.       IControlEvent ctlevt(evt);
  600.       IWindow* pwndControl = ctlevt.controlWindow();
  601.       /*************************************************************/
  602.       /* Figure out what kind of control experienced the event.    */ 
  603.       /* This handler is either attached to the control generating */
  604.       /* the WM_CONTROL message or to its owner.  If               */
  605.       /* IControlEvent::controlWindow returns 0, this must mean we */
  606.       /* have a non-wrappered control with a wrappered owner       */
  607.       /* window and that the handler is attached to the owner      */
  608.       /* window.  This case is supported only if the owner of the  */
  609.       /* control is also the control's parent (this is in order    */
  610.       /* for handleWithId to work).                                */
  611.       /*************************************************************/
  612.       unsigned long ulClassName = 0;
  613.       unsigned long ulMsg = ctlevt.parameter1().number2();
  614.       IWindowHandle hwndControl;
  615.       if (pwndControl)
  616.       {
  617.          hwndControl = pwndControl->handle();
  618.       }
  619.       else
  620.       {
  621.          hwndControl = IWindow::handleWithId( ctlevt.controlId(),
  622.                                               ctlevt.handle() );
  623.       }
  624.  
  625.       IWindowClassName className( hwndControl );
  626.  
  627.       if (className == WC_ENTRYFIELD)
  628.       {                        // entry field case
  629.          if (ulMsg == SP_BECOMETOAD)
  630.          {
  631.             bRc = becomeToad(ctlevt);
  632.          }
  633.          else if (ulMsg == SP_GAINWEALTH)
  634.          {
  635.             bRc = gainWealth(ctlevt);
  636.          }
  637.       }
  638.       else if (className == WC_SOMEOTHERCONTROL)
  639.            { .         .           .
  640.              .         .           .
  641.              .         .           .
  642.            }
  643.  
  644.       if (bRc)
  645.       {                           // processing done
  646.          evt.setResult(ctlevt.result());  // copy result
  647.       }
  648.    } /* endif WM_CONTROL */
  649.  
  650.    return bRc;
  651. }
  652.  
  653.  
  654. Boolean  MagicHandler :: becomeToad ( IControlEvent& evt )
  655. {
  656.   return false;
  657. }
  658.  
  659.  
  660. Boolean  MagicHandler :: gainWealth ( IControlEvent& evt )
  661. {
  662.   return false;
  663. }
  664. ===================== end of samplhdr.cpp ==============================
  665.