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 >
Wrap
C/C++ Source or Header
|
2002-07-05
|
14KB
|
421 lines
/*
*@@sourcefile cctl_progbar.c:
* implementation for the progress bar common control.
* See comctl.c for an overview.
*
* This has been extracted from comctl.c with V0.9.3 (2000-05-21) [umoeller].
*
* Note: Version numbering in this file relates to XWorkplace version
* numbering.
*
*@@header "helpers\comctl.h"
*@@added V0.9.3 (2000-05-21) [umoeller].
*/
/*
* Copyright (C) 1997-2000 Ulrich Möller.
* This file is part of the "XWorkplace helpers" source package.
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, in version 2 as it comes in the
* "COPYING" file of the XWorkplace main distribution.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define OS2EMX_PLAIN_CHAR
// this is needed for "os2emx.h"; if this is defined,
// emx will define PSZ as _signed_ char, otherwise
// as unsigned char
#define INCL_DOSEXCEPTIONS
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR
#define INCL_WINMESSAGEMGR
#define INCL_WININPUT
#define INCL_WINPOINTERS
#define INCL_WINTRACKRECT
#define INCL_WINTIMER
#define INCL_WINSYS
#define INCL_WINRECTANGLES /// xxx temporary
#define INCL_WINMENUS
#define INCL_WINSTATICS
#define INCL_WINBUTTONS
#define INCL_WINSTDCNR
#define INCL_GPIPRIMITIVES
#define INCL_GPILOGCOLORTABLE
#define INCL_GPILCIDS
#define INCL_GPIPATHS
#define INCL_GPIREGIONS
#define INCL_GPIBITMAPS // added V0.9.1 (2000-01-04) [umoeller]: needed for EMX headers
#include <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h> // needed for except.h
#include <assert.h> // needed for except.h
#include "setup.h" // code generation and debugging options
#include "helpers\cnrh.h"
#include "helpers\except.h" // exception handling
#include "helpers\gpih.h"
#include "helpers\linklist.h"
#include "helpers\winh.h"
#include "helpers\comctl.h"
#pragma hdrstop
/*
*@@category: Helpers\PM helpers\Window classes\Progress bars
* See cctl_progbar.c.
*/
/* ******************************************************************
*
* Progress bars
*
********************************************************************/
/*
*@@ PaintProgress:
* this does the actual painting of the progress bar, called
* from ctl_fnwpProgressBar.
* It is called both upon WM_PAINT and WM_UPDATEPROGRESSBAR
* with different HPS's then.
*
*@@added V0.9.0 [umoeller]
*@@changed V0.9.5 (2000-09-22) [umoeller]: fixed ypos of text
*/
static VOID PaintProgress(PPROGRESSBARDATA pData,
HWND hwndBar,
PRECTL prclWin, // in: window rectangle (WinQueryWindowRect)
HPS hps)
{
POINTL ptlText; // , aptlText[TXTBOX_COUNT];
BOOL fBackgroundPainted = FALSE;
CHAR szPercent[10] = "";
RECTL rclInnerButton;
LONG lcolScrollbar = WinQuerySysColor(HWND_DESKTOP,
SYSCLR_SCROLLBAR,
0);
// switch to RGB mode
gpihSwitchToRGB(hps);
if (pData->ulPaintX <= pData->ulOldPaintX)
{
RECTL rclOuterFrame; // inclusive
rclOuterFrame.xLeft = 0;
rclOuterFrame.yBottom = 0;
rclOuterFrame.xRight = prclWin->xRight - 1;
rclOuterFrame.yTop = prclWin->yTop - 1;
gpihDraw3DFrame(hps,
&rclOuterFrame, // inclusive
1,
WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0),
WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0));
rclOuterFrame.xLeft++;
rclOuterFrame.yBottom++;
WinFillRect(hps,
&rclOuterFrame, // exclusive, top right not drawn
lcolScrollbar);
fBackgroundPainted = TRUE;
}
// now draw the actual progress;
// rclInnerButton receives an _inclusive_ rectangle
rclInnerButton.xLeft = 1;
rclInnerButton.xRight = (pData->ulPaintX > (rclInnerButton.xLeft + 3))
? pData->ulPaintX
: rclInnerButton.xLeft +
((pData->ulAttr & PBA_BUTTONSTYLE)
? 3 : 1);
rclInnerButton.yBottom = 1;
rclInnerButton.yTop = prclWin->yTop // exclusive
- 2; // 1 to make inclusive, 1 for outer frame
if (pData->ulAttr & PBA_PERCENTFLAGS)
{
// percentage desired:
POINTL aptlText[TXTBOX_COUNT];
LONG lLineSpacing = 1;
FONTMETRICS fm;
if (GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm))
lLineSpacing = fm.lEmHeight;
sprintf(szPercent, "%lu %%", ((100 * pData->ulNow) / pData->ulMax) );
// calculate string space
GpiQueryTextBox(hps,
strlen(szPercent),
szPercent,
TXTBOX_COUNT,
(PPOINTL)&aptlText);
ptlText.x =
( ( (prclWin->xRight) // cx
- (aptlText[TXTBOX_BOTTOMRIGHT].x - aptlText[TXTBOX_BOTTOMLEFT].x)
)
/ 2);
ptlText.y =
( ( (prclWin->yTop) // cy
- (lLineSpacing)
)
/ 2) + 2;
if (!fBackgroundPainted)
{
// if we haven't drawn the background already,
// we'll need to do it now for the percentage area
RECTL rcl2;
rcl2.xLeft = ptlText.x;
rcl2.xRight = ptlText.x + (aptlText[TXTBOX_BOTTOMRIGHT].x-aptlText[TXTBOX_BOTTOMLEFT].x);
rcl2.yBottom = ptlText.y;
rcl2.yTop = ptlText.y + lLineSpacing;
WinFillRect(hps,
&rcl2,
lcolScrollbar);
}
}
if (pData->ulAttr & PBA_BUTTONSTYLE)
{
// draw "raised" inner rect
gpihDraw3DFrame(hps,
&rclInnerButton,
2,
WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0),
WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0));
}
rclInnerButton.xLeft += 2;
rclInnerButton.yBottom += 2;
rclInnerButton.yTop -= 2;
rclInnerButton.xRight -= 2;
if (rclInnerButton.xRight > rclInnerButton.xLeft)
{
POINTL ptl1;
// draw interior of inner rect
GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
SYSCLR_BUTTONMIDDLE,
0));
ptl1.x = rclInnerButton.xLeft;
ptl1.y = rclInnerButton.yBottom;
GpiMove(hps, &ptl1);
ptl1.x = rclInnerButton.xRight;
ptl1.y = rclInnerButton.yTop;
GpiBox(hps,
DRO_FILL | DRO_OUTLINE,
&ptl1, // inclusive!
0,
0);
}
// now print the percentage
if (pData->ulAttr & PBA_PERCENTFLAGS)
{
GpiMove(hps, &ptlText);
GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
SYSCLR_BUTTONDEFAULT,
0));
GpiCharString(hps, strlen(szPercent), szPercent);
}
// store current X position for next time
pData->ulOldPaintX = pData->ulPaintX;
}
/*
*@@ ctl_fnwpProgressBar:
* this is the window procedure for the progress bar control.
*
* This is not a stand-alone window procedure, but must only
* be used with static rectangle controls subclassed by
* ctlProgressBarFromStatic.
*
* We need to capture WM_PAINT to draw the progress bar according
* to the current progress, and we also update the static text field
* (percentage) next to it.
*
* This also evaluates the WM_UPDATEPROGRESSBAR message.
*
*@@changed V0.9.0 [umoeller]: moved this code here
*@@changed V0.9.1 (99-12-06): fixed memory leak
*/
MRESULT EXPENTRY ctl_fnwpProgressBar(HWND hwndBar, ULONG msg, MPARAM mp1, MPARAM mp2)
{
HPS hps;
PPROGRESSBARDATA ppd = (PPROGRESSBARDATA)WinQueryWindowULong(hwndBar, QWL_USER);
PFNWP OldStaticProc = NULL;
MRESULT mrc = NULL;
if (ppd)
{
OldStaticProc = ppd->OldStaticProc;
switch(msg)
{
/*
*@@ WM_UPDATEPROGRESSBAR:
* post or send this message to a progress bar
* to have a new progress displayed.
* Parameters:
* -- ULONG mp1 current value
* -- ULONG mp2 max value
* Example: mp1 = 100, mp2 = 300 will result
* in a progress of 33%.
*/
case WM_UPDATEPROGRESSBAR:
{
RECTL rclWin;
WinQueryWindowRect(hwndBar, &rclWin);
if ( (ppd->ulNow != (ULONG)mp1)
|| (ppd->ulMax != (ULONG)mp2)
)
{
ppd->ulNow = (ULONG)mp1;
ppd->ulMax = (ULONG)mp2;
}
else
// value not changed: do nothing
break;
// check validity
if (ppd->ulNow > ppd->ulMax)
ppd->ulNow = ppd->ulMax;
// avoid division by zero
if (ppd->ulMax == 0)
{
ppd->ulMax = 1;
ppd->ulNow = 0;
// paint 0% then
}
// calculate new X position of the progress
ppd->ulPaintX =
(ULONG)(
( (ULONG)(rclWin.xRight - rclWin.xLeft - 2)
* (ULONG)(ppd->ulNow)
)
/ (ULONG)ppd->ulMax
);
if (ppd->ulPaintX != ppd->ulOldPaintX)
{
// X position changed: redraw
// WinInvalidateRect(hwndBar, NULL, FALSE);
hps = WinGetPS(hwndBar);
PaintProgress(ppd, hwndBar, &rclWin, hps);
WinReleasePS(hps);
}
break; }
case WM_PAINT:
{
RECTL rclWin;
WinQueryWindowRect(hwndBar, &rclWin);
hps = WinBeginPaint(hwndBar, NULLHANDLE, NULL);
PaintProgress(ppd, hwndBar, &rclWin, hps);
WinEndPaint(hps);
break; }
/*
* WM_DESTROY:
* free PROGRESSBARDATA
* (added V0.9.1 (99-12-06))
*/
case WM_DESTROY:
{
free(ppd);
mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
break; }
default:
mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
}
}
return mrc;
}
/*
*@@ ctlProgressBarFromStatic:
* this function turns an existing static rectangle control
* into a progress bar by subclassing its window procedure
* with ctl_fnwpProgressBar.
*
* This way you can easily create a progress bar as a static
* control in any Dialog Editor; after loading the dlg template,
* simply call this function with the hwnd of the static control
* to make it a status bar.
*
* This is used for all the progress bars in XWorkplace and
* WarpIN.
*
* In order to _update_ the progress bar, simply post or send
* WM_UPDATEPROGRESSBAR to the static (= progress bar) window;
* this message is equal to WM_USER and needs the following
* parameters:
* -- mp1 ULONG ulNow: the current progress
* -- mp2 ULONG ulMax: the maximally possible progress
* (= 100%)
*
* The progress bar automatically calculates the current progress
* display. For example, if ulNow = 4096 and ulMax = 8192,
* a progress of 50% will be shown. It is possible to change
* ulMax after the progress bar has started display. If ulMax
* is 0, a progress of 0% will be shown (to avoid division
* by zero traps).
*
* ulAttr accepts of the following:
* -- PBA_NOPERCENTAGE: do not display percentage
* -- PBA_ALIGNLEFT: left-align percentage
* -- PBA_ALIGNRIGHT: right-align percentage
* -- PBA_ALIGNCENTER: center percentage
* -- PBA_BUTTONSTYLE: no "flat", but button-like look
*
*@@changed V0.9.0 [umoeller]: moved this code here
*/
BOOL ctlProgressBarFromStatic(HWND hwndChart, ULONG ulAttr)
{
PFNWP OldStaticProc;
if (OldStaticProc = WinSubclassWindow(hwndChart, ctl_fnwpProgressBar))
{
PPROGRESSBARDATA pData = (PPROGRESSBARDATA)malloc(sizeof(PROGRESSBARDATA));
pData->ulMax = 1;
pData->ulNow = 0;
pData->ulPaintX = 0;
pData->ulAttr = ulAttr;
pData->OldStaticProc = OldStaticProc;
WinSetWindowULong(hwndChart, QWL_USER, (ULONG)pData);
return (TRUE);
}
return (FALSE);
}