source: trunk/src/comctl32/progress.c@ 2523

Last change on this file since 2523 was 2523, checked in by cbratschi, 26 years ago

added API logging, removed progress frame

File size: 15.6 KB
Line 
1/* $Id: progress.c,v 1.12 2000-01-26 18:04:29 cbratschi Exp $ */
2/*
3 * Progress control
4 *
5 * Copyright 1997 Dimitrie O. Paun
6 * Copyright 1998, 1999 Eric Kohl
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 *
10 * Status: complete
11 * Version: 5.00
12 */
13
14#include "winbase.h"
15#include "commctrl.h"
16#include "progress.h"
17#include "comctl32.h"
18
19
20/* Control configuration constants */
21
22#define LED_GAP 2
23#define BORDER_WIDTH 1
24
25/* Work constants */
26
27//#define UNKNOWN_PARAM(msg, wParam, lParam) WARN(progress, \
28// "Unknown parameter(s) for message " #msg \
29// "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
30//#define UNKNOWN_PARAM(msg, wParam, lParam)
31
32#define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd,0))
33
34
35/***********************************************************************
36 * PROGRESS_Draw
37 * Draws the progress bar.
38 */
39static void
40PROGRESS_Draw (HWND hwnd, HDC hdc, INT lastVal, BOOL inUpdate)
41{
42 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
43 HBRUSH hbrBar,hbrBk,hbrLight,hbrShadow,hbrOld;
44 int rightBar, rightMost, ledWidth;
45 int lastBar;
46 RECT rect;
47 DWORD dwStyle;
48
49// TRACE(progress, "refresh pos=%d min=%d, max=%d\n",
50// infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
51
52 if (infoPtr->MinVal == infoPtr->MaxVal) return; //Prevent division through 0
53
54 /* get the required bar brush */
55 if (infoPtr->ColorBar == CLR_DEFAULT) hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
56 else hbrBar = CreateSolidBrush (infoPtr->ColorBar);
57
58 /* get the required background brush */
59 if (infoPtr->ColorBk == CLR_DEFAULT) hbrBk = GetSysColorBrush(COLOR_3DFACE);
60 else hbrBk = CreateSolidBrush(infoPtr->ColorBk);
61
62 /* get client rectangle */
63 GetClientRect (hwnd, &rect);
64
65 /* draw the background */
66 if (!inUpdate) FillRect(hdc, &rect, hbrBk);
67
68 rect.left += BORDER_WIDTH;
69 rect.right -= BORDER_WIDTH;
70 rect.top += BORDER_WIDTH;
71 rect.bottom -= BORDER_WIDTH;
72
73 /* get the window style */
74 dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
75
76 /* compute extent of progress bar */
77 if (dwStyle & PBS_VERTICAL)
78 {
79 rightBar = rect.bottom-MulDiv(infoPtr->CurVal-infoPtr->MinVal,rect.bottom-rect.top,infoPtr->MaxVal-infoPtr->MinVal);
80 if (inUpdate) lastBar = rect.bottom-MulDiv(lastVal-infoPtr->MinVal,rect.bottom-rect.top,infoPtr->MaxVal-infoPtr->MinVal);
81 ledWidth = MulDiv ((rect.right - rect.left), 2, 3);
82 rightMost = rect.top;
83 }
84 else
85 {
86 rightBar = rect.left+MulDiv(infoPtr->CurVal-infoPtr->MinVal,rect.right-rect.left,infoPtr->MaxVal-infoPtr->MinVal);
87 if (inUpdate) lastBar = rect.left+MulDiv(lastVal-infoPtr->MinVal,rect.right-rect.left,infoPtr->MaxVal-infoPtr->MinVal);
88 ledWidth = MulDiv ((rect.bottom - rect.top), 2, 3);
89 rightMost = rect.right;
90 }
91
92 /* now draw the bar */
93 if (dwStyle & PBS_SMOOTH)
94 {
95 if (dwStyle & PBS_VERTICAL)
96 {
97 if (inUpdate)
98 {
99 if (infoPtr->CurVal > lastVal)
100 {
101 rect.top = rightBar;
102 rect.bottom = lastBar;
103 FillRect(hdc,&rect,hbrBar);
104 } else if (infoPtr->CurVal < lastVal)
105 {
106 rect.top = lastBar;
107 rect.bottom = rightBar;
108 FillRect(hdc,&rect,hbrBk);
109 }
110 } else
111 {
112 rect.top = rightBar;
113 FillRect(hdc,&rect,hbrBar);
114 }
115 } else //Horizontal
116 {
117 if (inUpdate)
118 {
119 if (infoPtr->CurVal > lastVal)
120 {
121 rect.left = lastBar;
122 rect.right = rightBar;
123 FillRect(hdc,&rect,hbrBar);
124 } else if (infoPtr->CurVal < lastVal)
125 {
126 rect.left = rightBar;
127 rect.right = lastBar;
128 FillRect(hdc,&rect,hbrBk);
129 }
130 } else
131 {
132 rect.right = rightBar;
133 FillRect(hdc,&rect,hbrBar);
134 }
135 }
136 } else
137 {
138 if (dwStyle & PBS_VERTICAL)
139 {
140 if (inUpdate)
141 {
142 if (infoPtr->CurVal > lastVal)
143 {
144 rect.bottom -= ((int)(rect.bottom-lastBar)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP);
145 while(rect.bottom > rightBar)
146 {
147 rect.top = rect.bottom-ledWidth;
148 if (rect.top < rightMost) rect.top = rightMost;
149 FillRect(hdc,&rect,hbrBar);
150 rect.bottom = rect.top-LED_GAP;
151 }
152 } else if (infoPtr->CurVal < lastVal)
153 {
154 rect.top = rect.bottom-((int)(rect.bottom-lastBar)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP)-ledWidth;
155 if (rect.top < rightMost) rect.top = rightMost;
156 rect.bottom -= ((int)(rect.bottom-rightBar)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP);
157 FillRect(hdc,&rect,hbrBk);
158 }
159 } else
160 {
161 while(rect.bottom > rightBar)
162 {
163 rect.top = rect.bottom-ledWidth;
164 if (rect.top < rightMost) rect.top = rightMost;
165 FillRect(hdc,&rect,hbrBar);
166 rect.bottom = rect.top-LED_GAP;
167 }
168 }
169 } else //Horizontal
170 {
171 if (inUpdate)
172 {
173 if (infoPtr->CurVal > lastVal)
174 {
175 rect.left += ((int)(lastBar-rect.left)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP);
176 while(rect.left < rightBar)
177 {
178 rect.right = rect.left+ledWidth;
179 if (rect.right > rightMost) rect.right = rightMost;
180 FillRect(hdc,&rect,hbrBar);
181 rect.left = rect.right+LED_GAP;
182 }
183 } else if (infoPtr->CurVal < lastVal)
184 {
185 rect.right = rect.left+((int)(lastBar-rect.left)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP)+ledWidth;
186 if (rect.right > rightMost) rect.right = rightMost;
187 rect.left += ((int)(rightBar-rect.left)/(ledWidth+LED_GAP))*(ledWidth+LED_GAP);
188 FillRect(hdc,&rect,hbrBk);
189 }
190 } else
191 {
192 while(rect.left < rightBar)
193 {
194 rect.right = rect.left+ledWidth;
195 if (rect.right > rightMost) rect.right = rightMost;
196 FillRect(hdc,&rect,hbrBar);
197 rect.left = rect.right+LED_GAP;
198 }
199 }
200 }
201 }
202
203 /* delete bar brush */
204 if (infoPtr->ColorBar != CLR_DEFAULT) DeleteObject (hbrBar);
205
206 /* delete background brush */
207 if (infoPtr->ColorBk != CLR_DEFAULT) DeleteObject (hbrBk);
208}
209
210/***********************************************************************
211 * PROGRESS_Update (prototype, todo)
212 * Updates only the changed pixels -> faster, no flickering
213 */
214static void PROGRESS_Update(HWND hwnd,INT lastVal)
215{
216 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
217 HDC hdc;
218
219 if (lastVal != infoPtr->CurVal) //Only update if really necessary
220 {
221 hdc = GetDC(hwnd);
222 PROGRESS_Draw(hwnd,hdc,lastVal,TRUE);
223 ReleaseDC(hwnd,hdc);
224 }
225}
226
227/***********************************************************************
228 * PROGRESS_Refresh
229 * Draw the progress bar. The background need not be erased.
230 */
231static void
232PROGRESS_Refresh (HWND hwnd)
233{
234 HDC hdc;
235
236 hdc = GetDC (hwnd);
237 PROGRESS_Draw (hwnd, hdc, 0, FALSE);
238 ReleaseDC (hwnd, hdc);
239}
240
241/***********************************************************************
242 * PROGRESS_Paint
243 * Draw the progress bar. The background need not be erased.
244 * If dc!=0, it draws on it
245 */
246static void
247PROGRESS_Paint (HWND hwnd)
248{
249 PAINTSTRUCT ps;
250 HDC hdc;
251
252 hdc = BeginPaint (hwnd, &ps);
253 PROGRESS_Draw (hwnd, hdc, 0, FALSE);
254 EndPaint (hwnd, &ps);
255}
256
257
258/***********************************************************************
259 * PROGRESS_CoercePos
260 * Makes sure the current position (CUrVal) is within bounds.
261 */
262static void PROGRESS_CoercePos(HWND hwnd)
263{
264 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
265
266 if(infoPtr->CurVal < infoPtr->MinVal)
267 infoPtr->CurVal = infoPtr->MinVal;
268 if(infoPtr->CurVal > infoPtr->MaxVal)
269 infoPtr->CurVal = infoPtr->MaxVal;
270}
271
272
273static LRESULT PROGRESS_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
274{
275 DWORD dwExStyle;
276
277 dwExStyle = GetWindowLongA(hwnd,GWL_EXSTYLE);
278 SetWindowLongA(hwnd,GWL_EXSTYLE,dwExStyle | WS_EX_STATICEDGE);
279
280 return TRUE;
281}
282
283static LRESULT PROGRESS_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
284{
285 PROGRESS_INFO *infoPtr;
286
287 /* allocate memory for info struct */
288 infoPtr = (PROGRESS_INFO *)COMCTL32_Alloc(sizeof(PROGRESS_INFO));
289 SetWindowLongA(hwnd,0,(DWORD)infoPtr);
290
291 /* initialize the info struct */
292 infoPtr->MinVal = 0;
293 infoPtr->MaxVal = 100;
294 infoPtr->CurVal = 0;
295 infoPtr->Step = 10;
296 infoPtr->ColorBar = CLR_DEFAULT;
297 infoPtr->ColorBk = CLR_DEFAULT;
298 infoPtr->hFont = (HANDLE)NULL;
299// TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
300
301 return 0;
302}
303
304static LRESULT PROGRESS_Destroy(HWND hwnd,WPARAM wParam,LPARAM lParam)
305{
306 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
307
308 // TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
309 COMCTL32_Free (infoPtr);
310
311 return 0;
312}
313
314static LRESULT PROGRESS_GetFont(HWND hwnd,WPARAM wParam,LPARAM lParam)
315{
316 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
317
318 return (LRESULT)infoPtr->hFont;
319}
320
321/***********************************************************************
322 * PROGRESS_SetFont
323 * Set new Font for progress bar
324 */
325static HFONT PROGRESS_SetFont (HWND hwnd,WPARAM wParam,LPARAM lParam)
326{
327 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
328 HFONT hOldFont = infoPtr->hFont;
329
330 infoPtr->hFont = (HFONT)wParam;
331 if (LOWORD(lParam)) PROGRESS_Refresh (hwnd);
332
333 return hOldFont;
334}
335
336static LRESULT PROGRESS_DeltaPos(HWND hwnd,WPARAM wParam,LPARAM lParam)
337{
338 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
339 INT temp;
340
341 //if(lParam) UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
342 temp = infoPtr->CurVal;
343 if (wParam != 0)
344 {
345 infoPtr->CurVal += (INT)wParam;
346 PROGRESS_CoercePos(hwnd);
347 PROGRESS_Update(hwnd,temp);
348 }
349
350 return temp;
351}
352
353static LRESULT PROGRESS_SetPos(HWND hwnd,WPARAM wParam,LPARAM lParam)
354{
355 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
356 INT temp;
357
358 //if (lParam) UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
359 temp = infoPtr->CurVal;
360 if (temp != wParam)
361 {
362 infoPtr->CurVal = (UINT16)wParam; //CB: 0..65535 allowed
363 PROGRESS_CoercePos(hwnd);
364 PROGRESS_Update(hwnd,temp);
365 }
366
367 return temp;
368}
369
370static LRESULT PROGRESS_SetRange(HWND hwnd,WPARAM wParam,LPARAM lParam)
371{
372 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
373 INT temp;
374
375 //if (wParam) UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
376 temp = MAKELONG(infoPtr->MinVal,infoPtr->MaxVal);
377 if (temp != lParam)
378 {
379 infoPtr->MinVal = LOWORD(lParam);
380 infoPtr->MaxVal = HIWORD(lParam);
381 if (infoPtr->MaxVal <= infoPtr->MinVal) infoPtr->MaxVal = infoPtr->MinVal+1;
382 PROGRESS_CoercePos(hwnd);
383 PROGRESS_Refresh(hwnd);
384 }
385
386 return temp;
387}
388
389static LRESULT PROGRESS_SetStep(HWND hwnd,WPARAM wParam,LPARAM lParam)
390{
391 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
392 INT temp;
393
394 //if (lParam) UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
395 temp = infoPtr->Step;
396 infoPtr->Step = (INT)wParam; //CB: negative steps allowed
397
398 return temp;
399}
400
401static LRESULT PROGRESS_StepIt(HWND hwnd,WPARAM wParam,LPARAM lParam)
402{
403 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
404 INT temp;
405
406 //if (wParam || lParam) UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
407 temp = infoPtr->CurVal;
408 infoPtr->CurVal += infoPtr->Step;
409 if(infoPtr->CurVal > infoPtr->MaxVal) infoPtr->CurVal = infoPtr->MinVal;
410 if(temp != infoPtr->CurVal) PROGRESS_Update (hwnd,temp);
411
412 return temp;
413}
414
415static LRESULT PROGRESS_SetRange32(HWND hwnd,WPARAM wParam,LPARAM lParam)
416{
417 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
418 INT temp;
419
420 temp = MAKELONG(infoPtr->MinVal,infoPtr->MaxVal);
421 if((infoPtr->MinVal != (INT)wParam) || (infoPtr->MaxVal != (INT)lParam))
422 {
423 infoPtr->MinVal = (INT)wParam;
424 infoPtr->MaxVal = (INT)lParam;
425 if(infoPtr->MaxVal <= infoPtr->MinVal) infoPtr->MaxVal = infoPtr->MinVal+1;
426 PROGRESS_CoercePos(hwnd);
427 PROGRESS_Refresh(hwnd);
428 }
429
430 return temp;
431}
432
433static LRESULT PROGRESS_GetRange(HWND hwnd,WPARAM wParam,LPARAM lParam)
434{
435 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
436
437 if (lParam)
438 {
439 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
440 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
441 }
442
443 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
444}
445
446static LRESULT PROGRESS_GetPos(HWND hwnd,WPARAM wParam,LPARAM lParam)
447{
448 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
449
450 //if (wParam || lParam) UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
451
452 return (infoPtr->CurVal);
453}
454
455static LRESULT PROGRESS_SetBarColor(HWND hwnd,WPARAM wParam,LPARAM lParam)
456{
457 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
458 COLORREF oldColorBar = infoPtr->ColorBar;
459
460 //if (wParam) UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
461 infoPtr->ColorBar = (COLORREF)lParam;
462 if (infoPtr->ColorBar != oldColorBar) PROGRESS_Refresh(hwnd);
463
464 return 0;
465}
466
467static LRESULT PROGRESS_SetBkColor(HWND hwnd,WPARAM wParam,LPARAM lParam)
468{
469 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
470 COLORREF oldColorBk = infoPtr->ColorBk;
471
472 //if (wParam) UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
473 infoPtr->ColorBk = (COLORREF)lParam;
474 if (infoPtr->ColorBk != oldColorBk) PROGRESS_Refresh (hwnd);
475
476 return 0;
477}
478
479/***********************************************************************
480 * ProgressWindowProc
481 */
482static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
483 WPARAM wParam, LPARAM lParam)
484{
485 switch(message)
486 {
487 case WM_NCCREATE:
488 return PROGRESS_NCCreate(hwnd,wParam,lParam);
489
490 case WM_CREATE:
491 return PROGRESS_Create(hwnd,wParam,lParam);
492
493 case WM_DESTROY:
494 return PROGRESS_Destroy(hwnd,wParam,lParam);
495
496 case WM_ERASEBKGND:
497 /* pretend to erase it here, but we will do it in the paint
498 function to avoid flicker */
499 return 1;
500
501 case WM_GETFONT:
502 return PROGRESS_GetFont(hwnd,wParam,lParam);
503
504 case WM_SETFONT:
505 return PROGRESS_SetFont (hwnd,wParam,lParam);
506
507 case WM_PAINT:
508 PROGRESS_Paint(hwnd);
509 break;
510
511 case PBM_DELTAPOS:
512 return PROGRESS_DeltaPos(hwnd,wParam,lParam);
513
514 case PBM_SETPOS:
515 return PROGRESS_SetPos(hwnd,wParam,lParam);
516
517 case PBM_SETRANGE:
518 return PROGRESS_SetRange(hwnd,wParam,lParam);
519
520 case PBM_SETSTEP:
521 return PROGRESS_SetStep(hwnd,wParam,lParam);
522
523 case PBM_STEPIT:
524 return PROGRESS_StepIt(hwnd,wParam,lParam);
525
526 case PBM_SETRANGE32:
527 return PROGRESS_SetRange32(hwnd,wParam,lParam);
528
529 case PBM_GETRANGE:
530 return PROGRESS_GetRange(hwnd,wParam,lParam);
531
532 case PBM_GETPOS:
533 return PROGRESS_GetPos(hwnd,wParam,lParam);
534
535 case PBM_SETBARCOLOR:
536 return PROGRESS_SetBarColor(hwnd,wParam,lParam);
537
538 case PBM_SETBKCOLOR:
539 return PROGRESS_SetBkColor(hwnd,wParam,lParam);
540
541 default:
542// if (message >= WM_USER)
543// ERR(progress, "unknown msg %04x wp=%04x lp=%08lx\n",
544// message, wParam, lParam );
545 return DefWindowProcA( hwnd, message, wParam, lParam );
546 }
547
548 return 0;
549}
550
551
552/***********************************************************************
553 * PROGRESS_Register [Internal]
554 *
555 * Registers the progress bar window class.
556 */
557
558VOID
559PROGRESS_Register (VOID)
560{
561 WNDCLASSA wndClass;
562
563//SvL: Don't check this now
564// if (GlobalFindAtomA(PROGRESS_CLASSA)) return;
565
566 ZeroMemory (&wndClass, sizeof( WNDCLASSA));
567 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
568 wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc;
569 wndClass.cbClsExtra = 0;
570 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
571 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
572 wndClass.lpszClassName = PROGRESS_CLASSA;
573
574 RegisterClassA(&wndClass);
575}
576
577
578/***********************************************************************
579 * PROGRESS_Unregister [Internal]
580 *
581 * Unregisters the progress bar window class.
582 */
583
584VOID
585PROGRESS_Unregister (VOID)
586{
587 if (GlobalFindAtomA(PROGRESS_CLASSA))
588 UnregisterClassA(PROGRESS_CLASSA, (HINSTANCE)NULL);
589}
590
Note: See TracBrowser for help on using the repository browser.