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
);