source: trunk/src/comctl32/progress.c@ 8382

Last change on this file since 8382 was 8382, checked in by sandervl, 23 years ago

merge with latest Wine

File size: 11.9 KB
Line 
1/*
2 * Progress control
3 *
4 * Copyright 1997, 2002 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
6 *
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.
11 *
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.
16 *
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
20 */
21
22#include <string.h>
23#include "winbase.h"
24#include "commctrl.h"
25#include "wine/debug.h"
26
27WINE_DEFAULT_DEBUG_CHANNEL(progress);
28
29typedef struct
30{
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;
40
41/* Control configuration constants */
42
43#define LED_GAP 2
44
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);
48
49/***********************************************************************
50 * PROGRESS_EraseBackground
51 */
52static void PROGRESS_EraseBackground(PROGRESS_INFO *infoPtr, WPARAM wParam)
53{
54 RECT rect;
55 HBRUSH hbrBk;
56 HDC hdc = wParam ? (HDC)wParam : GetDC(infoPtr->Self);
57
58 /* get the required background brush */
59 if(infoPtr->ColorBk == CLR_DEFAULT)
60 hbrBk = GetSysColorBrush(COLOR_3DFACE);
61 else
62 hbrBk = CreateSolidBrush(infoPtr->ColorBk);
63
64 /* get client rectangle */
65 GetClientRect(infoPtr->Self, &rect);
66
67 /* draw the background */
68 FillRect(hdc, &rect, hbrBk);
69
70 /* delete background brush */
71 if(infoPtr->ColorBk != CLR_DEFAULT)
72 DeleteObject (hbrBk);
73
74 if(!wParam) ReleaseDC(infoPtr->Self, hdc);
75}
76
77/***********************************************************************
78 * PROGRESS_Draw
79 * Draws the progress bar.
80 */
81static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc)
82{
83 HBRUSH hbrBar;
84 int rightBar, rightMost, ledWidth;
85 RECT rect;
86 DWORD dwStyle;
87
88 TRACE("(infoPtr=%p, hdc=%x)\n", infoPtr, hdc);
89
90 /* get the required bar brush */
91 if (infoPtr->ColorBar == CLR_DEFAULT)
92 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
93 else
94 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
95
96 /* get client rectangle */
97 GetClientRect (infoPtr->Self, &rect);
98
99 InflateRect(&rect, -1, -1);
100
101 /* get the window style */
102 dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
103
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;
119 }
120
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;
136 }
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;
144 }
145 }
146 }
147
148 /* delete bar brush */
149 if (infoPtr->ColorBar != CLR_DEFAULT)
150 DeleteObject (hbrBar);
151
152 return 0;
153}
154
155
156/***********************************************************************
157 * PROGRESS_Paint
158 * Draw the progress bar. The background need not be erased.
159 * If dc!=0, it draws on it
160 */
161static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc)
162{
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;
169}
170
171
172/***********************************************************************
173 * PROGRESS_CoercePos
174 * Makes sure the current position (CurVal) is within bounds.
175 */
176static void PROGRESS_CoercePos(PROGRESS_INFO *infoPtr)
177{
178 if(infoPtr->CurVal < infoPtr->MinVal)
179 infoPtr->CurVal = infoPtr->MinVal;
180 if(infoPtr->CurVal > infoPtr->MaxVal)
181 infoPtr->CurVal = infoPtr->MaxVal;
182}
183
184
185/***********************************************************************
186 * PROGRESS_SetFont
187 * Set new Font for progress bar
188 */
189static HFONT PROGRESS_SetFont (PROGRESS_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
190{
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;
195}
196
197static DWORD PROGRESS_SetRange (PROGRESS_INFO *infoPtr, int low, int high)
198{
199 DWORD res = MAKELONG(LOWORD(infoPtr->MinVal), LOWORD(infoPtr->MaxVal));
200
201 /* if nothing changes, simply return */
202 if(infoPtr->MinVal == low && infoPtr->MaxVal == high) return res;
203
204 infoPtr->MinVal = low;
205 infoPtr->MaxVal = high;
206 PROGRESS_CoercePos(infoPtr);
207 return res;
208}
209
210/***********************************************************************
211 * ProgressWindowProc
212 */
213static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
214 WPARAM wParam, LPARAM lParam)
215{
216 PROGRESS_INFO *infoPtr;
217
218 TRACE("hwnd=%x msg=%04x wparam=%x lParam=%lx\n", hwnd, message, wParam, lParam);
219
220 infoPtr = (PROGRESS_INFO *)GetWindowLongW(hwnd, 0);
221
222 if (!infoPtr && message != WM_CREATE)
223 return DefWindowProcW( hwnd, message, wParam, lParam );
224
225 switch(message) {
226 case WM_CREATE:
227 {
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);
235
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);
240
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;
252 }
253
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;
259
260 case WM_ERASEBKGND:
261 PROGRESS_EraseBackground(infoPtr, wParam);
262 return TRUE;
263
264 case WM_GETFONT:
265 return (LRESULT)infoPtr->Font;
266
267 case WM_SETFONT:
268 return PROGRESS_SetFont (infoPtr, (HFONT)wParam, (BOOL)lParam);
269
270 case WM_PAINT:
271 return PROGRESS_Paint (infoPtr, (HDC)wParam);
272
273 case PBM_DELTAPOS:
274 {
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);
285 }
286 return oldVal;
287 }
288
289 case PBM_SETPOS:
290 {
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);
301 }
302 return oldVal;
303 }
304
305 case PBM_SETRANGE:
306 if (wParam) UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
307 return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam));
308
309 case PBM_SETSTEP:
310 {
311 INT oldStep;
312 if (lParam) UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
313 oldStep = infoPtr->Step;
314 infoPtr->Step = (INT)wParam;
315 return oldStep;
316 }
317
318 case PBM_STEPIT:
319 {
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)
327 {
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);
332 }
333 return oldVal;
334 }
335
336 case PBM_SETRANGE32:
337 return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam);
338
339 case PBM_GETRANGE:
340 if (lParam) {
341 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
342 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
343 }
344 return wParam ? infoPtr->MinVal : infoPtr->MaxVal;
345
346 case PBM_GETPOS:
347 if (wParam || lParam) UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
348 return infoPtr->CurVal;
349
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;
355
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;
361
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 );
366 }
367}
368
369
370/***********************************************************************
371 * PROGRESS_Register [Internal]
372 *
373 * Registers the progress bar window class.
374 */
375VOID PROGRESS_Register (void)
376{
377 WNDCLASSW wndClass;
378
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;
386
387 RegisterClassW (&wndClass);
388}
389
390
391/***********************************************************************
392 * PROGRESS_Unregister [Internal]
393 *
394 * Unregisters the progress bar window class.
395 */
396VOID PROGRESS_Unregister (void)
397{
398 UnregisterClassW (PROGRESS_CLASSW, (HINSTANCE)NULL);
399}
400
Note: See TracBrowser for help on using the repository browser.