4 * Copyright 1997, 2002 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(progress);
18 HWND Self; /* The window handle for this control */
19 INT CurVal; /* Current progress value */
20 INT MinVal; /* Minimum progress value */
21 INT MaxVal; /* Maximum progress value */
22 INT Step; /* Step to use on PMB_STEPIT */
23 COLORREF ColorBar; /* Bar color */
24 COLORREF ColorBk; /* Background color */
25 HFONT Font; /* Handle to font (not unused) */
28 /* Control configuration constants */
32 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN( \
33 "Unknown parameter(s) for message " #msg \
34 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
36 /***********************************************************************
37 * PROGRESS_EraseBackground
39 static void PROGRESS_EraseBackground(PROGRESS_INFO *infoPtr, WPARAM wParam)
43 HDC hdc = wParam ? (HDC)wParam : GetDC(infoPtr->Self);
45 /* get the required background brush */
46 if(infoPtr->ColorBk == CLR_DEFAULT)
47 hbrBk = GetSysColorBrush(COLOR_3DFACE);
49 hbrBk = CreateSolidBrush(infoPtr->ColorBk);
51 /* get client rectangle */
52 GetClientRect(infoPtr->Self, &rect);
54 /* draw the background */
55 FillRect(hdc, &rect, hbrBk);
57 /* delete background brush */
58 if(infoPtr->ColorBk != CLR_DEFAULT)
61 if(!wParam) ReleaseDC(infoPtr->Self, hdc);
64 /***********************************************************************
66 * Draws the progress bar.
68 static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc)
71 int rightBar, rightMost, ledWidth;
75 TRACE("(infoPtr=%p, hdc=%x)\n", infoPtr, hdc);
77 /* get the required bar brush */
78 if (infoPtr->ColorBar == CLR_DEFAULT)
79 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
81 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
83 /* get client rectangle */
84 GetClientRect (infoPtr->Self, &rect);
86 InflateRect(&rect, -1, -1);
88 /* get the window style */
89 dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
91 /* compute extent of progress bar */
92 if (dwStyle & PBS_VERTICAL) {
93 rightBar = rect.bottom -
94 MulDiv (infoPtr->CurVal - infoPtr->MinVal,
95 rect.bottom - rect.top,
96 infoPtr->MaxVal - infoPtr->MinVal);
97 ledWidth = MulDiv (rect.right - rect.left, 2, 3);
100 rightBar = rect.left +
101 MulDiv (infoPtr->CurVal - infoPtr->MinVal,
102 rect.right - rect.left,
103 infoPtr->MaxVal - infoPtr->MinVal);
104 ledWidth = MulDiv (rect.bottom - rect.top, 2, 3);
105 rightMost = rect.right;
108 /* now draw the bar */
109 if (dwStyle & PBS_SMOOTH) {
110 if (dwStyle & PBS_VERTICAL)
113 rect.right = rightBar;
114 FillRect(hdc, &rect, hbrBar);
116 if (dwStyle & PBS_VERTICAL) {
117 while(rect.bottom > rightBar) {
118 rect.top = rect.bottom - ledWidth;
119 if (rect.top < rightMost)
120 rect.top = rightMost;
121 FillRect(hdc, &rect, hbrBar);
122 rect.bottom = rect.top - LED_GAP;
125 while(rect.left < rightBar) {
126 rect.right = rect.left + ledWidth;
127 if (rect.right > rightMost)
128 rect.right = rightMost;
129 FillRect(hdc, &rect, hbrBar);
130 rect.left = rect.right + LED_GAP;
135 /* delete bar brush */
136 if (infoPtr->ColorBar != CLR_DEFAULT)
137 DeleteObject (hbrBar);
143 /***********************************************************************
145 * Draw the progress bar. The background need not be erased.
146 * If dc!=0, it draws on it
148 static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc)
151 if (hdc) return PROGRESS_Draw (infoPtr, hdc);
152 hdc = BeginPaint (infoPtr->Self, &ps);
153 PROGRESS_Draw (infoPtr, hdc);
154 EndPaint (infoPtr->Self, &ps);
159 /***********************************************************************
161 * Makes sure the current position (CurVal) is within bounds.
163 static void PROGRESS_CoercePos(PROGRESS_INFO *infoPtr)
165 if(infoPtr->CurVal < infoPtr->MinVal)
166 infoPtr->CurVal = infoPtr->MinVal;
167 if(infoPtr->CurVal > infoPtr->MaxVal)
168 infoPtr->CurVal = infoPtr->MaxVal;
172 /***********************************************************************
174 * Set new Font for progress bar
176 static HFONT PROGRESS_SetFont (PROGRESS_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
178 HFONT hOldFont = infoPtr->Font;
179 infoPtr->Font = hFont;
180 /* Since infoPtr->Font is not used, there is no need for repaint */
184 static DWORD PROGRESS_SetRange (PROGRESS_INFO *infoPtr, int low, int high)
186 DWORD res = MAKELONG(LOWORD(infoPtr->MinVal), LOWORD(infoPtr->MaxVal));
188 /* if nothing changes, simply return */
189 if(infoPtr->MinVal == low && infoPtr->MaxVal == high) return res;
191 infoPtr->MinVal = low;
192 infoPtr->MaxVal = high;
193 PROGRESS_CoercePos(infoPtr);
197 /***********************************************************************
200 static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
201 WPARAM wParam, LPARAM lParam)
203 PROGRESS_INFO *infoPtr;
205 TRACE("hwnd=%x msg=%04x wparam=%x lParam=%lx\n", hwnd, message, wParam, lParam);
207 infoPtr = (PROGRESS_INFO *)GetWindowLongW(hwnd, 0);
209 if (!infoPtr && message != WM_CREATE)
210 return DefWindowProcW( hwnd, message, wParam, lParam );
215 DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
216 dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
217 dwExStyle |= WS_EX_STATICEDGE;
218 SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_STATICEDGE);
219 /* Force recalculation of a non-client area */
220 SetWindowPos(hwnd, 0, 0, 0, 0, 0,
221 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
223 /* allocate memory for info struct */
224 infoPtr = (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
225 if (!infoPtr) return -1;
226 SetWindowLongW (hwnd, 0, (DWORD)infoPtr);
228 /* initialize the info struct */
229 infoPtr->Self = hwnd;
231 infoPtr->MaxVal = 100;
234 infoPtr->ColorBar = CLR_DEFAULT;
235 infoPtr->ColorBk = CLR_DEFAULT;
237 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd);
242 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd);
243 COMCTL32_Free (infoPtr);
244 SetWindowLongW(hwnd, 0, 0);
248 PROGRESS_EraseBackground(infoPtr, wParam);
252 return (LRESULT)infoPtr->Font;
255 return PROGRESS_SetFont (infoPtr, (HFONT)wParam, (BOOL)lParam);
258 return PROGRESS_Paint (infoPtr, (HDC)wParam);
263 if(lParam) UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
264 oldVal = infoPtr->CurVal;
267 infoPtr->CurVal += (INT)wParam;
268 PROGRESS_CoercePos (infoPtr);
269 TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
270 bErase = (oldVal > infoPtr->CurVal);
271 InvalidateRect(hwnd, NULL, bErase);
279 if (lParam) UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
280 oldVal = infoPtr->CurVal;
281 if(oldVal != wParam) {
283 infoPtr->CurVal = (INT)wParam;
284 PROGRESS_CoercePos(infoPtr);
285 TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
286 bErase = (oldVal > infoPtr->CurVal);
287 InvalidateRect(hwnd, NULL, bErase);
293 if (wParam) UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
294 return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam));
299 if (lParam) UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
300 oldStep = infoPtr->Step;
301 infoPtr->Step = (INT)wParam;
308 if (wParam || lParam) UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
309 oldVal = infoPtr->CurVal;
310 infoPtr->CurVal += infoPtr->Step;
311 if(infoPtr->CurVal > infoPtr->MaxVal)
312 infoPtr->CurVal = infoPtr->MinVal;
313 if(oldVal != infoPtr->CurVal)
316 TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
317 bErase = (oldVal > infoPtr->CurVal);
318 InvalidateRect(hwnd, NULL, bErase);
324 return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam);
328 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
329 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
331 return wParam ? infoPtr->MinVal : infoPtr->MaxVal;
334 if (wParam || lParam) UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
335 return infoPtr->CurVal;
337 case PBM_SETBARCOLOR:
338 if (wParam) UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
339 infoPtr->ColorBar = (COLORREF)lParam;
340 InvalidateRect(hwnd, NULL, TRUE);
344 if (wParam) UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
345 infoPtr->ColorBk = (COLORREF)lParam;
346 InvalidateRect(hwnd, NULL, TRUE);
350 if (message >= WM_USER)
351 ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam );
352 return DefWindowProcW( hwnd, message, wParam, lParam );
357 /***********************************************************************
358 * PROGRESS_Register [Internal]
360 * Registers the progress bar window class.
362 VOID PROGRESS_Register (void)
366 ZeroMemory (&wndClass, sizeof(wndClass));
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 = LoadCursorW (0, IDC_ARROWW);
372 wndClass.lpszClassName = PROGRESS_CLASSW;
374 RegisterClassW (&wndClass);
378 /***********************************************************************
379 * PROGRESS_Unregister [Internal]
381 * Unregisters the progress bar window class.
383 VOID PROGRESS_Unregister (void)
385 UnregisterClassW (PROGRESS_CLASSW, (HINSTANCE)NULL);