kernel32/tests: Detect and handle a redirected stdin.
[wine.git] / dlls / comctl32 / progress.c
blob4638ffcd3c036c8c6a0929bdbcad820b5f4765b0
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * NOTE
23 * This code was audited for completeness against the documented features
24 * of Comctl32.dll version 6.0 on Sep. 9, 2002, by Dimitrie O. Paun.
26 * Unless otherwise noted, we believe this code to be complete, as per
27 * the specification mentioned above.
28 * If you discover missing features, or bugs, please note them below.
30 * TODO:
32 * Styles:
33 * -- PBS_SMOOTHREVERSE
37 #include <stdarg.h>
38 #include <string.h>
39 #include "windef.h"
40 #include "winbase.h"
41 #include "wingdi.h"
42 #include "winuser.h"
43 #include "winnls.h"
44 #include "commctrl.h"
45 #include "comctl32.h"
46 #include "uxtheme.h"
47 #include "vssym32.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(progress);
52 typedef struct
54 HWND Self; /* The window handle for this control */
55 INT CurVal; /* Current progress value */
56 INT MinVal; /* Minimum progress value */
57 INT MaxVal; /* Maximum progress value */
58 INT Step; /* Step to use on PMB_STEPIT */
59 INT MarqueePos; /* Marquee animation position */
60 BOOL Marquee; /* Whether the marquee animation is enabled */
61 COLORREF ColorBar; /* Bar color */
62 COLORREF ColorBk; /* Background color */
63 HFONT Font; /* Handle to font (not unused) */
64 } PROGRESS_INFO;
66 /* Control configuration constants */
68 #define LED_GAP 2
69 #define MARQUEE_LEDS 5
70 #define ID_MARQUEE_TIMER 1
71 #define DEFAULT_MARQUEE_PERIOD 30
73 /* Helper to obtain size of a progress bar chunk ("led"). */
74 static inline int get_led_size ( const PROGRESS_INFO *infoPtr, LONG style,
75 const RECT* rect )
77 HTHEME theme = GetWindowTheme (infoPtr->Self);
78 if (theme)
80 int chunkSize;
81 if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSCHUNKSIZE, &chunkSize )))
82 return chunkSize;
85 if (style & PBS_VERTICAL)
86 return MulDiv (rect->right - rect->left, 2, 3);
87 else
88 return MulDiv (rect->bottom - rect->top, 2, 3);
91 /* Helper to obtain gap between progress bar chunks */
92 static inline int get_led_gap ( const PROGRESS_INFO *infoPtr )
94 HTHEME theme = GetWindowTheme (infoPtr->Self);
95 if (theme)
97 int spaceSize;
98 if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSSPACESIZE, &spaceSize )))
99 return spaceSize;
102 return LED_GAP;
105 /* Get client rect. Takes into account that theming needs no adjustment. */
106 static inline void get_client_rect (HWND hwnd, RECT* rect)
108 HTHEME theme = GetWindowTheme (hwnd);
109 GetClientRect (hwnd, rect);
110 if (!theme)
111 InflateRect(rect, -1, -1);
112 else
114 DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
115 int part = (dwStyle & PBS_VERTICAL) ? PP_BARVERT : PP_BAR;
116 GetThemeBackgroundContentRect (theme, 0, part, 0, rect, rect);
120 /* Compute the extend of the bar */
121 static inline int get_bar_size( LONG style, const RECT* rect )
123 if (style & PBS_VERTICAL)
124 return rect->bottom - rect->top;
125 else
126 return rect->right - rect->left;
129 /* Compute the pixel position of a progress value */
130 static inline int get_bar_position( const PROGRESS_INFO *infoPtr, LONG style,
131 const RECT* rect, INT value )
133 return MulDiv (value - infoPtr->MinVal, get_bar_size (style, rect),
134 infoPtr->MaxVal - infoPtr->MinVal);
137 /***********************************************************************
138 * PROGRESS_Invalidate
140 * Don't be too clever about invalidating the progress bar.
141 * InstallShield depends on this simple behaviour.
143 static void PROGRESS_Invalidate( const PROGRESS_INFO *infoPtr, INT old, INT new )
145 InvalidateRect( infoPtr->Self, NULL, old > new );
148 /* Information for a progress bar drawing helper */
149 typedef struct tagProgressDrawInfo
151 HDC hdc;
152 RECT rect;
153 HBRUSH hbrBar;
154 HBRUSH hbrBk;
155 int ledW, ledGap;
156 HTHEME theme;
157 RECT bgRect;
158 } ProgressDrawInfo;
160 typedef void (*ProgressDrawProc)(const ProgressDrawInfo* di, int start, int end);
162 /* draw solid horizontal bar from 'start' to 'end' */
163 static void draw_solid_bar_H (const ProgressDrawInfo* di, int start, int end)
165 RECT r;
166 SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
167 FillRect (di->hdc, &r, di->hbrBar);
170 /* draw solid horizontal background from 'start' to 'end' */
171 static void draw_solid_bkg_H (const ProgressDrawInfo* di, int start, int end)
173 RECT r;
174 SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
175 FillRect (di->hdc, &r, di->hbrBk);
178 /* draw solid vertical bar from 'start' to 'end' */
179 static void draw_solid_bar_V (const ProgressDrawInfo* di, int start, int end)
181 RECT r;
182 SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
183 FillRect (di->hdc, &r, di->hbrBar);
186 /* draw solid vertical background from 'start' to 'end' */
187 static void draw_solid_bkg_V (const ProgressDrawInfo* di, int start, int end)
189 RECT r;
190 SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
191 FillRect (di->hdc, &r, di->hbrBk);
194 /* draw chunky horizontal bar from 'start' to 'end' */
195 static void draw_chunk_bar_H (const ProgressDrawInfo* di, int start, int end)
197 RECT r;
198 int right = di->rect.left + end;
199 r.left = di->rect.left + start;
200 r.top = di->rect.top;
201 r.bottom = di->rect.bottom;
202 while (r.left < right)
204 r.right = min (r.left + di->ledW, right);
205 FillRect (di->hdc, &r, di->hbrBar);
206 r.left = r.right;
207 r.right = min (r.left + di->ledGap, right);
208 FillRect (di->hdc, &r, di->hbrBk);
209 r.left = r.right;
213 /* draw chunky vertical bar from 'start' to 'end' */
214 static void draw_chunk_bar_V (const ProgressDrawInfo* di, int start, int end)
216 RECT r;
217 int top = di->rect.bottom - end;
218 r.left = di->rect.left;
219 r.right = di->rect.right;
220 r.bottom = di->rect.bottom - start;
221 while (r.bottom > top)
223 r.top = max (r.bottom - di->ledW, top);
224 FillRect (di->hdc, &r, di->hbrBar);
225 r.bottom = r.top;
226 r.top = max (r.bottom - di->ledGap, top);
227 FillRect (di->hdc, &r, di->hbrBk);
228 r.bottom = r.top;
232 /* drawing functions for "classic" style */
233 static const ProgressDrawProc drawProcClassic[8] = {
234 /* Smooth */
235 /* Horizontal */
236 draw_solid_bar_H, draw_solid_bkg_H,
237 /* Vertical */
238 draw_solid_bar_V, draw_solid_bkg_V,
239 /* Chunky */
240 /* Horizontal */
241 draw_chunk_bar_H, draw_solid_bkg_H,
242 /* Vertical */
243 draw_chunk_bar_V, draw_solid_bkg_V,
246 /* draw themed horizontal bar from 'start' to 'end' */
247 static void draw_theme_bar_H (const ProgressDrawInfo* di, int start, int end)
249 RECT r;
250 r.left = di->rect.left + start;
251 r.top = di->rect.top;
252 r.bottom = di->rect.bottom;
253 r.right = di->rect.left + end;
254 DrawThemeBackground (di->theme, di->hdc, PP_CHUNK, 0, &r, NULL);
257 /* draw themed vertical bar from 'start' to 'end' */
258 static void draw_theme_bar_V (const ProgressDrawInfo* di, int start, int end)
260 RECT r;
261 r.left = di->rect.left;
262 r.right = di->rect.right;
263 r.bottom = di->rect.bottom - start;
264 r.top = di->rect.bottom - end;
265 DrawThemeBackground (di->theme, di->hdc, PP_CHUNKVERT, 0, &r, NULL);
268 /* draw themed horizontal background from 'start' to 'end' */
269 static void draw_theme_bkg_H (const ProgressDrawInfo* di, int start, int end)
271 RECT bgrect, r;
273 SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
274 bgrect = di->bgRect;
275 OffsetRect(&bgrect, -bgrect.left, -bgrect.top);
277 DrawThemeBackground (di->theme, di->hdc, PP_BAR, 0, &bgrect, &r);
280 /* draw themed vertical background from 'start' to 'end' */
281 static void draw_theme_bkg_V (const ProgressDrawInfo* di, int start, int end)
283 RECT bgrect, r;
285 SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
286 bgrect = di->bgRect;
287 OffsetRect(&bgrect, -bgrect.left, -bgrect.top);
289 DrawThemeBackground (di->theme, di->hdc, PP_BARVERT, 0, &bgrect, &r);
292 /* drawing functions for themed style */
293 static const ProgressDrawProc drawProcThemed[8] = {
294 /* Smooth */
295 /* Horizontal */
296 draw_theme_bar_H, draw_theme_bkg_H,
297 /* Vertical */
298 draw_theme_bar_V, draw_theme_bkg_V,
299 /* Chunky */
300 /* Horizontal */
301 draw_theme_bar_H, draw_theme_bkg_H,
302 /* Vertical */
303 draw_theme_bar_V, draw_theme_bkg_V,
306 /***********************************************************************
307 * PROGRESS_Draw
308 * Draws the progress bar.
310 static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc)
312 int barSize;
313 DWORD dwStyle;
314 BOOL barSmooth;
315 const ProgressDrawProc* drawProcs;
316 ProgressDrawInfo pdi;
318 TRACE("(infoPtr=%p, hdc=%p)\n", infoPtr, hdc);
320 pdi.hdc = hdc;
321 pdi.theme = GetWindowTheme (infoPtr->Self);
323 /* get the required bar brush */
324 if (infoPtr->ColorBar == CLR_DEFAULT)
325 pdi.hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
326 else
327 pdi.hbrBar = CreateSolidBrush (infoPtr->ColorBar);
329 if (infoPtr->ColorBk == CLR_DEFAULT)
330 pdi.hbrBk = GetSysColorBrush(COLOR_3DFACE);
331 else
332 pdi.hbrBk = CreateSolidBrush(infoPtr->ColorBk);
334 /* get the window style */
335 dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
337 /* get client rectangle */
338 GetClientRect (infoPtr->Self, &pdi.rect);
339 if (!pdi.theme) {
340 FrameRect( hdc, &pdi.rect, pdi.hbrBk );
341 InflateRect(&pdi.rect, -1, -1);
343 else
345 RECT cntRect;
346 int part = (dwStyle & PBS_VERTICAL) ? PP_BARVERT : PP_BAR;
348 GetThemeBackgroundContentRect (pdi.theme, hdc, part, 0, &pdi.rect,
349 &cntRect);
351 /* Exclude content rect - content background will be drawn later */
352 ExcludeClipRect (hdc, cntRect.left, cntRect.top,
353 cntRect.right, cntRect.bottom);
354 if (IsThemeBackgroundPartiallyTransparent (pdi.theme, part, 0))
355 DrawThemeParentBackground (infoPtr->Self, hdc, NULL);
356 DrawThemeBackground (pdi.theme, hdc, part, 0, &pdi.rect, NULL);
357 SelectClipRgn (hdc, NULL);
358 pdi.rect = cntRect;
361 /* compute some drawing parameters */
362 barSmooth = (dwStyle & PBS_SMOOTH) && !pdi.theme;
363 drawProcs = &((pdi.theme ? drawProcThemed : drawProcClassic)[(barSmooth ? 0 : 4)
364 + ((dwStyle & PBS_VERTICAL) ? 2 : 0)]);
365 barSize = get_bar_size( dwStyle, &pdi.rect );
366 if (pdi.theme)
368 GetWindowRect( infoPtr->Self, &pdi.bgRect );
369 MapWindowPoints( infoPtr->Self, 0, (POINT*)&pdi.bgRect, 2 );
372 if (!barSmooth)
373 pdi.ledW = get_led_size( infoPtr, dwStyle, &pdi.rect);
374 pdi.ledGap = get_led_gap( infoPtr );
376 if (dwStyle & PBS_MARQUEE)
378 const int ledW = !barSmooth ? (pdi.ledW + pdi.ledGap) : 1;
379 const int leds = (barSize + ledW - 1) / ledW;
380 const int ledMEnd = infoPtr->MarqueePos + MARQUEE_LEDS;
382 if (ledMEnd > leds)
384 /* case 1: the marquee bar extends over the end and wraps around to
385 * the start */
386 const int gapStart = max((ledMEnd - leds) * ledW, 0);
387 const int gapEnd = min(infoPtr->MarqueePos * ledW, barSize);
389 drawProcs[0]( &pdi, 0, gapStart);
390 drawProcs[1]( &pdi, gapStart, gapEnd);
391 drawProcs[0]( &pdi, gapEnd, barSize);
393 else
395 /* case 2: the marquee bar is between start and end */
396 const int barStart = infoPtr->MarqueePos * ledW;
397 const int barEnd = min (ledMEnd * ledW, barSize);
399 drawProcs[1]( &pdi, 0, barStart);
400 drawProcs[0]( &pdi, barStart, barEnd);
401 drawProcs[1]( &pdi, barEnd, barSize);
404 else
406 int barEnd = get_bar_position( infoPtr, dwStyle, &pdi.rect,
407 infoPtr->CurVal);
408 if (!barSmooth)
410 const int ledW = pdi.ledW + pdi.ledGap;
411 barEnd = min (((barEnd + ledW - 1) / ledW) * ledW, barSize);
413 drawProcs[0]( &pdi, 0, barEnd);
414 drawProcs[1]( &pdi, barEnd, barSize);
417 /* delete bar brush */
418 if (infoPtr->ColorBar != CLR_DEFAULT) DeleteObject (pdi.hbrBar);
419 if (infoPtr->ColorBk != CLR_DEFAULT) DeleteObject (pdi.hbrBk);
421 return 0;
424 /***********************************************************************
425 * PROGRESS_Paint
426 * Draw the progress bar. The background need not be erased.
427 * If dc!=0, it draws on it
429 static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc)
431 PAINTSTRUCT ps;
432 if (hdc) return PROGRESS_Draw (infoPtr, hdc);
433 hdc = BeginPaint (infoPtr->Self, &ps);
434 PROGRESS_Draw (infoPtr, hdc);
435 EndPaint (infoPtr->Self, &ps);
436 return 0;
440 /***********************************************************************
441 * Advance marquee progress by one step.
443 static void PROGRESS_UpdateMarquee (PROGRESS_INFO *infoPtr)
445 LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE);
446 RECT rect;
447 int ledWidth, leds;
448 HTHEME theme = GetWindowTheme (infoPtr->Self);
449 BOOL smooth = (style & PBS_SMOOTH) && !theme;
451 get_client_rect (infoPtr->Self, &rect);
453 if (smooth)
454 ledWidth = 1;
455 else
456 ledWidth = get_led_size( infoPtr, style, &rect ) + get_led_gap( infoPtr );
458 leds = (get_bar_size( style, &rect ) + ledWidth - 1) /
459 ledWidth;
461 /* increment the marquee progress */
462 if (++infoPtr->MarqueePos >= leds)
463 infoPtr->MarqueePos = 0;
465 InvalidateRect(infoPtr->Self, &rect, TRUE);
466 UpdateWindow(infoPtr->Self);
470 /***********************************************************************
471 * PROGRESS_CoercePos
472 * Makes sure the current position (CurVal) is within bounds.
474 static void PROGRESS_CoercePos(PROGRESS_INFO *infoPtr)
476 if(infoPtr->CurVal < infoPtr->MinVal)
477 infoPtr->CurVal = infoPtr->MinVal;
478 if(infoPtr->CurVal > infoPtr->MaxVal)
479 infoPtr->CurVal = infoPtr->MaxVal;
483 /***********************************************************************
484 * PROGRESS_SetFont
485 * Set new Font for progress bar
487 static HFONT PROGRESS_SetFont (PROGRESS_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
489 HFONT hOldFont = infoPtr->Font;
490 infoPtr->Font = hFont;
491 /* Since infoPtr->Font is not used, there is no need for repaint */
492 return hOldFont;
495 static DWORD PROGRESS_SetRange (PROGRESS_INFO *infoPtr, int low, int high)
497 DWORD res = MAKELONG(LOWORD(infoPtr->MinVal), LOWORD(infoPtr->MaxVal));
499 /* if nothing changes, simply return */
500 if(infoPtr->MinVal == low && infoPtr->MaxVal == high) return res;
502 infoPtr->MinVal = low;
503 infoPtr->MaxVal = high;
504 PROGRESS_CoercePos(infoPtr);
505 InvalidateRect(infoPtr->Self, NULL, TRUE);
506 return res;
509 static UINT PROGRESS_SetPos (PROGRESS_INFO *infoPtr, INT pos)
511 DWORD style = GetWindowLongW(infoPtr->Self, GWL_STYLE);
513 if (style & PBS_MARQUEE)
515 PROGRESS_UpdateMarquee(infoPtr);
516 return 1;
518 else
520 UINT oldVal;
521 oldVal = infoPtr->CurVal;
522 if (oldVal != pos) {
523 infoPtr->CurVal = pos;
524 PROGRESS_CoercePos(infoPtr);
525 TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
526 PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
527 UpdateWindow( infoPtr->Self );
529 return oldVal;
533 /***********************************************************************
534 * ProgressWindowProc
536 static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
537 WPARAM wParam, LPARAM lParam)
539 PROGRESS_INFO *infoPtr;
540 static const WCHAR themeClass[] = {'P','r','o','g','r','e','s','s',0};
541 HTHEME theme;
543 TRACE("hwnd=%p msg=%04x wparam=%lx lParam=%lx\n", hwnd, message, wParam, lParam);
545 infoPtr = (PROGRESS_INFO *)GetWindowLongPtrW(hwnd, 0);
547 if (!infoPtr && message != WM_CREATE)
548 return DefWindowProcW( hwnd, message, wParam, lParam );
550 switch(message) {
551 case WM_CREATE:
553 DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
555 theme = OpenThemeData (hwnd, themeClass);
557 dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
558 if (!theme) dwExStyle |= WS_EX_STATICEDGE;
559 SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle);
560 /* Force recalculation of a non-client area */
561 SetWindowPos(hwnd, 0, 0, 0, 0, 0,
562 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
564 /* allocate memory for info struct */
565 infoPtr = Alloc (sizeof(PROGRESS_INFO));
566 if (!infoPtr) return -1;
567 SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
569 /* initialize the info struct */
570 infoPtr->Self = hwnd;
571 infoPtr->MinVal = 0;
572 infoPtr->MaxVal = 100;
573 infoPtr->CurVal = 0;
574 infoPtr->Step = 10;
575 infoPtr->MarqueePos = 0;
576 infoPtr->Marquee = FALSE;
577 infoPtr->ColorBar = CLR_DEFAULT;
578 infoPtr->ColorBk = CLR_DEFAULT;
579 infoPtr->Font = 0;
581 TRACE("Progress Ctrl creation, hwnd=%p\n", hwnd);
582 return 0;
585 case WM_DESTROY:
586 TRACE("Progress Ctrl destruction, hwnd=%p\n", hwnd);
587 Free (infoPtr);
588 SetWindowLongPtrW(hwnd, 0, 0);
589 theme = GetWindowTheme (hwnd);
590 CloseThemeData (theme);
591 return 0;
593 case WM_ERASEBKGND:
594 return 1;
596 case WM_GETFONT:
597 return (LRESULT)infoPtr->Font;
599 case WM_SETFONT:
600 return (LRESULT)PROGRESS_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
602 case WM_PRINTCLIENT:
603 case WM_PAINT:
604 return PROGRESS_Paint (infoPtr, (HDC)wParam);
606 case WM_TIMER:
607 if (wParam == ID_MARQUEE_TIMER)
608 PROGRESS_UpdateMarquee (infoPtr);
609 return 0;
611 case WM_THEMECHANGED:
613 DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
615 theme = GetWindowTheme (hwnd);
616 CloseThemeData (theme);
617 theme = OpenThemeData (hwnd, themeClass);
619 /* WS_EX_STATICEDGE disappears when the control is themed */
620 if (theme)
621 dwExStyle &= ~WS_EX_STATICEDGE;
622 else
623 dwExStyle |= WS_EX_STATICEDGE;
624 SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle);
626 InvalidateRect (hwnd, NULL, FALSE);
627 return 0;
630 case PBM_DELTAPOS:
632 INT oldVal;
633 oldVal = infoPtr->CurVal;
634 if(wParam != 0) {
635 infoPtr->CurVal += (INT)wParam;
636 PROGRESS_CoercePos (infoPtr);
637 TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
638 PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
639 UpdateWindow( infoPtr->Self );
641 return oldVal;
644 case PBM_SETPOS:
645 return PROGRESS_SetPos(infoPtr, wParam);
647 case PBM_SETRANGE:
648 return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam));
650 case PBM_SETSTEP:
652 INT oldStep;
653 oldStep = infoPtr->Step;
654 infoPtr->Step = (INT)wParam;
655 return oldStep;
658 case PBM_GETSTEP:
659 return infoPtr->Step;
661 case PBM_STEPIT:
663 INT oldVal;
664 oldVal = infoPtr->CurVal;
665 infoPtr->CurVal += infoPtr->Step;
666 if(infoPtr->CurVal > infoPtr->MaxVal)
667 infoPtr->CurVal = infoPtr->MinVal;
668 if(oldVal != infoPtr->CurVal)
670 TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
671 PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
672 UpdateWindow( infoPtr->Self );
674 return oldVal;
677 case PBM_SETRANGE32:
678 return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam);
680 case PBM_GETRANGE:
681 if (lParam) {
682 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
683 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
685 return wParam ? infoPtr->MinVal : infoPtr->MaxVal;
687 case PBM_GETPOS:
688 return infoPtr->CurVal;
690 case PBM_SETBARCOLOR:
692 COLORREF clr = infoPtr->ColorBar;
694 infoPtr->ColorBar = (COLORREF)lParam;
695 InvalidateRect(hwnd, NULL, TRUE);
696 return clr;
699 case PBM_GETBARCOLOR:
700 return infoPtr->ColorBar;
702 case PBM_SETBKCOLOR:
704 COLORREF clr = infoPtr->ColorBk;
706 infoPtr->ColorBk = (COLORREF)lParam;
707 InvalidateRect(hwnd, NULL, TRUE);
708 return clr;
711 case PBM_GETBKCOLOR:
712 return infoPtr->ColorBk;
714 case PBM_SETSTATE:
715 if(wParam != PBST_NORMAL)
716 FIXME("state %04lx not yet handled\n", wParam);
717 return PBST_NORMAL;
719 case PBM_GETSTATE:
720 return PBST_NORMAL;
722 case PBM_SETMARQUEE:
723 if(wParam != 0)
725 UINT period = lParam ? (UINT)lParam : DEFAULT_MARQUEE_PERIOD;
726 infoPtr->Marquee = TRUE;
727 SetTimer(infoPtr->Self, ID_MARQUEE_TIMER, period, NULL);
729 else
731 infoPtr->Marquee = FALSE;
732 KillTimer(infoPtr->Self, ID_MARQUEE_TIMER);
734 return infoPtr->Marquee;
736 default:
737 if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message))
738 ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam );
739 return DefWindowProcW( hwnd, message, wParam, lParam );
744 /***********************************************************************
745 * PROGRESS_Register [Internal]
747 * Registers the progress bar window class.
749 void PROGRESS_Register (void)
751 WNDCLASSW wndClass;
753 ZeroMemory (&wndClass, sizeof(wndClass));
754 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
755 wndClass.lpfnWndProc = ProgressWindowProc;
756 wndClass.cbClsExtra = 0;
757 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
758 wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
759 wndClass.lpszClassName = PROGRESS_CLASSW;
761 RegisterClassW (&wndClass);
765 /***********************************************************************
766 * PROGRESS_Unregister [Internal]
768 * Unregisters the progress bar window class.
770 void PROGRESS_Unregister (void)
772 UnregisterClassW (PROGRESS_CLASSW, NULL);