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

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

aaa

File size: 10.6 KB
Line 
1/* $Id: progress.c,v 1.3 1999-06-12 20:44:06 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 */
11
12#include "winbase.h"
13#include "commctrl.h"
14#include "progress.h"
15#include "comctl32.h"
16
17
18/* Control configuration constants */
19
20#define LED_GAP 2
21
22/* Work constants */
23
24//#define UNKNOWN_PARAM(msg, wParam, lParam) WARN(progress, \
25// "Unknown parameter(s) for message " #msg \
26// "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
27#define UNKNOWN_PARAM(msg, wParam, lParam)
28
29#define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd, 0))
30
31
32/***********************************************************************
33 * PROGRESS_Draw
34 * Draws the progress bar.
35 */
36static void
37PROGRESS_Draw (HWND hwnd, HDC hdc, INT lastVal, BOOL inUpdate)
38{
39 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
40 HBRUSH hbrBar, hbrBk;
41 int rightBar, rightMost, ledWidth;
42 RECT rect;
43 DWORD dwStyle;
44
45// TRACE(progress, "refresh pos=%d min=%d, max=%d\n",
46// infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
47
48 /* get the required bar brush */
49 if (infoPtr->ColorBar == CLR_DEFAULT)
50 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
51 else
52 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
53
54 /* get the required background brush */
55 if (infoPtr->ColorBk == CLR_DEFAULT)
56 hbrBk = GetSysColorBrush (COLOR_3DFACE);
57 else
58 hbrBk = CreateSolidBrush (infoPtr->ColorBk);
59
60 /* get client rectangle */
61 GetClientRect (hwnd, &rect);
62
63 /* draw the background */
64 FillRect(hdc, &rect, hbrBk);
65
66 rect.left++; rect.right--; rect.top++; rect.bottom--;
67
68 /* get the window style */
69 dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
70
71 /* compute extent of progress bar */
72 if (dwStyle & PBS_VERTICAL)
73 {
74 rightBar = rect.bottom -
75 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
76 rect.bottom - rect.top,
77 infoPtr->MaxVal-infoPtr->MinVal);
78 ledWidth = MulDiv ((rect.right - rect.left), 2, 3);
79 rightMost = rect.top;
80 }
81 else
82 {
83 rightBar = rect.left +
84 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
85 rect.right - rect.left,
86 infoPtr->MaxVal-infoPtr->MinVal);
87 ledWidth = MulDiv ((rect.bottom - rect.top), 2, 3);
88 rightMost = rect.right;
89 }
90
91 /* now draw the bar */
92 if (dwStyle & PBS_SMOOTH)
93 {
94 if (dwStyle & PBS_VERTICAL)
95 rect.top = rightBar;
96 else
97 rect.right = rightBar;
98 FillRect(hdc, &rect, hbrBar);
99 }
100 else
101 {
102 if (dwStyle & PBS_VERTICAL)
103 {
104 while(rect.bottom > rightBar) {
105 rect.top = rect.bottom-ledWidth;
106 if (rect.top < rightMost)
107 rect.top = rightMost;
108 FillRect(hdc, &rect, hbrBar);
109 rect.bottom = rect.top-LED_GAP;
110 }
111 }
112 else {
113 while(rect.left < rightBar) {
114 rect.right = rect.left+ledWidth;
115 if (rect.right > rightMost)
116 rect.right = rightMost;
117 FillRect(hdc, &rect, hbrBar);
118 rect.left = rect.right+LED_GAP;
119 }
120 }
121 }
122
123 /* delete bar brush */
124 if (infoPtr->ColorBar != CLR_DEFAULT)
125 DeleteObject (hbrBar);
126
127 /* delete background brush */
128 if (infoPtr->ColorBk != CLR_DEFAULT)
129 DeleteObject (hbrBk);
130}
131
132/***********************************************************************
133 * PROGRESS_Update (prototype, todo)
134 * Updates only the changed pixels -> faster, no flickering
135 */
136static void PROGRESS_Update(HWND hwnd,INT lastVal)
137{
138 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
139 HDC hdc;
140
141 if (lastVal != infoPtr->CurVal) //Only update if really necessary
142 {
143 hdc = GetDC(hwnd);
144 PROGRESS_Draw(hwnd,hdc,lastVal,TRUE);
145 ReleaseDC(hwnd,hdc);
146 }
147}
148
149/***********************************************************************
150 * PROGRESS_Refresh
151 * Draw the progress bar. The background need not be erased.
152 */
153static void
154PROGRESS_Refresh (HWND hwnd)
155{
156 HDC hdc;
157
158 hdc = GetDC (hwnd);
159 PROGRESS_Draw (hwnd, hdc, 0, FALSE);
160 ReleaseDC (hwnd, hdc);
161}
162
163/***********************************************************************
164 * PROGRESS_Paint
165 * Draw the progress bar. The background need not be erased.
166 * If dc!=0, it draws on it
167 */
168static void
169PROGRESS_Paint (HWND hwnd)
170{
171 PAINTSTRUCT ps;
172 HDC hdc;
173
174 hdc = BeginPaint (hwnd, &ps);
175 PROGRESS_Draw (hwnd, hdc, 0, FALSE);
176 EndPaint (hwnd, &ps);
177}
178
179
180/***********************************************************************
181 * PROGRESS_CoercePos
182 * Makes sure the current position (CUrVal) is within bounds.
183 */
184static void PROGRESS_CoercePos(HWND hwnd)
185{
186 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
187
188 if(infoPtr->CurVal < infoPtr->MinVal)
189 infoPtr->CurVal = infoPtr->MinVal;
190 if(infoPtr->CurVal > infoPtr->MaxVal)
191 infoPtr->CurVal = infoPtr->MaxVal;
192}
193
194
195/***********************************************************************
196 * PROGRESS_SetFont
197 * Set new Font for progress bar
198 */
199static HFONT
200PROGRESS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
201{
202 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
203 HFONT hOldFont = infoPtr->hFont;
204
205 infoPtr->hFont = (HFONT)wParam;
206 if (LOWORD(lParam))
207 PROGRESS_Refresh (hwnd);
208 return hOldFont;
209}
210
211
212/***********************************************************************
213 * ProgressWindowProc
214 */
215LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
216 WPARAM wParam, LPARAM lParam)
217{
218 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
219 UINT temp;
220
221 switch(message)
222 {
223 case WM_NCCREATE:
224 {
225 DWORD dwExStyle;
226 dwExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
227 SetWindowLongA(hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_STATICEDGE);
228 }
229 return TRUE;
230
231 case WM_CREATE:
232 /* allocate memory for info struct */
233 infoPtr =
234 (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
235 SetWindowLongA(hwnd, 0, (DWORD)infoPtr);
236
237 /* initialize the info struct */
238 infoPtr->MinVal=0;
239 infoPtr->MaxVal=100;
240 infoPtr->CurVal=0;
241 infoPtr->Step=10;
242 infoPtr->ColorBar=CLR_DEFAULT;
243 infoPtr->ColorBk=CLR_DEFAULT;
244 infoPtr->hFont=(HANDLE)NULL;
245// TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
246 break;
247
248 case WM_DESTROY:
249// TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
250 COMCTL32_Free (infoPtr);
251 break;
252
253 case WM_ERASEBKGND:
254 /* pretend to erase it here, but we will do it in the paint
255 function to avoid flicker */
256 return 1;
257
258 case WM_GETFONT:
259 return (LRESULT)infoPtr->hFont;
260
261 case WM_SETFONT:
262 return PROGRESS_SetFont (hwnd, wParam, lParam);
263
264 case WM_PAINT:
265 PROGRESS_Paint (hwnd);
266 break;
267
268 case PBM_DELTAPOS:
269 if(lParam)
270 UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
271 temp = infoPtr->CurVal;
272 if(wParam != 0){
273 infoPtr->CurVal += (INT)wParam; //CB: negative values allowed, was UINT16
274 PROGRESS_CoercePos (hwnd);
275 PROGRESS_Update (hwnd,temp);
276 }
277 return temp;
278
279 case PBM_SETPOS:
280 if (lParam)
281 UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
282 temp = infoPtr->CurVal;
283 if(temp != wParam){
284 infoPtr->CurVal = (UINT16)wParam;
285 PROGRESS_CoercePos(hwnd);
286 PROGRESS_Update (hwnd,temp);
287 }
288 return temp;
289
290 case PBM_SETRANGE:
291 if (wParam)
292 UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
293 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
294 if(temp != lParam){
295 infoPtr->MinVal = LOWORD(lParam);
296 infoPtr->MaxVal = HIWORD(lParam);
297 if(infoPtr->MaxVal <= infoPtr->MinVal)
298 infoPtr->MaxVal = infoPtr->MinVal+1;
299 PROGRESS_CoercePos(hwnd);
300 PROGRESS_Refresh (hwnd);
301 }
302 return temp;
303
304 case PBM_SETSTEP:
305 if (lParam)
306 UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
307 temp = infoPtr->Step;
308 infoPtr->Step = (UINT16)wParam;
309 return temp;
310
311 case PBM_STEPIT:
312 if (wParam || lParam)
313 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
314 temp = infoPtr->CurVal;
315 infoPtr->CurVal += infoPtr->Step;
316 if(infoPtr->CurVal > infoPtr->MaxVal)
317 infoPtr->CurVal = infoPtr->MinVal;
318 if(temp != infoPtr->CurVal)
319 PROGRESS_Update (hwnd,temp);
320 return temp;
321
322 case PBM_SETRANGE32:
323 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
324 if((infoPtr->MinVal != (INT)wParam) ||
325 (infoPtr->MaxVal != (INT)lParam)) {
326 infoPtr->MinVal = (INT)wParam;
327 infoPtr->MaxVal = (INT)lParam;
328 if(infoPtr->MaxVal <= infoPtr->MinVal)
329 infoPtr->MaxVal = infoPtr->MinVal+1;
330 PROGRESS_CoercePos(hwnd);
331 PROGRESS_Refresh (hwnd);
332 }
333 return temp;
334
335 case PBM_GETRANGE:
336 if (lParam){
337 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
338 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
339 }
340 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
341
342 case PBM_GETPOS:
343 if (wParam || lParam)
344 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
345 return (infoPtr->CurVal);
346
347 case PBM_SETBARCOLOR:
348 if (wParam)
349 UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
350 infoPtr->ColorBar = (COLORREF)lParam;
351 PROGRESS_Refresh (hwnd);
352 break;
353
354 case PBM_SETBKCOLOR:
355 if (wParam)
356 UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
357 infoPtr->ColorBk = (COLORREF)lParam;
358 PROGRESS_Refresh (hwnd);
359 break;
360
361 default:
362// if (message >= WM_USER)
363// ERR(progress, "unknown msg %04x wp=%04x lp=%08lx\n",
364// message, wParam, lParam );
365 return DefWindowProcA( hwnd, message, wParam, lParam );
366 }
367
368 return 0;
369}
370
371
372/***********************************************************************
373 * PROGRESS_Register [Internal]
374 *
375 * Registers the progress bar window class.
376 */
377
378VOID
379PROGRESS_Register (VOID)
380{
381 WNDCLASSA wndClass;
382
383 if (GlobalFindAtomA(PROGRESS_CLASSA)) return;
384
385 ZeroMemory (&wndClass, sizeof( WNDCLASSA));
386 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
387 wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc;
388 wndClass.cbClsExtra = 0;
389 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
390 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
391 wndClass.lpszClassName = PROGRESS_CLASSA;
392
393 RegisterClassA(&wndClass);
394}
395
396
397/***********************************************************************
398 * PROGRESS_Unregister [Internal]
399 *
400 * Unregisters the progress bar window class.
401 */
402
403VOID
404PROGRESS_Unregister (VOID)
405{
406 if (GlobalFindAtomA(PROGRESS_CLASSA))
407 UnregisterClassA(PROGRESS_CLASSA, (HINSTANCE)NULL);
408}
409
Note: See TracBrowser for help on using the repository browser.