home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwphescr.zip / XWPH0208.ZIP / src / helpers / cctl_progbar.c < prev    next >
C/C++ Source or Header  |  2002-07-05  |  14KB  |  421 lines

  1.  
  2. /*
  3.  *@@sourcefile cctl_progbar.c:
  4.  *      implementation for the progress bar common control.
  5.  *      See comctl.c for an overview.
  6.  *
  7.  *      This has been extracted from comctl.c with V0.9.3 (2000-05-21) [umoeller].
  8.  *
  9.  *      Note: Version numbering in this file relates to XWorkplace version
  10.  *            numbering.
  11.  *
  12.  *@@header "helpers\comctl.h"
  13.  *@@added V0.9.3 (2000-05-21) [umoeller].
  14.  */
  15.  
  16. /*
  17.  *      Copyright (C) 1997-2000 Ulrich Möller.
  18.  *      This file is part of the "XWorkplace helpers" source package.
  19.  *      This is free software; you can redistribute it and/or modify
  20.  *      it under the terms of the GNU General Public License as published
  21.  *      by the Free Software Foundation, in version 2 as it comes in the
  22.  *      "COPYING" file of the XWorkplace main distribution.
  23.  *      This program is distributed in the hope that it will be useful,
  24.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26.  *      GNU General Public License for more details.
  27.  */
  28.  
  29. #define OS2EMX_PLAIN_CHAR
  30.     // this is needed for "os2emx.h"; if this is defined,
  31.     // emx will define PSZ as _signed_ char, otherwise
  32.     // as unsigned char
  33.  
  34. #define INCL_DOSEXCEPTIONS
  35. #define INCL_DOSPROCESS
  36. #define INCL_DOSSEMAPHORES
  37. #define INCL_DOSERRORS
  38.  
  39. #define INCL_WINWINDOWMGR
  40. #define INCL_WINFRAMEMGR
  41. #define INCL_WINMESSAGEMGR
  42. #define INCL_WININPUT
  43. #define INCL_WINPOINTERS
  44. #define INCL_WINTRACKRECT
  45. #define INCL_WINTIMER
  46. #define INCL_WINSYS
  47.  
  48. #define INCL_WINRECTANGLES      /// xxx temporary
  49.  
  50. #define INCL_WINMENUS
  51. #define INCL_WINSTATICS
  52. #define INCL_WINBUTTONS
  53. #define INCL_WINSTDCNR
  54.  
  55. #define INCL_GPIPRIMITIVES
  56. #define INCL_GPILOGCOLORTABLE
  57. #define INCL_GPILCIDS
  58. #define INCL_GPIPATHS
  59. #define INCL_GPIREGIONS
  60. #define INCL_GPIBITMAPS             // added V0.9.1 (2000-01-04) [umoeller]: needed for EMX headers
  61. #include <os2.h>
  62.  
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #include <string.h>
  66. #include <setjmp.h>             // needed for except.h
  67. #include <assert.h>             // needed for except.h
  68.  
  69. #include "setup.h"                      // code generation and debugging options
  70.  
  71. #include "helpers\cnrh.h"
  72. #include "helpers\except.h"             // exception handling
  73. #include "helpers\gpih.h"
  74. #include "helpers\linklist.h"
  75. #include "helpers\winh.h"
  76.  
  77. #include "helpers\comctl.h"
  78.  
  79. #pragma hdrstop
  80.  
  81. /*
  82.  *@@category: Helpers\PM helpers\Window classes\Progress bars
  83.  *      See cctl_progbar.c.
  84.  */
  85.  
  86. /* ******************************************************************
  87.  *
  88.  *   Progress bars
  89.  *
  90.  ********************************************************************/
  91.  
  92. /*
  93.  *@@ PaintProgress:
  94.  *      this does the actual painting of the progress bar, called
  95.  *      from ctl_fnwpProgressBar.
  96.  *      It is called both upon WM_PAINT and WM_UPDATEPROGRESSBAR
  97.  *      with different HPS's then.
  98.  *
  99.  *@@added V0.9.0 [umoeller]
  100.  *@@changed V0.9.5 (2000-09-22) [umoeller]: fixed ypos of text
  101.  */
  102.  
  103. static VOID PaintProgress(PPROGRESSBARDATA pData,
  104.                           HWND hwndBar,
  105.                           PRECTL prclWin,      // in: window rectangle (WinQueryWindowRect)
  106.                           HPS hps)
  107. {
  108.     POINTL  ptlText; // , aptlText[TXTBOX_COUNT];
  109.     BOOL    fBackgroundPainted = FALSE;
  110.     CHAR    szPercent[10] = "";
  111.     RECTL   rclInnerButton;
  112.     LONG    lcolScrollbar = WinQuerySysColor(HWND_DESKTOP,
  113.                                              SYSCLR_SCROLLBAR,
  114.                                              0);
  115.  
  116.     // switch to RGB mode
  117.     gpihSwitchToRGB(hps);
  118.  
  119.     if (pData->ulPaintX <= pData->ulOldPaintX)
  120.     {
  121.         RECTL rclOuterFrame;        // inclusive
  122.         rclOuterFrame.xLeft = 0;
  123.         rclOuterFrame.yBottom = 0;
  124.         rclOuterFrame.xRight = prclWin->xRight - 1;
  125.         rclOuterFrame.yTop = prclWin->yTop - 1;
  126.  
  127.         gpihDraw3DFrame(hps,
  128.                         &rclOuterFrame,     // inclusive
  129.                         1,
  130.                         WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0),
  131.                         WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0));
  132.  
  133.         rclOuterFrame.xLeft++;
  134.         rclOuterFrame.yBottom++;
  135.         WinFillRect(hps,
  136.                     &rclOuterFrame,     // exclusive, top right not drawn
  137.                     lcolScrollbar);
  138.         fBackgroundPainted = TRUE;
  139.     }
  140.  
  141.     // now draw the actual progress;
  142.     // rclInnerButton receives an _inclusive_ rectangle
  143.     rclInnerButton.xLeft = 1;
  144.     rclInnerButton.xRight = (pData->ulPaintX > (rclInnerButton.xLeft + 3))
  145.                                  ? pData->ulPaintX
  146.                                  : rclInnerButton.xLeft +
  147.                                        ((pData->ulAttr & PBA_BUTTONSTYLE)
  148.                                            ? 3 : 1);
  149.     rclInnerButton.yBottom = 1;
  150.     rclInnerButton.yTop = prclWin->yTop     // exclusive
  151.                             - 2;            // 1 to make inclusive, 1 for outer frame
  152.  
  153.     if (pData->ulAttr & PBA_PERCENTFLAGS)
  154.     {
  155.         // percentage desired:
  156.  
  157.         POINTL  aptlText[TXTBOX_COUNT];
  158.         LONG    lLineSpacing = 1;
  159.         FONTMETRICS fm;
  160.         if (GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm))
  161.             lLineSpacing = fm.lEmHeight;
  162.  
  163.         sprintf(szPercent, "%lu %%", ((100 * pData->ulNow) / pData->ulMax) );
  164.         // calculate string space
  165.         GpiQueryTextBox(hps,
  166.                         strlen(szPercent),
  167.                         szPercent,
  168.                         TXTBOX_COUNT,
  169.                         (PPOINTL)&aptlText);
  170.  
  171.         ptlText.x =
  172.                         (   (   (prclWin->xRight)     // cx
  173.                               - (aptlText[TXTBOX_BOTTOMRIGHT].x - aptlText[TXTBOX_BOTTOMLEFT].x)
  174.                             )
  175.                         / 2);
  176.         ptlText.y =
  177.                         (   (   (prclWin->yTop)       // cy
  178.                               - (lLineSpacing)
  179.                             )
  180.                         / 2) + 2;
  181.  
  182.         if (!fBackgroundPainted)
  183.         {
  184.             // if we haven't drawn the background already,
  185.             // we'll need to do it now for the percentage area
  186.             RECTL rcl2;
  187.             rcl2.xLeft      = ptlText.x;
  188.             rcl2.xRight     = ptlText.x + (aptlText[TXTBOX_BOTTOMRIGHT].x-aptlText[TXTBOX_BOTTOMLEFT].x);
  189.             rcl2.yBottom    = ptlText.y;
  190.             rcl2.yTop       = ptlText.y + lLineSpacing;
  191.             WinFillRect(hps,
  192.                         &rcl2,
  193.                         lcolScrollbar);
  194.         }
  195.     }
  196.  
  197.     if (pData->ulAttr & PBA_BUTTONSTYLE)
  198.     {
  199.         // draw "raised" inner rect
  200.         gpihDraw3DFrame(hps,
  201.                         &rclInnerButton,
  202.                         2,
  203.                         WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0),
  204.                         WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0));
  205.     }
  206.  
  207.     rclInnerButton.xLeft += 2;
  208.     rclInnerButton.yBottom += 2;
  209.     rclInnerButton.yTop -= 2;
  210.     rclInnerButton.xRight -= 2;
  211.  
  212.     if (rclInnerButton.xRight > rclInnerButton.xLeft)
  213.     {
  214.         POINTL ptl1;
  215.         // draw interior of inner rect
  216.         GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
  217.                                           SYSCLR_BUTTONMIDDLE,
  218.                                           0));
  219.         ptl1.x = rclInnerButton.xLeft;
  220.         ptl1.y = rclInnerButton.yBottom;
  221.         GpiMove(hps, &ptl1);
  222.         ptl1.x = rclInnerButton.xRight;
  223.         ptl1.y = rclInnerButton.yTop;
  224.         GpiBox(hps,
  225.                DRO_FILL | DRO_OUTLINE,
  226.                &ptl1,       // inclusive!
  227.                0,
  228.                0);
  229.     }
  230.  
  231.     // now print the percentage
  232.     if (pData->ulAttr & PBA_PERCENTFLAGS)
  233.     {
  234.         GpiMove(hps, &ptlText);
  235.         GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
  236.                                           SYSCLR_BUTTONDEFAULT,
  237.                                           0));
  238.         GpiCharString(hps, strlen(szPercent), szPercent);
  239.     }
  240.  
  241.     // store current X position for next time
  242.     pData->ulOldPaintX = pData->ulPaintX;
  243. }
  244.  
  245. /*
  246.  *@@ ctl_fnwpProgressBar:
  247.  *      this is the window procedure for the progress bar control.
  248.  *
  249.  *      This is not a stand-alone window procedure, but must only
  250.  *      be used with static rectangle controls subclassed by
  251.  *      ctlProgressBarFromStatic.
  252.  *
  253.  *      We need to capture WM_PAINT to draw the progress bar according
  254.  *      to the current progress, and we also update the static text field
  255.  *      (percentage) next to it.
  256.  *
  257.  *      This also evaluates the WM_UPDATEPROGRESSBAR message.
  258.  *
  259.  *@@changed V0.9.0 [umoeller]: moved this code here
  260.  *@@changed V0.9.1 (99-12-06): fixed memory leak
  261.  */
  262.  
  263. MRESULT EXPENTRY ctl_fnwpProgressBar(HWND hwndBar, ULONG msg, MPARAM mp1, MPARAM mp2)
  264. {
  265.     HPS                 hps;
  266.     PPROGRESSBARDATA    ppd = (PPROGRESSBARDATA)WinQueryWindowULong(hwndBar, QWL_USER);
  267.  
  268.     PFNWP   OldStaticProc = NULL;
  269.  
  270.     MRESULT mrc = NULL;
  271.  
  272.     if (ppd)
  273.     {
  274.         OldStaticProc = ppd->OldStaticProc;
  275.  
  276.         switch(msg)
  277.         {
  278.  
  279.             /*
  280.              *@@ WM_UPDATEPROGRESSBAR:
  281.              *      post or send this message to a progress bar
  282.              *      to have a new progress displayed.
  283.              *      Parameters:
  284.              *      --  ULONG mp1   current value
  285.              *      --  ULONG mp2   max value
  286.              *      Example: mp1 = 100, mp2 = 300 will result
  287.              *      in a progress of 33%.
  288.              */
  289.  
  290.             case WM_UPDATEPROGRESSBAR:
  291.             {
  292.                 RECTL rclWin;
  293.                 WinQueryWindowRect(hwndBar, &rclWin);
  294.                 if (    (ppd->ulNow != (ULONG)mp1)
  295.                      || (ppd->ulMax != (ULONG)mp2)
  296.                    )
  297.                 {
  298.                     ppd->ulNow = (ULONG)mp1;
  299.                     ppd->ulMax = (ULONG)mp2;
  300.                 }
  301.                 else
  302.                     // value not changed: do nothing
  303.                     break;
  304.  
  305.                 // check validity
  306.                 if (ppd->ulNow > ppd->ulMax)
  307.                     ppd->ulNow = ppd->ulMax;
  308.                 // avoid division by zero
  309.                 if (ppd->ulMax == 0)
  310.                 {
  311.                     ppd->ulMax = 1;
  312.                     ppd->ulNow = 0;
  313.                     // paint 0% then
  314.                 }
  315.  
  316.                 // calculate new X position of the progress
  317.                 ppd->ulPaintX =
  318.                     (ULONG)(
  319.                               (    (ULONG)(rclWin.xRight - rclWin.xLeft - 2)
  320.                                  * (ULONG)(ppd->ulNow)
  321.                               )
  322.                               /  (ULONG)ppd->ulMax
  323.                            );
  324.                 if (ppd->ulPaintX != ppd->ulOldPaintX)
  325.                 {
  326.                     // X position changed: redraw
  327.                     // WinInvalidateRect(hwndBar, NULL, FALSE);
  328.                     hps = WinGetPS(hwndBar);
  329.                     PaintProgress(ppd, hwndBar, &rclWin, hps);
  330.                     WinReleasePS(hps);
  331.                 }
  332.             break; }
  333.  
  334.             case WM_PAINT:
  335.             {
  336.                 RECTL rclWin;
  337.                 WinQueryWindowRect(hwndBar, &rclWin);
  338.                 hps = WinBeginPaint(hwndBar, NULLHANDLE, NULL);
  339.                 PaintProgress(ppd, hwndBar, &rclWin, hps);
  340.                 WinEndPaint(hps);
  341.             break; }
  342.  
  343.             /*
  344.              * WM_DESTROY:
  345.              *      free PROGRESSBARDATA
  346.              *      (added V0.9.1 (99-12-06))
  347.              */
  348.  
  349.             case WM_DESTROY:
  350.             {
  351.                 free(ppd);
  352.                 mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
  353.             break; }
  354.  
  355.             default:
  356.                 mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
  357.        }
  358.     }
  359.     return mrc;
  360. }
  361.  
  362. /*
  363.  *@@ ctlProgressBarFromStatic:
  364.  *      this function turns an existing static rectangle control
  365.  *      into a progress bar by subclassing its window procedure
  366.  *      with ctl_fnwpProgressBar.
  367.  *
  368.  *      This way you can easily create a progress bar as a static
  369.  *      control in any Dialog Editor; after loading the dlg template,
  370.  *      simply call this function with the hwnd of the static control
  371.  *      to make it a status bar.
  372.  *
  373.  *      This is used for all the progress bars in XWorkplace and
  374.  *      WarpIN.
  375.  *
  376.  *      In order to _update_ the progress bar, simply post or send
  377.  *      WM_UPDATEPROGRESSBAR to the static (= progress bar) window;
  378.  *      this message is equal to WM_USER and needs the following
  379.  *      parameters:
  380.  *      --  mp1     ULONG ulNow: the current progress
  381.  *      --  mp2     ULONG ulMax: the maximally possible progress
  382.  *                               (= 100%)
  383.  *
  384.  *      The progress bar automatically calculates the current progress
  385.  *      display. For example, if ulNow = 4096 and ulMax = 8192,
  386.  *      a progress of 50% will be shown. It is possible to change
  387.  *      ulMax after the progress bar has started display. If ulMax
  388.  *      is 0, a progress of 0% will be shown (to avoid division
  389.  *      by zero traps).
  390.  *
  391.  *      ulAttr accepts of the following:
  392.  *      --  PBA_NOPERCENTAGE:    do not display percentage
  393.  *      --  PBA_ALIGNLEFT:       left-align percentage
  394.  *      --  PBA_ALIGNRIGHT:      right-align percentage
  395.  *      --  PBA_ALIGNCENTER:     center percentage
  396.  *      --  PBA_BUTTONSTYLE:     no "flat", but button-like look
  397.  *
  398.  *@@changed V0.9.0 [umoeller]: moved this code here
  399.  */
  400.  
  401. BOOL ctlProgressBarFromStatic(HWND hwndChart, ULONG ulAttr)
  402. {
  403.     PFNWP OldStaticProc;
  404.     if (OldStaticProc = WinSubclassWindow(hwndChart, ctl_fnwpProgressBar))
  405.     {
  406.         PPROGRESSBARDATA pData = (PPROGRESSBARDATA)malloc(sizeof(PROGRESSBARDATA));
  407.         pData->ulMax = 1;
  408.         pData->ulNow = 0;
  409.         pData->ulPaintX = 0;
  410.         pData->ulAttr = ulAttr;
  411.         pData->OldStaticProc = OldStaticProc;
  412.  
  413.         WinSetWindowULong(hwndChart, QWL_USER, (ULONG)pData);
  414.         return (TRUE);
  415.     }
  416.  
  417.     return (FALSE);
  418. }
  419.  
  420.  
  421.