home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ctlcpp.zip / NEWCTL.CPP < prev    next >
C/C++ Source or Header  |  1994-06-06  |  11KB  |  304 lines

  1. /***************************************************************/
  2. /* Filename: newctl.cpp                                        */
  3. /*                                                             */
  4. /* Purpose: Main source file for C++ control NewControl.       */
  5. /*                                                             */
  6. /* Program name: cppctl.exe     Title: C++ PM Control Test App */
  7. /* OS/2 Developer Magazine, Issue: Sept. '94, page             */
  8. /* Article title: Writing OS/2 PM Controls in C++              */
  9. /* Authors: Eric Snell and Lori Ruffing                        */
  10. /*                                                             */
  11. /* Description: This example shows how to implement an OS/2 PM */
  12. /*              control window in C++.                         */
  13. /*                                                             */
  14. /* Program Requirements: This example requires the IBM C Set++ */
  15. /*                       compiler and libraries.               */
  16. /***************************************************************/
  17. extern "C"
  18.    {
  19.    #define INCL_WINSYS
  20.    #define INCL_WINWINDOWMGR
  21.    #define INCL_GPICONTROL
  22.    #define INCL_GPILOGCOLORTABLE
  23.    #define INCL_GPIPRIMITIVES
  24.    #include <os2.h>
  25.    }
  26.  
  27. #ifndef _IEXCEPT_
  28.    #include <iexcept.hpp>
  29. #endif
  30.  
  31. #define MIN(a, b) ( ( (a) <= (b) ) ? (a) : (b) )
  32. #define MAX(a, b) ( ( (a) >= (b) ) ? (a) : (b) )
  33.  
  34. #include "newctl.hpp"
  35.  
  36. // Class variables and constants
  37. const NewControl::Style NewControl::notifyMB1 = 1;
  38. const NewControl::Style NewControl::notifyMB2 = (1 << 1);
  39.  
  40. const NewControl::Style NewControl::classDefaultStyle =
  41.    IWindow::visible | notifyMB1 | notifyMB2;
  42.  
  43. NewControl::Style NewControl::currentDefaultStyle =
  44.    NewControl::classDefaultStyle;
  45.  
  46. // Define the NewControl class name for use in constructing IAbstractWindow
  47. const char* NewControl::newControlClass = "NewControlClass";
  48.  
  49. // Define the the class style to be CS_SIZEREDRAW so that the text in
  50. // the control will be scaled to the window size.
  51. const unsigned long NewControl::newControlClassStyle = CS_SIZEREDRAW;
  52.  
  53. // Define the text to be displayed in the control.
  54. const char* NewControl::dummyText = "Mouse clicks: ";
  55.  
  56. // Define the default colors for background, foreground, and hilite.
  57. const IColor NewControl::defclrBackground(IColor::paleGray);
  58. const IColor NewControl::defclrForeground(IColor::blue);
  59. const IColor NewControl::defclrHilite(IColor::red);
  60.  
  61. //----------------------------------------------------------------------------
  62. // Method: NewControl::establishColor
  63. //
  64. // Description: 'establishColor' sets the the logical color table
  65. //              for the hps into RGB mode and sets 'clr' to the
  66. //              color value for 'clrArea' or 'defClr' if there
  67. //              is an exception.
  68. //----------------------------------------------------------------------------
  69. inline NewControl& NewControl::establishColor(IColor& clr,
  70.                                               NewControl::ColorArea clrArea,
  71.                                               const IColor& defClr)
  72.    {
  73.    // Need to bracket the call with try/catch since an exception will
  74.    // be thrown if someone removed the presparam.
  75.    try
  76.       {
  77.       clr = color(clrArea);
  78.       }
  79.    catch (IException& exc)
  80.       {
  81.       // Reassign default to make sure it wasn't hosed up somehow.
  82.       clr = defClr;
  83.       }
  84.  
  85.    return *this;
  86.    }
  87.  
  88. //----------------------------------------------------------------------------
  89. // Method: NewControl::NewControl
  90. //
  91. // Description: 'NewControl' is the constructor for the NewControl class.
  92. //              It takes all the standard window creation parameters
  93. //              plus the class name, class style, and extra window words.
  94. //----------------------------------------------------------------------------
  95. NewControl::NewControl(unsigned long id,
  96.                        IWindow* parent,
  97.                        IWindow* owner,
  98.                        const IRectangle& initial,
  99.                        const Style& style)
  100.    : IAbstractWindow(newControlClass,
  101.                      newControlClassStyle,
  102.                      0,
  103.                      id,
  104.                      parent,
  105.                      owner,
  106.                      initial,
  107.                      style.asUnsignedLong()),
  108.      clicks(0),
  109.      cx(initial.width()),
  110.      cy(initial.height())
  111.    {
  112.    // Set color presparams to try to avoid exceptions being
  113.    // thrown.
  114.    setColor(background, defclrBackground);
  115.    setColor(foreground, defclrForeground);
  116.    setColor(hilite, defclrHilite);
  117.  
  118.    // Attach the mouse click handler because we want to be
  119.    // notified of any click.
  120.    IMouseClickHandler::handleEventsFor(this);
  121.    }
  122.  
  123. //----------------------------------------------------------------------------
  124. // Method: NewControl::~NewControl
  125. //
  126. // Description: '~NewControl' is the destructor for the NewControl class.
  127. //----------------------------------------------------------------------------
  128. NewControl::~NewControl()
  129.    {
  130.    }
  131.  
  132. NewControl::Style NewControl::defaultStyle()
  133.    {
  134.    return currentDefaultStyle;
  135.    }
  136.  
  137. void NewControl::setDefaultStyle(const Style& style)
  138.    {
  139.    currentDefaultStyle = style;
  140.    }
  141.  
  142. NewControl& NewControl::setColor(ColorArea area, const IColor& color)
  143.    {
  144.    IWindow::setColor(area, color);
  145.    return *this;
  146.    }
  147.  
  148. IColor NewControl::color(ColorArea area) const
  149.    {
  150.    return IWindow::color(area);
  151.    }
  152.  
  153. //----------------------------------------------------------------------------
  154. // Method: NewControl::paintWindow
  155. //
  156. // Description: 'paintWindow' is called in response to a paint event, 'evt'.
  157. //              It establishes the colors to paint as well as determines
  158. //              how large and where to draw the text.
  159. //----------------------------------------------------------------------------
  160. Boolean NewControl::paintWindow(IPaintEvent& evt)
  161.    {
  162.    IColor clrBackground(defclrBackground);
  163.    IColor clrForeground(defclrForeground);
  164.    IColor clrHilite(defclrHilite);
  165.  
  166.    IPresSpaceHandle hps = evt.presSpaceHandle();
  167.  
  168.    // Should make a separate method which sets the logical
  169.    // color table for the HPS into RGB mode and sets all our
  170.    // colors. Also, colors could be cached in private data
  171.    // and only updated when presparams change.
  172.    establishColor(clrBackground, background, defclrBackground);
  173.    establishColor(clrForeground, foreground, defclrForeground);
  174.    establishColor(clrHilite, hilite, defclrHilite);
  175.  
  176.    evt.clearBackground(clrBackground);
  177.  
  178.    // Create the text to draw
  179.    IString theText(dummyText);
  180.    IString theNumber(clicks);
  181.    theNumber.rightJustify(4);
  182.    IString both(theText + theNumber);
  183.  
  184.    POINTL aptl[TXTBOX_COUNT];
  185.    POINTL ptl = {0,0};
  186.  
  187.    // Find where we're going to draw our text and how big it will be.
  188.    GpiQueryTextBox(hps,
  189.                    strlen((char*)both),
  190.                    (char*)both,
  191.                    TXTBOX_COUNT,
  192.                    aptl);
  193.  
  194.    long textWidth = MAX(aptl[TXTBOX_TOPRIGHT].x,
  195.                         aptl[TXTBOX_BOTTOMRIGHT].x);
  196.    long textHeight = MAX(aptl[TXTBOX_TOPLEFT].y,
  197.                          aptl[TXTBOX_TOPRIGHT].y);
  198.  
  199.    // Center the text before drawing it.
  200.    long x = (cx - textWidth) / 2;
  201.    long y = (cy - textHeight) / 2;
  202.  
  203.    evt.drawText(theText, IPoint(x, y), clrForeground);
  204.  
  205.    GpiQueryTextBox(hps,
  206.                    strlen((char*)theText),
  207.                    (char*)theText,
  208.                    TXTBOX_COUNT,
  209.                    aptl);
  210.  
  211.    // Draw the number to the side of the text
  212.    x += aptl[TXTBOX_CONCAT].x;
  213.    evt.drawText(theNumber, IPoint(x, y), clrHilite);
  214.  
  215.    return true;
  216.    }
  217.  
  218. //----------------------------------------------------------------------------
  219. // Method: NewControl::windowResize
  220. //
  221. // Description: 'windowResize' is called in response to a resize event, 'evt'.
  222. //              It stores the current width and height of the control.
  223. //----------------------------------------------------------------------------
  224. Boolean NewControl::windowResize(IResizeEvent& evt)
  225.    {
  226.    // Keep track of control's width and height.
  227.    cx = evt.newSize().width();
  228.    cy = evt.newSize().height();
  229.    return false;
  230.    }
  231.  
  232. //----------------------------------------------------------------------------
  233. // Method: NewControl::gainingFocus
  234. //
  235. // Description: 'gainingFocus' is called in response to a focus gain event,
  236. //              'evt'. It doesn't do anything, but you can fill in any code
  237. //              you feel appropriate for when the control gains focus.
  238. //----------------------------------------------------------------------------
  239. Boolean NewControl::gainingFocus(IEvent &evt)
  240.    {
  241.    evt;
  242.  
  243.    // You could create a cursor here if you like.
  244.  
  245.    return true;
  246.    }
  247.  
  248. //----------------------------------------------------------------------------
  249. // Method: NewControl::losingFocus
  250. //
  251. // Description: 'losingFocus' is called in response to a focus loss event,
  252. //              'evt'. It doesn't do anything, but you can fill in any code
  253. //              you feel appropriate for when the control loses focus.
  254. //----------------------------------------------------------------------------
  255. Boolean NewControl::losingFocus(IEvent &evt)
  256.    {
  257.    evt;
  258.  
  259.    // You could destroy a cursor here if you like.
  260.  
  261.    return true;
  262.    }
  263.  
  264. //----------------------------------------------------------------------------
  265. // Method: NewControl::mouseClicked
  266. //
  267. // Description: 'mouseClicked' is called in response to a mouse click event,
  268. //              'evt'. It sends notifications to the owner describing which
  269. //              mouse button was clicked and refreshes the window when
  270. //              appropriate.
  271. //----------------------------------------------------------------------------
  272. Boolean NewControl::mouseClicked(IMouseClickEvent& evt)
  273.    {
  274.    // If the mouse is clicked down and NewControl doesn't already
  275.    // have the focus, set the focus to it.
  276.    if (IMouseClickEvent::down == evt.mouseAction() &&
  277.        !hasFocus())
  278.       setFocus();
  279.  
  280.    // If the mouse is clicked and released...
  281.    if (IMouseClickEvent::click == evt.mouseAction())
  282.       {
  283.  
  284.       // If it was button 1, update the click count, paint, and notify owner.
  285.       if (IMouseClickEvent::button1 == evt.mouseNumber())
  286.          {
  287.          ++clicks;
  288.          refresh();
  289.          owner()->sendEvent(WM_CONTROL,
  290.                             IEventParameter1(id(), IMouseClickEvent::button1));
  291.          }
  292.  
  293.       // If it was button 2, just notify owner.
  294.       else if (IMouseClickEvent::button2 == evt.mouseNumber())
  295.          {
  296.          owner()->sendEvent(WM_CONTROL,
  297.                             IEventParameter1(id(), IMouseClickEvent::button2));
  298.          }
  299.       }
  300.  
  301.    return true;
  302.    }
  303.  
  304.