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

Last change on this file since 41 was 41, checked in by achimha, 26 years ago

* empty log message *

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