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

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

COMCTL32 5.80 changes

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