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
);
201 if (!infoPtr
&& (message
!= WM_CREATE
))
202 return DefWindowProcA( hwnd
, message
, wParam
, lParam
);
208 dwExStyle
= GetWindowLongA (hwnd
, GWL_EXSTYLE
);
209 SetWindowLongA (hwnd
, GWL_EXSTYLE
, dwExStyle
| WS_EX_STATICEDGE
);
214 /* allocate memory for info struct */
216 (PROGRESS_INFO
*)COMCTL32_Alloc (sizeof(PROGRESS_INFO
));
217 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
219 /* initialize the info struct */
224 infoPtr
->ColorBar
=CLR_DEFAULT
;
225 infoPtr
->ColorBk
=CLR_DEFAULT
;
226 infoPtr
->hFont
=(HANDLE
)NULL
;
227 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd
);
231 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd
);
232 COMCTL32_Free (infoPtr
);
233 SetWindowLongA(hwnd
, 0, 0);
237 /* pretend to erase it here, but we will do it in the paint
238 function to avoid flicker */
242 return (LRESULT
)infoPtr
->hFont
;
245 return PROGRESS_SetFont (hwnd
, wParam
, lParam
);
248 PROGRESS_Paint (hwnd
);
253 UNKNOWN_PARAM(PBM_DELTAPOS
, wParam
, lParam
);
254 temp
= infoPtr
->CurVal
;
256 infoPtr
->CurVal
+= (UINT16
)wParam
;
257 PROGRESS_CoercePos (hwnd
);
258 PROGRESS_Refresh (hwnd
);
264 UNKNOWN_PARAM(PBM_SETPOS
, wParam
, lParam
);
265 temp
= infoPtr
->CurVal
;
267 infoPtr
->CurVal
= (UINT16
)wParam
;
268 PROGRESS_CoercePos(hwnd
);
269 PROGRESS_Refresh (hwnd
);
275 UNKNOWN_PARAM(PBM_SETRANGE
, wParam
, lParam
);
276 temp
= MAKELONG(infoPtr
->MinVal
, infoPtr
->MaxVal
);
278 infoPtr
->MinVal
= LOWORD(lParam
);
279 infoPtr
->MaxVal
= HIWORD(lParam
);
280 if(infoPtr
->MaxVal
<= infoPtr
->MinVal
)
281 infoPtr
->MaxVal
= infoPtr
->MinVal
+1;
282 PROGRESS_CoercePos(hwnd
);
283 PROGRESS_Refresh (hwnd
);
289 UNKNOWN_PARAM(PBM_SETSTEP
, wParam
, lParam
);
290 temp
= infoPtr
->Step
;
291 infoPtr
->Step
= (UINT16
)wParam
;
295 if (wParam
|| lParam
)
296 UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
297 temp
= infoPtr
->CurVal
;
298 infoPtr
->CurVal
+= infoPtr
->Step
;
299 if(infoPtr
->CurVal
> infoPtr
->MaxVal
)
300 infoPtr
->CurVal
= infoPtr
->MinVal
;
301 if(temp
!= infoPtr
->CurVal
)
302 PROGRESS_Refresh (hwnd
);
306 temp
= MAKELONG(infoPtr
->MinVal
, infoPtr
->MaxVal
);
307 if((infoPtr
->MinVal
!= (INT
)wParam
) ||
308 (infoPtr
->MaxVal
!= (INT
)lParam
)) {
309 infoPtr
->MinVal
= (INT
)wParam
;
310 infoPtr
->MaxVal
= (INT
)lParam
;
311 if(infoPtr
->MaxVal
<= infoPtr
->MinVal
)
312 infoPtr
->MaxVal
= infoPtr
->MinVal
+1;
313 PROGRESS_CoercePos(hwnd
);
314 PROGRESS_Refresh (hwnd
);
320 ((PPBRANGE
)lParam
)->iLow
= infoPtr
->MinVal
;
321 ((PPBRANGE
)lParam
)->iHigh
= infoPtr
->MaxVal
;
323 return (wParam
) ? infoPtr
->MinVal
: infoPtr
->MaxVal
;
326 if (wParam
|| lParam
)
327 UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
328 return (infoPtr
->CurVal
);
330 case PBM_SETBARCOLOR
:
332 UNKNOWN_PARAM(PBM_SETBARCOLOR
, wParam
, lParam
);
333 infoPtr
->ColorBar
= (COLORREF
)lParam
;
334 PROGRESS_Refresh (hwnd
);
339 UNKNOWN_PARAM(PBM_SETBKCOLOR
, wParam
, lParam
);
340 infoPtr
->ColorBk
= (COLORREF
)lParam
;
341 PROGRESS_Refresh (hwnd
);
345 if (message
>= WM_USER
)
346 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
347 message
, wParam
, lParam
);
348 return DefWindowProcA( hwnd
, message
, wParam
, lParam
);
355 /***********************************************************************
356 * PROGRESS_Register [Internal]
358 * Registers the progress bar window class.
362 PROGRESS_Register (void)
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 UnregisterClassA (PROGRESS_CLASSA
, (HINSTANCE
)NULL
);