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

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

Tons of updates.

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