source: trunk/src/helpers/cctl_progbar.c@ 14

Last change on this file since 14 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 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 */
84
85/* ******************************************************************
86 *
87 * Progress bars
88 *
89 ********************************************************************/
90
91/*
92 *@@ PaintProgress:
93 * this does the actual painting of the progress bar, called
94 * from ctl_fnwpProgressBar.
95 * It is called both upon WM_PAINT and WM_UPDATEPROGRESSBAR
96 * with different HPS's then.
97 *
98 *@@added V0.9.0 [umoeller]
99 *@@changed V0.9.5 (2000-09-22) [umoeller]: fixed ypos of text
100 */
101
102VOID PaintProgress(PPROGRESSBARDATA pData, HWND hwndBar, HPS hps)
103{
104 POINTL ptl1, ptlText, aptlText[TXTBOX_COUNT];
105 RECTL rcl, rcl2;
106
107 CHAR szPercent[10] = "";
108
109 // switch to RGB mode
110 GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL);
111
112 if (pData->ulPaintX <= pData->ulOldPaintX)
113 {
114 // draw frame and background only if this is either
115 // a "real" WM_PAINT (i.e., the window was overlapped
116 // and needs repainting; then ulPaintX == ulOldPaintX)
117 // or if ulNow has _de_creased
118 GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0));
119 ptl1.x = 0;
120 ptl1.y = 0;
121 GpiMove(hps, &ptl1);
122 ptl1.y = (pData->rclBar.yTop);
123 GpiLine(hps, &ptl1);
124 ptl1.x = (pData->rclBar.xRight);
125 GpiLine(hps, &ptl1);
126 GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0));
127 ptl1.y = 0;
128 GpiLine(hps, &ptl1);
129 ptl1.x = 0;
130 GpiLine(hps, &ptl1);
131
132 pData->rclBar.xLeft = 1;
133 pData->rclBar.yBottom = 1;
134 WinFillRect(hps, &(pData->rclBar),
135 WinQuerySysColor(HWND_DESKTOP, SYSCLR_SCROLLBAR, 0));
136 }
137
138 // draw percentage?
139 if (pData->ulAttr & PBA_PERCENTFLAGS)
140 {
141 // make string
142 sprintf(szPercent, "%lu %%", ((100 * pData->ulNow) / pData->ulMax) );
143
144 // calculate string space
145 GpiQueryTextBox(hps, strlen(szPercent), szPercent,
146 TXTBOX_COUNT, (PPOINTL)&aptlText);
147
148 // calculate coordinates
149 ptlText.x = pData->rclBar.xLeft +
150 ( ( (pData->rclBar.xRight-pData->rclBar.xLeft)
151 - (aptlText[TXTBOX_BOTTOMRIGHT].x-aptlText[TXTBOX_BOTTOMLEFT].x)
152 )
153 / 2);
154 ptlText.y = 2 + pData->rclBar.yBottom + // fixed V0.9.5 (2000-09-22) [umoeller]
155 ( ( (pData->rclBar.yTop-pData->rclBar.yBottom)
156 - (aptlText[TXTBOX_TOPLEFT].y-aptlText[TXTBOX_BOTTOMLEFT].y)
157 )
158 / 2);
159
160 // do we need to repaint the background under the percentage?
161 if ( ( (ptlText.x
162 + ( aptlText[TXTBOX_BOTTOMRIGHT].x
163 - aptlText[TXTBOX_BOTTOMLEFT].x)
164 )
165 > pData->ulPaintX)
166 && (pData->ulPaintX > pData->ulOldPaintX)
167 )
168 {
169 // if we haven't drawn the background already,
170 // we'll need to do it now for the percentage area
171 rcl.xLeft = ptlText.x;
172 rcl.xRight = ptlText.x + (aptlText[TXTBOX_BOTTOMRIGHT].x-aptlText[TXTBOX_BOTTOMLEFT].x);
173 rcl.yBottom = ptlText.y;
174 rcl.yTop = ptlText.y + (aptlText[TXTBOX_TOPLEFT].y-aptlText[TXTBOX_BOTTOMLEFT].y);
175 WinFillRect(hps, &rcl,
176 WinQuerySysColor(HWND_DESKTOP, SYSCLR_SCROLLBAR, 0));
177 }
178 }
179
180 // now draw the actual progress
181 rcl2.xLeft = pData->rclBar.xLeft;
182 rcl2.xRight = (pData->ulPaintX > (rcl2.xLeft + 3))
183 ? pData->ulPaintX
184 : rcl2.xLeft + ((pData->ulAttr & PBA_BUTTONSTYLE)
185 ? 3 : 1);
186 rcl2.yBottom = pData->rclBar.yBottom;
187 rcl2.yTop = pData->rclBar.yTop-1;
188
189 if (pData->ulAttr & PBA_BUTTONSTYLE)
190 {
191 RECTL rcl3 = rcl2;
192 // draw "raised" inner rect
193 rcl3.xLeft = rcl2.xLeft;
194 rcl3.yBottom = rcl2.yBottom;
195 rcl3.yTop = rcl2.yTop+1;
196 rcl3.xRight = rcl2.xRight+1;
197 gpihDraw3DFrame(hps, &rcl3, 2,
198 WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0),
199 WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0));
200 // WinInflateRect(WinQueryAnchorBlock(hwndBar), &rcl2, -2, -2);
201 rcl2.xLeft += 2;
202 rcl2.yBottom += 2;
203 rcl2.yTop -= 2;
204 rcl2.xRight -= 2;
205 }
206
207 if (rcl2.xRight > rcl2.xLeft)
208 {
209 GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
210 // SYSCLR_HILITEBACKGROUND,
211 SYSCLR_BUTTONMIDDLE,
212 0));
213 ptl1.x = rcl2.xLeft;
214 ptl1.y = rcl2.yBottom;
215 GpiMove(hps, &ptl1);
216 ptl1.x = rcl2.xRight;
217 ptl1.y = rcl2.yTop;
218 GpiBox(hps, DRO_FILL | DRO_OUTLINE,
219 &ptl1,
220 0,
221 0);
222 }
223
224 // now print the percentage
225 if (pData->ulAttr & PBA_PERCENTFLAGS)
226 {
227 GpiMove(hps, &ptlText);
228 GpiSetColor(hps, WinQuerySysColor(HWND_DESKTOP,
229 // SYSCLR_HILITEFOREGROUND,
230 SYSCLR_BUTTONDEFAULT,
231 0));
232 GpiCharString(hps, strlen(szPercent), szPercent);
233 }
234
235 // store current X position for next time
236 pData->ulOldPaintX = pData->ulPaintX;
237}
238
239/*
240 *@@ ctl_fnwpProgressBar:
241 * this is the window procedure for the progress bar control.
242 *
243 * This is not a stand-alone window procedure, but must only
244 * be used with static rectangle controls subclassed by
245 * ctlProgressBarFromStatic.
246 *
247 * We need to capture WM_PAINT to draw the progress bar according
248 * to the current progress, and we also update the static text field
249 * (percentage) next to it.
250 *
251 * This also evaluates the WM_UPDATEPROGRESSBAR message.
252 *
253 *@@changed V0.9.0 [umoeller]: moved this code here
254 *@@changed V0.9.1 (99-12-06): fixed memory leak
255 */
256
257MRESULT EXPENTRY ctl_fnwpProgressBar(HWND hwndBar, ULONG msg, MPARAM mp1, MPARAM mp2)
258{
259 HPS hps;
260 PPROGRESSBARDATA ppd = (PPROGRESSBARDATA)WinQueryWindowULong(hwndBar, QWL_USER);
261
262 PFNWP OldStaticProc = NULL;
263
264 MRESULT mrc = NULL;
265
266 if (ppd)
267 {
268 OldStaticProc = ppd->OldStaticProc;
269
270 switch(msg)
271 {
272
273 /*
274 *@@ WM_UPDATEPROGRESSBAR:
275 * post or send this message to a progress bar
276 * to have a new progress displayed.
277 * Parameters:
278 * -- ULONG mp1 current value
279 * -- ULONG mp2 max value
280 * Example: mp1 = 100, mp2 = 300 will result
281 * in a progress of 33%.
282 */
283
284 case WM_UPDATEPROGRESSBAR:
285 {
286 if ( (ppd->ulNow != (ULONG)mp1)
287 || (ppd->ulMax != (ULONG)mp2)
288 )
289 {
290 ppd->ulNow = (ULONG)mp1;
291 ppd->ulMax = (ULONG)mp2;
292 }
293 else
294 // value not changed: do nothing
295 break;
296
297 // check validity
298 if (ppd->ulNow > ppd->ulMax)
299 ppd->ulNow = ppd->ulMax;
300 // avoid division by zero
301 if (ppd->ulMax == 0)
302 {
303 ppd->ulMax = 1;
304 ppd->ulNow = 0;
305 // paint 0% then
306 }
307
308 // calculate new X position of the progress
309 ppd->ulPaintX =
310 (ULONG)(
311 ( (ULONG)(ppd->rclBar.xRight - ppd->rclBar.xLeft)
312 * (ULONG)(ppd->ulNow)
313 )
314 / (ULONG)ppd->ulMax
315 );
316 if (ppd->ulPaintX != ppd->ulOldPaintX)
317 {
318 // X position changed: redraw
319 // WinInvalidateRect(hwndBar, NULL, FALSE);
320 hps = WinGetPS(hwndBar);
321 PaintProgress(ppd, hwndBar, hps);
322 WinReleasePS(hps);
323 }
324 break; }
325
326 case WM_PAINT:
327 {
328 RECTL rcl;
329 hps = WinBeginPaint(hwndBar, NULLHANDLE, &rcl);
330 PaintProgress(ppd, hwndBar, hps);
331 WinEndPaint(hps);
332 break; }
333
334 /*
335 * WM_DESTROY:
336 * free PROGRESSBARDATA
337 * (added V0.9.1 (99-12-06))
338 */
339
340 case WM_DESTROY:
341 {
342 free(ppd);
343 mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
344 break; }
345
346 default:
347 mrc = OldStaticProc(hwndBar, msg, mp1, mp2);
348 }
349 }
350 return (mrc);
351}
352
353/*
354 *@@ ctlProgressBarFromStatic:
355 * this function turns an existing static rectangle control
356 * into a progress bar by subclassing its window procedure
357 * with ctl_fnwpProgressBar.
358 *
359 * This way you can easily create a progress bar as a static
360 * control in any Dialog Editor; after loading the dlg template,
361 * simply call this function with the hwnd of the static control
362 * to make it a status bar.
363 *
364 * This is used for all the progress bars in XWorkplace and
365 * WarpIN.
366 *
367 * In order to _update_ the progress bar, simply post or send
368 * WM_UPDATEPROGRESSBAR to the static (= progress bar) window;
369 * this message is equal to WM_USER and needs the following
370 * parameters:
371 * -- mp1 ULONG ulNow: the current progress
372 * -- mp2 ULONG ulMax: the maximally possible progress
373 * (= 100%)
374 *
375 * The progress bar automatically calculates the current progress
376 * display. For example, if ulNow = 4096 and ulMax = 8192,
377 * a progress of 50% will be shown. It is possible to change
378 * ulMax after the progress bar has started display. If ulMax
379 * is 0, a progress of 0% will be shown (to avoid division
380 * by zero traps).
381 *
382 * ulAttr accepts of the following:
383 * -- PBA_NOPERCENTAGE: do not display percentage
384 * -- PBA_ALIGNLEFT: left-align percentage
385 * -- PBA_ALIGNRIGHT: right-align percentage
386 * -- PBA_ALIGNCENTER: center percentage
387 * -- PBA_BUTTONSTYLE: no "flat", but button-like look
388 *
389 *@@changed V0.9.0 [umoeller]: moved this code here
390 */
391
392BOOL ctlProgressBarFromStatic(HWND hwndChart, ULONG ulAttr)
393{
394 PFNWP OldStaticProc = WinSubclassWindow(hwndChart, ctl_fnwpProgressBar);
395 if (OldStaticProc)
396 {
397 PPROGRESSBARDATA pData = (PPROGRESSBARDATA)malloc(sizeof(PROGRESSBARDATA));
398 pData->ulMax = 1;
399 pData->ulNow = 0;
400 pData->ulPaintX = 0;
401 pData->ulAttr = ulAttr;
402 pData->OldStaticProc = OldStaticProc;
403 WinQueryWindowRect(hwndChart, &(pData->rclBar));
404 (pData->rclBar.xRight)--;
405 (pData->rclBar.yTop)--;
406
407 WinSetWindowULong(hwndChart, QWL_USER, (ULONG)pData);
408 return (TRUE);
409 }
410 else return (FALSE);
411}
412
413
Note: See TracBrowser for help on using the repository browser.