4 * Copyright 1997, 2002 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(progress
);
31 HWND Self
; /* The window handle for this control */
32 INT CurVal
; /* Current progress value */
33 INT MinVal
; /* Minimum progress value */
34 INT MaxVal
; /* Maximum progress value */
35 INT Step
; /* Step to use on PMB_STEPIT */
36 COLORREF ColorBar
; /* Bar color */
37 COLORREF ColorBk
; /* Background color */
38 HFONT Font
; /* Handle to font (not unused) */
41 /* Control configuration constants */
45 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN( \
46 "Unknown parameter(s) for message " #msg \
47 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
49 /***********************************************************************
50 * PROGRESS_EraseBackground
52 static void PROGRESS_EraseBackground(PROGRESS_INFO
*infoPtr
, WPARAM wParam
)
56 HDC hdc
= wParam
? (HDC
)wParam
: GetDC(infoPtr
->Self
);
58 /* get the required background brush */
59 if(infoPtr
->ColorBk
== CLR_DEFAULT
)
60 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
62 hbrBk
= CreateSolidBrush(infoPtr
->ColorBk
);
64 /* get client rectangle */
65 GetClientRect(infoPtr
->Self
, &rect
);
67 /* draw the background */
68 FillRect(hdc
, &rect
, hbrBk
);
70 /* delete background brush */
71 if(infoPtr
->ColorBk
!= CLR_DEFAULT
)
74 if(!wParam
) ReleaseDC(infoPtr
->Self
, hdc
);
77 /***********************************************************************
79 * Draws the progress bar.
81 static LRESULT
PROGRESS_Draw (PROGRESS_INFO
*infoPtr
, HDC hdc
)
84 int rightBar
, rightMost
, ledWidth
;
88 TRACE("(infoPtr=%p, hdc=%x)\n", infoPtr
, hdc
);
90 /* get the required bar brush */
91 if (infoPtr
->ColorBar
== CLR_DEFAULT
)
92 hbrBar
= GetSysColorBrush(COLOR_HIGHLIGHT
);
94 hbrBar
= CreateSolidBrush (infoPtr
->ColorBar
);
96 /* get client rectangle */
97 GetClientRect (infoPtr
->Self
, &rect
);
99 InflateRect(&rect
, -1, -1);
101 /* get the window style */
102 dwStyle
= GetWindowLongW (infoPtr
->Self
, GWL_STYLE
);
104 /* compute extent of progress bar */
105 if (dwStyle
& PBS_VERTICAL
) {
106 rightBar
= rect
.bottom
-
107 MulDiv (infoPtr
->CurVal
- infoPtr
->MinVal
,
108 rect
.bottom
- rect
.top
,
109 infoPtr
->MaxVal
- infoPtr
->MinVal
);
110 ledWidth
= MulDiv (rect
.right
- rect
.left
, 2, 3);
111 rightMost
= rect
.top
;
113 rightBar
= rect
.left
+
114 MulDiv (infoPtr
->CurVal
- infoPtr
->MinVal
,
115 rect
.right
- rect
.left
,
116 infoPtr
->MaxVal
- infoPtr
->MinVal
);
117 ledWidth
= MulDiv (rect
.bottom
- rect
.top
, 2, 3);
118 rightMost
= rect
.right
;
121 /* now draw the bar */
122 if (dwStyle
& PBS_SMOOTH
) {
123 if (dwStyle
& PBS_VERTICAL
)
126 rect
.right
= rightBar
;
127 FillRect(hdc
, &rect
, hbrBar
);
129 if (dwStyle
& PBS_VERTICAL
) {
130 while(rect
.bottom
> rightBar
) {
131 rect
.top
= rect
.bottom
- ledWidth
;
132 if (rect
.top
< rightMost
)
133 rect
.top
= rightMost
;
134 FillRect(hdc
, &rect
, hbrBar
);
135 rect
.bottom
= rect
.top
- LED_GAP
;
138 while(rect
.left
< rightBar
) {
139 rect
.right
= rect
.left
+ ledWidth
;
140 if (rect
.right
> rightMost
)
141 rect
.right
= rightMost
;
142 FillRect(hdc
, &rect
, hbrBar
);
143 rect
.left
= rect
.right
+ LED_GAP
;
148 /* delete bar brush */
149 if (infoPtr
->ColorBar
!= CLR_DEFAULT
)
150 DeleteObject (hbrBar
);
156 /***********************************************************************
158 * Draw the progress bar. The background need not be erased.
159 * If dc!=0, it draws on it
161 static LRESULT
PROGRESS_Paint (PROGRESS_INFO
*infoPtr
, HDC hdc
)
164 if (hdc
) return PROGRESS_Draw (infoPtr
, hdc
);
165 hdc
= BeginPaint (infoPtr
->Self
, &ps
);
166 PROGRESS_Draw (infoPtr
, hdc
);
167 EndPaint (infoPtr
->Self
, &ps
);
172 /***********************************************************************
174 * Makes sure the current position (CurVal) is within bounds.
176 static void PROGRESS_CoercePos(PROGRESS_INFO
*infoPtr
)
178 if(infoPtr
->CurVal
< infoPtr
->MinVal
)
179 infoPtr
->CurVal
= infoPtr
->MinVal
;
180 if(infoPtr
->CurVal
> infoPtr
->MaxVal
)
181 infoPtr
->CurVal
= infoPtr
->MaxVal
;
185 /***********************************************************************
187 * Set new Font for progress bar
189 static HFONT
PROGRESS_SetFont (PROGRESS_INFO
*infoPtr
, HFONT hFont
, BOOL bRedraw
)
191 HFONT hOldFont
= infoPtr
->Font
;
192 infoPtr
->Font
= hFont
;
193 /* Since infoPtr->Font is not used, there is no need for repaint */
197 static DWORD
PROGRESS_SetRange (PROGRESS_INFO
*infoPtr
, int low
, int high
)
199 DWORD res
= MAKELONG(LOWORD(infoPtr
->MinVal
), LOWORD(infoPtr
->MaxVal
));
201 /* if nothing changes, simply return */
202 if(infoPtr
->MinVal
== low
&& infoPtr
->MaxVal
== high
) return res
;
204 infoPtr
->MinVal
= low
;
205 infoPtr
->MaxVal
= high
;
206 PROGRESS_CoercePos(infoPtr
);
210 /***********************************************************************
213 static LRESULT WINAPI
ProgressWindowProc(HWND hwnd
, UINT message
,
214 WPARAM wParam
, LPARAM lParam
)
216 PROGRESS_INFO
*infoPtr
;
218 TRACE("hwnd=%x msg=%04x wparam=%x lParam=%lx\n", hwnd
, message
, wParam
, lParam
);
220 infoPtr
= (PROGRESS_INFO
*)GetWindowLongW(hwnd
, 0);
222 if (!infoPtr
&& message
!= WM_CREATE
)
223 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
228 DWORD dwExStyle
= GetWindowLongW (hwnd
, GWL_EXSTYLE
);
229 dwExStyle
&= ~(WS_EX_CLIENTEDGE
| WS_EX_WINDOWEDGE
);
230 dwExStyle
|= WS_EX_STATICEDGE
;
231 SetWindowLongW (hwnd
, GWL_EXSTYLE
, dwExStyle
| WS_EX_STATICEDGE
);
232 /* Force recalculation of a non-client area */
233 SetWindowPos(hwnd
, 0, 0, 0, 0, 0,
234 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
236 /* allocate memory for info struct */
237 infoPtr
= (PROGRESS_INFO
*)COMCTL32_Alloc (sizeof(PROGRESS_INFO
));
238 if (!infoPtr
) return -1;
239 SetWindowLongW (hwnd
, 0, (DWORD
)infoPtr
);
241 /* initialize the info struct */
242 infoPtr
->Self
= hwnd
;
244 infoPtr
->MaxVal
= 100;
247 infoPtr
->ColorBar
= CLR_DEFAULT
;
248 infoPtr
->ColorBk
= CLR_DEFAULT
;
250 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd
);
255 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd
);
256 COMCTL32_Free (infoPtr
);
257 SetWindowLongW(hwnd
, 0, 0);
261 PROGRESS_EraseBackground(infoPtr
, wParam
);
265 return (LRESULT
)infoPtr
->Font
;
268 return PROGRESS_SetFont (infoPtr
, (HFONT
)wParam
, (BOOL
)lParam
);
271 return PROGRESS_Paint (infoPtr
, (HDC
)wParam
);
276 if(lParam
) UNKNOWN_PARAM(PBM_DELTAPOS
, wParam
, lParam
);
277 oldVal
= infoPtr
->CurVal
;
280 infoPtr
->CurVal
+= (INT
)wParam
;
281 PROGRESS_CoercePos (infoPtr
);
282 TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal
, infoPtr
->CurVal
);
283 bErase
= (oldVal
> infoPtr
->CurVal
);
284 InvalidateRect(hwnd
, NULL
, bErase
);
292 if (lParam
) UNKNOWN_PARAM(PBM_SETPOS
, wParam
, lParam
);
293 oldVal
= infoPtr
->CurVal
;
294 if(oldVal
!= wParam
) {
296 infoPtr
->CurVal
= (INT
)wParam
;
297 PROGRESS_CoercePos(infoPtr
);
298 TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal
, infoPtr
->CurVal
);
299 bErase
= (oldVal
> infoPtr
->CurVal
);
300 InvalidateRect(hwnd
, NULL
, bErase
);
306 if (wParam
) UNKNOWN_PARAM(PBM_SETRANGE
, wParam
, lParam
);
307 return PROGRESS_SetRange (infoPtr
, (int)LOWORD(lParam
), (int)HIWORD(lParam
));
312 if (lParam
) UNKNOWN_PARAM(PBM_SETSTEP
, wParam
, lParam
);
313 oldStep
= infoPtr
->Step
;
314 infoPtr
->Step
= (INT
)wParam
;
321 if (wParam
|| lParam
) UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
322 oldVal
= infoPtr
->CurVal
;
323 infoPtr
->CurVal
+= infoPtr
->Step
;
324 if(infoPtr
->CurVal
> infoPtr
->MaxVal
)
325 infoPtr
->CurVal
= infoPtr
->MinVal
;
326 if(oldVal
!= infoPtr
->CurVal
)
329 TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal
, infoPtr
->CurVal
);
330 bErase
= (oldVal
> infoPtr
->CurVal
);
331 InvalidateRect(hwnd
, NULL
, bErase
);
337 return PROGRESS_SetRange (infoPtr
, (int)wParam
, (int)lParam
);
341 ((PPBRANGE
)lParam
)->iLow
= infoPtr
->MinVal
;
342 ((PPBRANGE
)lParam
)->iHigh
= infoPtr
->MaxVal
;
344 return wParam
? infoPtr
->MinVal
: infoPtr
->MaxVal
;
347 if (wParam
|| lParam
) UNKNOWN_PARAM(PBM_STEPIT
, wParam
, lParam
);
348 return infoPtr
->CurVal
;
350 case PBM_SETBARCOLOR
:
351 if (wParam
) UNKNOWN_PARAM(PBM_SETBARCOLOR
, wParam
, lParam
);
352 infoPtr
->ColorBar
= (COLORREF
)lParam
;
353 InvalidateRect(hwnd
, NULL
, TRUE
);
357 if (wParam
) UNKNOWN_PARAM(PBM_SETBKCOLOR
, wParam
, lParam
);
358 infoPtr
->ColorBk
= (COLORREF
)lParam
;
359 InvalidateRect(hwnd
, NULL
, TRUE
);
363 if (message
>= WM_USER
)
364 ERR("unknown msg %04x wp=%04x lp=%08lx\n", message
, wParam
, lParam
);
365 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
370 /***********************************************************************
371 * PROGRESS_Register [Internal]
373 * Registers the progress bar window class.
375 VOID
PROGRESS_Register (void)
379 ZeroMemory (&wndClass
, sizeof(wndClass
));
380 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
| CS_HREDRAW
;
381 wndClass
.lpfnWndProc
= (WNDPROC
)ProgressWindowProc
;
382 wndClass
.cbClsExtra
= 0;
383 wndClass
.cbWndExtra
= sizeof (PROGRESS_INFO
*);
384 wndClass
.hCursor
= LoadCursorW (0, IDC_ARROWW
);
385 wndClass
.lpszClassName
= PROGRESS_CLASSW
;
387 RegisterClassW (&wndClass
);
391 /***********************************************************************
392 * PROGRESS_Unregister [Internal]
394 * Unregisters the progress bar window class.
396 VOID
PROGRESS_Unregister (void)
398 UnregisterClassW (PROGRESS_CLASSW
, (HINSTANCE
)NULL
);