source: branches/branch-1-0/src/helpers/cctl_progbar.c

Last change on this file was 222, checked in by umoeller, 23 years ago

Minor adjustments for new static handling.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
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
103STATIC 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
263MRESULT 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
401BOOL 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
Note: See TracBrowser for help on using the repository browser.