4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(progress)
17 /* Control configuration constants */
23 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(\
24 "Unknown parameter(s) for message " #msg \
25 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
27 #define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd, 0))
30 /***********************************************************************
32 * Draws the progress bar.
35 PROGRESS_Draw (HWND hwnd, HDC hdc)
37 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
39 int rightBar, rightMost, ledWidth;
43 TRACE("refresh pos=%d min=%d, max=%d\n",
44 infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
46 /* get the required bar brush */
47 if (infoPtr->ColorBar == CLR_DEFAULT)
48 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
50 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
52 /* get the required background brush */
53 if (infoPtr->ColorBk == CLR_DEFAULT)
54 hbrBk = GetSysColorBrush (COLOR_3DFACE);
56 hbrBk = CreateSolidBrush (infoPtr->ColorBk);
58 /* get client rectangle */
59 GetClientRect (hwnd, &rect);
61 /* draw the background */
62 FillRect(hdc, &rect, hbrBk);
64 rect.left++; rect.right--; rect.top++; rect.bottom--;
66 /* get the window style */
67 dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
69 /* compute extent of progress bar */
70 if (dwStyle & PBS_VERTICAL)
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);
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;
89 /* now draw the bar */
90 if (dwStyle & PBS_SMOOTH)
92 if (dwStyle & PBS_VERTICAL)
95 rect.right = rightBar;
96 FillRect(hdc, &rect, hbrBar);
100 if (dwStyle & PBS_VERTICAL)
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;
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;
121 /* delete bar brush */
122 if (infoPtr->ColorBar != CLR_DEFAULT)
123 DeleteObject (hbrBar);
125 /* delete background brush */
126 if (infoPtr->ColorBk != CLR_DEFAULT)
127 DeleteObject (hbrBk);
130 /***********************************************************************
132 * Draw the progress bar. The background need not be erased.
135 PROGRESS_Refresh (HWND hwnd)
140 PROGRESS_Draw (hwnd, hdc);
141 ReleaseDC (hwnd, hdc);
144 /***********************************************************************
146 * Draw the progress bar. The background need not be erased.
147 * If dc!=0, it draws on it
150 PROGRESS_Paint (HWND hwnd)
155 hdc = BeginPaint (hwnd, &ps);
156 PROGRESS_Draw (hwnd, hdc);
157 EndPaint (hwnd, &ps);
161 /***********************************************************************
163 * Makes sure the current position (CUrVal) is within bounds.
165 static void PROGRESS_CoercePos(HWND hwnd)
167 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
169 if(infoPtr->CurVal < infoPtr->MinVal)
170 infoPtr->CurVal = infoPtr->MinVal;
171 if(infoPtr->CurVal > infoPtr->MaxVal)
172 infoPtr->CurVal = infoPtr->MaxVal;
176 /***********************************************************************
178 * Set new Font for progress bar
181 PROGRESS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
183 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
184 HFONT hOldFont = infoPtr->hFont;
186 infoPtr->hFont = (HFONT)wParam;
188 PROGRESS_Refresh (hwnd);
193 /***********************************************************************
196 static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
197 WPARAM wParam, LPARAM lParam)
199 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
207 dwExStyle = GetWindowLongA (hwnd, GWL_EXSTYLE);
208 SetWindowLongA (hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_STATICEDGE);
213 /* allocate memory for info struct */
215 (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
216 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
218 /* initialize the info struct */
223 infoPtr->ColorBar=CLR_DEFAULT;
224 infoPtr->ColorBk=CLR_DEFAULT;
225 infoPtr->hFont=(HANDLE)NULL;
226 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd);
230 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd);
231 COMCTL32_Free (infoPtr);
235 /* pretend to erase it here, but we will do it in the paint
236 function to avoid flicker */
240 return (LRESULT)infoPtr->hFont;
243 return PROGRESS_SetFont (hwnd, wParam, lParam);
246 PROGRESS_Paint (hwnd);
251 UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
252 temp = infoPtr->CurVal;
254 infoPtr->CurVal += (UINT16)wParam;
255 PROGRESS_CoercePos (hwnd);
256 PROGRESS_Refresh (hwnd);
262 UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
263 temp = infoPtr->CurVal;
265 infoPtr->CurVal = (UINT16)wParam;
266 PROGRESS_CoercePos(hwnd);
267 PROGRESS_Refresh (hwnd);
273 UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
274 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
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);
287 UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
288 temp = infoPtr->Step;
289 infoPtr->Step = (UINT16)wParam;
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);
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);
318 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
319 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
321 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
324 if (wParam || lParam)
325 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
326 return (infoPtr->CurVal);
328 case PBM_SETBARCOLOR:
330 UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
331 infoPtr->ColorBar = (COLORREF)lParam;
332 PROGRESS_Refresh (hwnd);
337 UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
338 infoPtr->ColorBk = (COLORREF)lParam;
339 PROGRESS_Refresh (hwnd);
343 if (message >= WM_USER)
344 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
345 message, wParam, lParam );
346 return DefWindowProcA( hwnd, message, wParam, lParam );
353 /***********************************************************************
354 * PROGRESS_Register [Internal]
356 * Registers the progress bar window class.
360 PROGRESS_Register (void)
364 if (GlobalFindAtomA (PROGRESS_CLASSA)) return;
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;
374 RegisterClassA (&wndClass);
378 /***********************************************************************
379 * PROGRESS_Unregister [Internal]
381 * Unregisters the progress bar window class.
385 PROGRESS_Unregister (void)
387 if (GlobalFindAtomA (PROGRESS_CLASSA))
388 UnregisterClassA (PROGRESS_CLASSA, (HINSTANCE)NULL);