4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
15 /* Control configuration constants */
21 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(progress, \
22 "Unknown parameter(s) for message " #msg \
23 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
25 #define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd, 0))
28 /***********************************************************************
30 * Draws the progress bar.
33 PROGRESS_Draw (HWND hwnd
, HDC hdc
)
35 PROGRESS_INFO
*infoPtr
= PROGRESS_GetInfoPtr(hwnd
);
37 int rightBar
, rightMost
, ledWidth
;
41 TRACE(progress
, "refresh pos=%d min=%d, max=%d\n",
42 infoPtr
->CurVal
, infoPtr
->MinVal
, infoPtr
->MaxVal
);
44 /* get the required bar brush */
45 if (infoPtr
->ColorBar
== CLR_DEFAULT
)
46 hbrBar
= GetSysColorBrush(COLOR_HIGHLIGHT
);
48 hbrBar
= CreateSolidBrush (infoPtr
->ColorBar
);
50 /* get the required background brush */
51 if (infoPtr
->ColorBk
== CLR_DEFAULT
)
52 hbrBk
= GetSysColorBrush (COLOR_3DFACE
);
54 hbrBk
= CreateSolidBrush (infoPtr
->ColorBk
);
56 /* get client rectangle */
57 GetClientRect (hwnd
, &rect
);
59 /* draw the background */
60 FillRect(hdc
, &rect
, hbrBk
);
62 rect
.left
++; rect
.right
--; rect
.top
++; rect
.bottom
--;
64 /* get the window style */
65 dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
67 /* compute extent of progress bar */
68 if (dwStyle
& PBS_VERTICAL
)
70 rightBar
= rect
.bottom
-
71 MulDiv(infoPtr
->CurVal
-infoPtr
->MinVal
,
72 rect
.bottom
- rect
.top
,
73 infoPtr
->MaxVal
-infoPtr
->MinVal
);
74 ledWidth
= MulDiv ((rect
.right
- rect
.left
), 2, 3);
79 rightBar
= rect
.left
+
80 MulDiv(infoPtr
->CurVal
-infoPtr
->MinVal
,
81 rect
.right
- rect
.left
,
82 infoPtr
->MaxVal
-infoPtr
->MinVal
);
83 ledWidth
= MulDiv ((rect
.bottom
- rect
.top
), 2, 3);
84 rightMost
= rect
.right
;
87 /* now draw the bar */
88 if (dwStyle
& PBS_SMOOTH
)
90 if (dwStyle
& PBS_VERTICAL
)
93 rect
.right
= rightBar
;
94 FillRect(hdc
, &rect
, hbrBar
);
98 if (dwStyle
& PBS_VERTICAL
)
100 while(rect
.bottom
> rightBar
) {
101 rect
.top
= rect
.bottom
-ledWidth
;
102 if (rect
.top
< rightMost
)
103 rect
.top
= rightMost
;
104 FillRect(hdc
, &rect
, hbrBar
);
105 rect
.bottom
= rect
.top
-LED_GAP
;
109 while(rect
.left
< rightBar
) {
110 rect
.right
= rect
.left
+ledWidth
;
111 if (rect
.right
> rightMost
)
112 rect
.right
= rightMost
;
113 FillRect(hdc
, &rect
, hbrBar
);
114 rect
.left
= rect
.right
+LED_GAP
;
119 /* delete bar brush */
120 if (infoPtr
->ColorBar
!= CLR_DEFAULT
)
121 DeleteObject (hbrBar
);
123 /* delete background brush */
124 if (infoPtr
->ColorBk
!= CLR_DEFAULT
)
125 DeleteObject (hbrBk
);
128 /***********************************************************************
130 * Draw the progress bar. The background need not be erased.
133 PROGRESS_Refresh (HWND hwnd
)
138 PROGRESS_Draw (hwnd
, hdc
);
139 ReleaseDC (hwnd
, hdc
);
142 /***********************************************************************
144 * Draw the progress bar. The background need not be erased.
145 * If dc!=0, it draws on it
148 PROGRESS_Paint (HWND hwnd
)
153 hdc
= BeginPaint (hwnd
, &ps
);
154 PROGRESS_Draw (hwnd
, hdc
);
155 EndPaint (hwnd
, &ps
);
159 /***********************************************************************
161 * Makes sure the current position (CUrVal) is within bounds.
163 static void PROGRESS_CoercePos(HWND hwnd
)
165 PROGRESS_INFO
*infoPtr
= PROGRESS_GetInfoPtr(hwnd
);
167 if(infoPtr
->CurVal
< infoPtr
->MinVal
)
168 infoPtr
->CurVal
= infoPtr
->MinVal
;
169 if(infoPtr
->CurVal
> infoPtr
->MaxVal
)
170 infoPtr
->CurVal
= infoPtr
->MaxVal
;
174 /***********************************************************************
176 * Set new Font for progress bar
179 PROGRESS_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
181 PROGRESS_INFO
*infoPtr
= PROGRESS_GetInfoPtr(hwnd
);
182 HFONT hOldFont
= infoPtr
->hFont
;
184 infoPtr
->hFont
= (HFONT
)wParam
;
186 PROGRESS_Refresh (hwnd
);
191 /***********************************************************************
194 LRESULT WINAPI
ProgressWindowProc(HWND hwnd
, UINT message
,
195 WPARAM wParam
, LPARAM lParam
)
197 PROGRESS_INFO
*infoPtr
= PROGRESS_GetInfoPtr(hwnd
);
205 dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
206 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
| WS_EX_STATICEDGE
);
211 /* allocate memory for info struct */
213 (PROGRESS_INFO
*)COMCTL32_Alloc (sizeof(PROGRESS_INFO
));
214 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
216 /* initialize the info struct */
221 infoPtr
->ColorBar
=CLR_DEFAULT
;
222 infoPtr
->ColorBk
=CLR_DEFAULT
;
223 infoPtr
->hFont
=(HANDLE
)NULL
;
224 TRACE(progress
, "Progress Ctrl creation, hwnd=%04x\n", hwnd
);
228 TRACE (progress
, "Progress Ctrl destruction, hwnd=%04x\n", hwnd
);
229 COMCTL32_Free (infoPtr
);
233 /* pretend to erase it here, but we will do it in the paint
234 function to avoid flicker */
238 return (LRESULT
)infoPtr
->hFont
;
241 return PROGRESS_SetFont (hwnd
, wParam
, lParam
);
244 PROGRESS_Paint (hwnd
);
249 UNKNOWN_PARAM(PBM_DELTAPOS
, wParam
, lParam
);
250 temp
= infoPtr
->CurVal
;
252 infoPtr
->CurVal
+= (UINT16
)wParam
;
253 PROGRESS_CoercePos (hwnd
);
254 PROGRESS_Refresh (hwnd
);
260 UNKNOWN_PARAM(PBM_SETPOS
, wParam
, lParam
);
261 temp
= infoPtr
->CurVal
;
263 infoPtr
->CurVal
= (UINT16
)wParam
;
264 PROGRESS_CoercePos(hwnd
);
265 PROGRESS_Refresh (hwnd
);
271 UNKNOWN_PARAM(PBM_SETRANGE
, wParam
, lParam
);
272 temp
= MAKELONG(infoPtr
->MinVal
, infoPtr
->MaxVal
);
274 infoPtr
->MinVal
= LOWORD(lParam
);
275 infoPtr
->MaxVal
= HIWORD(lParam
);
276 if(infoPtr
->MaxVal
<= infoPtr
->MinVal
)
277 infoPtr
->MaxVal
= infoPtr
->MinVal
+1;
278 PROGRESS_CoercePos(hwnd
);
279 PROGRESS_Refresh (hwnd
);
285 UNKNOWN_PARAM(PBM_SETSTEP
, wParam
, lParam
);
286 temp
= infoPtr
->Step
;
287 infoPtr
->Step
= (UINT16
)wParam
;
291 if (wParam
|| lParam
)
292 UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
293 temp
= infoPtr
->CurVal
;
294 infoPtr
->CurVal
+= infoPtr
->Step
;
295 if(infoPtr
->CurVal
> infoPtr
->MaxVal
)
296 infoPtr
->CurVal
= infoPtr
->MinVal
;
297 if(temp
!= infoPtr
->CurVal
)
298 PROGRESS_Refresh (hwnd
);
302 temp
= MAKELONG(infoPtr
->MinVal
, infoPtr
->MaxVal
);
303 if((infoPtr
->MinVal
!= (INT
)wParam
) ||
304 (infoPtr
->MaxVal
!= (INT
)lParam
)) {
305 infoPtr
->MinVal
= (INT
)wParam
;
306 infoPtr
->MaxVal
= (INT
)lParam
;
307 if(infoPtr
->MaxVal
<= infoPtr
->MinVal
)
308 infoPtr
->MaxVal
= infoPtr
->MinVal
+1;
309 PROGRESS_CoercePos(hwnd
);
310 PROGRESS_Refresh (hwnd
);
316 ((PPBRANGE
)lParam
)->iLow
= infoPtr
->MinVal
;
317 ((PPBRANGE
)lParam
)->iHigh
= infoPtr
->MaxVal
;
319 return (wParam
) ? infoPtr
->MinVal
: infoPtr
->MaxVal
;
322 if (wParam
|| lParam
)
323 UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
324 return (infoPtr
->CurVal
);
326 case PBM_SETBARCOLOR
:
328 UNKNOWN_PARAM(PBM_SETBARCOLOR
, wParam
, lParam
);
329 infoPtr
->ColorBar
= (COLORREF
)lParam
;
330 PROGRESS_Refresh (hwnd
);
335 UNKNOWN_PARAM(PBM_SETBKCOLOR
, wParam
, lParam
);
336 infoPtr
->ColorBk
= (COLORREF
)lParam
;
337 PROGRESS_Refresh (hwnd
);
341 if (message
>= WM_USER
)
342 ERR(progress
, "unknown msg %04x wp=%04x lp=%08lx\n",
343 message
, wParam
, lParam
);
344 return DefWindowProcA( hwnd
, message
, wParam
, lParam
);
351 /***********************************************************************
352 * PROGRESS_Register [Internal]
354 * Registers the progress bar window class.
358 PROGRESS_Register (VOID
)
362 if (GlobalFindAtomA (PROGRESS_CLASSA
)) return;
364 ZeroMemory (&wndClass
, sizeof( WNDCLASSA
));
365 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
| CS_HREDRAW
;
366 wndClass
.lpfnWndProc
= (WNDPROC
)ProgressWindowProc
;
367 wndClass
.cbClsExtra
= 0;
368 wndClass
.cbWndExtra
= sizeof (PROGRESS_INFO
*);
369 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
370 wndClass
.lpszClassName
= PROGRESS_CLASSA
;
372 RegisterClassA (&wndClass
);
376 /***********************************************************************
377 * PROGRESS_Unregister [Internal]
379 * Unregisters the progress bar window class.
383 PROGRESS_Unregister (VOID
)
385 if (GlobalFindAtomA (PROGRESS_CLASSA
))
386 UnregisterClassA (PROGRESS_CLASSA
, (HINSTANCE
)NULL
);