4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(progress);
18 INT CurVal; /* Current progress value */
19 INT MinVal; /* Minimum progress value */
20 INT MaxVal; /* Maximum progress value */
21 INT Step; /* Step to use on PMB_STEPIT */
22 COLORREF ColorBar; /* Bar color */
23 COLORREF ColorBk; /* Background color */
24 HFONT hFont; /* Handle to font (not unused) */
27 /* Control configuration constants */
33 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(\
34 "Unknown parameter(s) for message " #msg \
35 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
37 #define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd, 0))
40 /***********************************************************************
42 * Draws the progress bar.
45 PROGRESS_Draw (HWND hwnd, HDC hdc)
47 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
49 int rightBar, rightMost, ledWidth;
53 TRACE("refresh pos=%d min=%d, max=%d\n",
54 infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
56 /* get the required bar brush */
57 if (infoPtr->ColorBar == CLR_DEFAULT)
58 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
60 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
62 /* get the required background brush */
63 if (infoPtr->ColorBk == CLR_DEFAULT)
64 hbrBk = GetSysColorBrush (COLOR_3DFACE);
66 hbrBk = CreateSolidBrush (infoPtr->ColorBk);
68 /* get client rectangle */
69 GetClientRect (hwnd, &rect);
71 /* draw the background */
72 FillRect(hdc, &rect, hbrBk);
74 rect.left++; rect.right--; rect.top++; rect.bottom--;
76 /* get the window style */
77 dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
79 /* compute extent of progress bar */
80 if (dwStyle & PBS_VERTICAL)
82 rightBar = rect.bottom -
83 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
84 rect.bottom - rect.top,
85 infoPtr->MaxVal-infoPtr->MinVal);
86 ledWidth = MulDiv ((rect.right - rect.left), 2, 3);
91 rightBar = rect.left +
92 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
93 rect.right - rect.left,
94 infoPtr->MaxVal-infoPtr->MinVal);
95 ledWidth = MulDiv ((rect.bottom - rect.top), 2, 3);
96 rightMost = rect.right;
99 /* now draw the bar */
100 if (dwStyle & PBS_SMOOTH)
102 if (dwStyle & PBS_VERTICAL)
105 rect.right = rightBar;
106 FillRect(hdc, &rect, hbrBar);
110 if (dwStyle & PBS_VERTICAL)
112 while(rect.bottom > rightBar) {
113 rect.top = rect.bottom-ledWidth;
114 if (rect.top < rightMost)
115 rect.top = rightMost;
116 FillRect(hdc, &rect, hbrBar);
117 rect.bottom = rect.top-LED_GAP;
121 while(rect.left < rightBar) {
122 rect.right = rect.left+ledWidth;
123 if (rect.right > rightMost)
124 rect.right = rightMost;
125 FillRect(hdc, &rect, hbrBar);
126 rect.left = rect.right+LED_GAP;
131 /* delete bar brush */
132 if (infoPtr->ColorBar != CLR_DEFAULT)
133 DeleteObject (hbrBar);
135 /* delete background brush */
136 if (infoPtr->ColorBk != CLR_DEFAULT)
137 DeleteObject (hbrBk);
140 /***********************************************************************
142 * Draw the progress bar. The background need not be erased.
145 PROGRESS_Refresh (HWND hwnd)
150 PROGRESS_Draw (hwnd, hdc);
151 ReleaseDC (hwnd, hdc);
154 /***********************************************************************
156 * Draw the progress bar. The background need not be erased.
157 * If dc!=0, it draws on it
160 PROGRESS_Paint (HWND hwnd)
165 hdc = BeginPaint (hwnd, &ps);
166 PROGRESS_Draw (hwnd, hdc);
167 EndPaint (hwnd, &ps);
171 /***********************************************************************
173 * Makes sure the current position (CUrVal) is within bounds.
175 static void PROGRESS_CoercePos(HWND hwnd)
177 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
179 if(infoPtr->CurVal < infoPtr->MinVal)
180 infoPtr->CurVal = infoPtr->MinVal;
181 if(infoPtr->CurVal > infoPtr->MaxVal)
182 infoPtr->CurVal = infoPtr->MaxVal;
186 /***********************************************************************
188 * Set new Font for progress bar
191 PROGRESS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
193 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
194 HFONT hOldFont = infoPtr->hFont;
196 infoPtr->hFont = (HFONT)wParam;
198 PROGRESS_Refresh (hwnd);
203 /***********************************************************************
206 static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
207 WPARAM wParam, LPARAM lParam)
209 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
211 if (!infoPtr && (message != WM_CREATE))
212 return DefWindowProcA( hwnd, message, wParam, lParam );
218 dwExStyle = GetWindowLongA (hwnd, GWL_EXSTYLE);
219 SetWindowLongA (hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_STATICEDGE);
224 /* allocate memory for info struct */
226 (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
227 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
229 /* initialize the info struct */
234 infoPtr->ColorBar=CLR_DEFAULT;
235 infoPtr->ColorBk=CLR_DEFAULT;
236 infoPtr->hFont=(HANDLE)NULL;
237 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd);
241 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd);
242 COMCTL32_Free (infoPtr);
243 SetWindowLongA(hwnd, 0, 0);
247 /* pretend to erase it here, but we will do it in the paint
248 function to avoid flicker */
252 return (LRESULT)infoPtr->hFont;
255 return PROGRESS_SetFont (hwnd, wParam, lParam);
258 PROGRESS_Paint (hwnd);
263 UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
264 temp = infoPtr->CurVal;
266 infoPtr->CurVal += (WORD)wParam;
267 PROGRESS_CoercePos (hwnd);
268 PROGRESS_Refresh (hwnd);
274 UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
275 temp = infoPtr->CurVal;
277 infoPtr->CurVal = (WORD)wParam;
278 PROGRESS_CoercePos(hwnd);
279 PROGRESS_Refresh (hwnd);
285 UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
286 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
288 infoPtr->MinVal = LOWORD(lParam);
289 infoPtr->MaxVal = HIWORD(lParam);
290 if(infoPtr->MaxVal <= infoPtr->MinVal)
291 infoPtr->MaxVal = infoPtr->MinVal+1;
292 PROGRESS_CoercePos(hwnd);
293 PROGRESS_Refresh (hwnd);
299 UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
300 temp = infoPtr->Step;
301 infoPtr->Step = (WORD)wParam;
305 if (wParam || lParam)
306 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
307 temp = infoPtr->CurVal;
308 infoPtr->CurVal += infoPtr->Step;
309 if(infoPtr->CurVal > infoPtr->MaxVal)
310 infoPtr->CurVal = infoPtr->MinVal;
311 if(temp != infoPtr->CurVal)
312 PROGRESS_Refresh (hwnd);
316 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
317 if((infoPtr->MinVal != (INT)wParam) ||
318 (infoPtr->MaxVal != (INT)lParam)) {
319 infoPtr->MinVal = (INT)wParam;
320 infoPtr->MaxVal = (INT)lParam;
321 if(infoPtr->MaxVal <= infoPtr->MinVal)
322 infoPtr->MaxVal = infoPtr->MinVal+1;
323 PROGRESS_CoercePos(hwnd);
324 PROGRESS_Refresh (hwnd);
330 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
331 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
333 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
336 if (wParam || lParam)
337 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
338 return (infoPtr->CurVal);
340 case PBM_SETBARCOLOR:
342 UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
343 infoPtr->ColorBar = (COLORREF)lParam;
344 PROGRESS_Refresh (hwnd);
349 UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
350 infoPtr->ColorBk = (COLORREF)lParam;
351 PROGRESS_Refresh (hwnd);
355 if (message >= WM_USER)
356 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
357 message, wParam, lParam );
358 return DefWindowProcA( hwnd, message, wParam, lParam );
365 /***********************************************************************
366 * PROGRESS_Register [Internal]
368 * Registers the progress bar window class.
372 PROGRESS_Register (void)
376 ZeroMemory (&wndClass, sizeof( WNDCLASSA));
377 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
378 wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc;
379 wndClass.cbClsExtra = 0;
380 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
381 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
382 wndClass.lpszClassName = PROGRESS_CLASSA;
384 RegisterClassA (&wndClass);
388 /***********************************************************************
389 * PROGRESS_Unregister [Internal]
391 * Unregisters the progress bar window class.
395 PROGRESS_Unregister (void)
397 UnregisterClassA (PROGRESS_CLASSA, (HINSTANCE)NULL);