Removed trailing whitespace.
[wine/wine-gecko.git] / dlls / comctl32 / progress.c
blob5f9aee37b39d780b87712b1c8e6b124877a19af9
1 /*
2 * Progress control
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
22 #include <string.h>
23 #include "winbase.h"
24 #include "commctrl.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(progress);
29 typedef struct
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) */
39 } PROGRESS_INFO;
41 /* Control configuration constants */
43 #define LED_GAP 2
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)
54 RECT rect;
55 HBRUSH hbrBk;
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);
61 else
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)
72 DeleteObject (hbrBk);
74 if(!wParam) ReleaseDC(infoPtr->Self, hdc);
77 /***********************************************************************
78 * PROGRESS_Draw
79 * Draws the progress bar.
81 static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc)
83 HBRUSH hbrBar;
84 int rightBar, rightMost, ledWidth;
85 RECT rect;
86 DWORD dwStyle;
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);
93 else
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;
112 } else {
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)
124 rect.top = rightBar;
125 else
126 rect.right = rightBar;
127 FillRect(hdc, &rect, hbrBar);
128 } else {
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;
137 } else {
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);
152 return 0;
156 /***********************************************************************
157 * PROGRESS_Paint
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)
163 PAINTSTRUCT ps;
164 if (hdc) return PROGRESS_Draw (infoPtr, hdc);
165 hdc = BeginPaint (infoPtr->Self, &ps);
166 PROGRESS_Draw (infoPtr, hdc);
167 EndPaint (infoPtr->Self, &ps);
168 return 0;
172 /***********************************************************************
173 * PROGRESS_CoercePos
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 /***********************************************************************
186 * PROGRESS_SetFont
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 */
194 return hOldFont;
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);
207 return res;
210 /***********************************************************************
211 * ProgressWindowProc
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 );
225 switch(message) {
226 case WM_CREATE:
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;
243 infoPtr->MinVal = 0;
244 infoPtr->MaxVal = 100;
245 infoPtr->CurVal = 0;
246 infoPtr->Step = 10;
247 infoPtr->ColorBar = CLR_DEFAULT;
248 infoPtr->ColorBk = CLR_DEFAULT;
249 infoPtr->Font = 0;
250 TRACE("Progress Ctrl creation, hwnd=%04x\n", hwnd);
251 return 0;
254 case WM_DESTROY:
255 TRACE("Progress Ctrl destruction, hwnd=%04x\n", hwnd);
256 COMCTL32_Free (infoPtr);
257 SetWindowLongW(hwnd, 0, 0);
258 return 0;
260 case WM_ERASEBKGND:
261 PROGRESS_EraseBackground(infoPtr, wParam);
262 return TRUE;
264 case WM_GETFONT:
265 return (LRESULT)infoPtr->Font;
267 case WM_SETFONT:
268 return PROGRESS_SetFont (infoPtr, (HFONT)wParam, (BOOL)lParam);
270 case WM_PAINT:
271 return PROGRESS_Paint (infoPtr, (HDC)wParam);
273 case PBM_DELTAPOS:
275 INT oldVal;
276 if(lParam) UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
277 oldVal = infoPtr->CurVal;
278 if(wParam != 0) {
279 BOOL bErase;
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);
286 return oldVal;
289 case PBM_SETPOS:
291 INT oldVal;
292 if (lParam) UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
293 oldVal = infoPtr->CurVal;
294 if(oldVal != wParam) {
295 BOOL bErase;
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);
302 return oldVal;
305 case PBM_SETRANGE:
306 if (wParam) UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
307 return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam));
309 case PBM_SETSTEP:
311 INT oldStep;
312 if (lParam) UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
313 oldStep = infoPtr->Step;
314 infoPtr->Step = (INT)wParam;
315 return oldStep;
318 case PBM_STEPIT:
320 INT oldVal;
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)
328 BOOL bErase;
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);
333 return oldVal;
336 case PBM_SETRANGE32:
337 return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam);
339 case PBM_GETRANGE:
340 if (lParam) {
341 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
342 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
344 return wParam ? infoPtr->MinVal : infoPtr->MaxVal;
346 case PBM_GETPOS:
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);
354 return 0;
356 case PBM_SETBKCOLOR:
357 if (wParam) UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
358 infoPtr->ColorBk = (COLORREF)lParam;
359 InvalidateRect(hwnd, NULL, TRUE);
360 return 0;
362 default:
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)
377 WNDCLASSW wndClass;
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);