Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comctl32/progress.c
5965 views
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*
21
* TODO:
22
*
23
* Styles:
24
* -- PBS_SMOOTHREVERSE
25
*
26
*/
27
28
#include <stdarg.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include "windef.h"
32
#include "winbase.h"
33
#include "wingdi.h"
34
#include "winuser.h"
35
#include "winnls.h"
36
#include "commctrl.h"
37
#include "comctl32.h"
38
#include "wine/debug.h"
39
40
WINE_DEFAULT_DEBUG_CHANNEL(progress);
41
42
typedef struct
43
{
44
HWND Self; /* The window handle for this control */
45
INT CurVal; /* Current progress value */
46
INT MinVal; /* Minimum progress value */
47
INT MaxVal; /* Maximum progress value */
48
INT Step; /* Step to use on PMB_STEPIT */
49
INT MarqueePos; /* Marquee animation position */
50
BOOL Marquee; /* Whether the marquee animation is enabled */
51
COLORREF ColorBar; /* Bar color */
52
COLORREF ColorBk; /* Background color */
53
HFONT Font; /* Handle to font (not unused) */
54
UINT State; /* State of progress bar */
55
} PROGRESS_INFO;
56
57
/* Control configuration constants */
58
59
#define LED_GAP 2
60
#define MARQUEE_LEDS 5
61
#define ID_MARQUEE_TIMER 1
62
#define DEFAULT_MARQUEE_PERIOD 30
63
64
/* Helper to obtain size of a progress bar chunk ("led"). */
65
static inline int get_led_size ( const PROGRESS_INFO *infoPtr, LONG style,
66
const RECT* rect )
67
{
68
#if __WINE_COMCTL32_VERSION == 6
69
HTHEME theme = GetWindowTheme (infoPtr->Self);
70
if (theme)
71
{
72
int chunkSize;
73
if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSCHUNKSIZE, &chunkSize )))
74
return chunkSize;
75
}
76
#endif
77
78
if (style & PBS_VERTICAL)
79
return MulDiv (rect->right - rect->left, 2, 3);
80
else
81
return MulDiv (rect->bottom - rect->top, 2, 3);
82
}
83
84
/* Helper to obtain gap between progress bar chunks */
85
static inline int get_led_gap ( const PROGRESS_INFO *infoPtr )
86
{
87
#if __WINE_COMCTL32_VERSION == 6
88
HTHEME theme = GetWindowTheme (infoPtr->Self);
89
if (theme)
90
{
91
int spaceSize;
92
if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSSPACESIZE, &spaceSize )))
93
return spaceSize;
94
}
95
#endif
96
97
return LED_GAP;
98
}
99
100
/* Get client rect. Takes into account that theming needs no adjustment. */
101
static inline void get_client_rect (HWND hwnd, RECT* rect)
102
{
103
#if __WINE_COMCTL32_VERSION == 6
104
HTHEME theme = GetWindowTheme (hwnd);
105
106
if (theme)
107
{
108
DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
109
int part = (dwStyle & PBS_VERTICAL) ? PP_BARVERT : PP_BAR;
110
GetClientRect (hwnd, rect);
111
GetThemeBackgroundContentRect (theme, 0, part, 0, rect, rect);
112
return;
113
}
114
#endif
115
116
GetClientRect (hwnd, rect);
117
InflateRect (rect, -1, -1);
118
}
119
120
/* Compute the extend of the bar */
121
static inline int get_bar_size( LONG style, const RECT* rect )
122
{
123
if (style & PBS_VERTICAL)
124
return rect->bottom - rect->top;
125
else
126
return rect->right - rect->left;
127
}
128
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 )
132
{
133
return MulDiv (value - infoPtr->MinVal, get_bar_size (style, rect),
134
infoPtr->MaxVal - infoPtr->MinVal);
135
}
136
137
/***********************************************************************
138
* PROGRESS_Invalidate
139
*
140
* Don't be too clever about invalidating the progress bar.
141
* InstallShield depends on this simple behaviour.
142
*/
143
static void PROGRESS_Invalidate( const PROGRESS_INFO *infoPtr, INT old, INT new )
144
{
145
InvalidateRect( infoPtr->Self, NULL, old > new );
146
}
147
148
/* Information for a progress bar drawing helper */
149
typedef struct tagProgressDrawInfo
150
{
151
const PROGRESS_INFO *infoPtr;
152
HDC hdc;
153
RECT rect;
154
HBRUSH hbrBar;
155
HBRUSH hbrBk;
156
int ledW, ledGap;
157
} ProgressDrawInfo;
158
159
typedef void (*ProgressDrawProc)(const ProgressDrawInfo* di, int start, int end);
160
161
/* draw solid horizontal bar from 'start' to 'end' */
162
static void draw_solid_bar_H (const ProgressDrawInfo* di, int start, int end)
163
{
164
RECT r;
165
SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
166
FillRect (di->hdc, &r, di->hbrBar);
167
}
168
169
/* draw solid horizontal background from 'start' to 'end' */
170
static void draw_solid_bkg_H (const ProgressDrawInfo* di, int start, int end)
171
{
172
RECT r;
173
SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
174
FillRect (di->hdc, &r, di->hbrBk);
175
}
176
177
/* draw solid vertical bar from 'start' to 'end' */
178
static void draw_solid_bar_V (const ProgressDrawInfo* di, int start, int end)
179
{
180
RECT r;
181
SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
182
FillRect (di->hdc, &r, di->hbrBar);
183
}
184
185
/* draw solid vertical background from 'start' to 'end' */
186
static void draw_solid_bkg_V (const ProgressDrawInfo* di, int start, int end)
187
{
188
RECT r;
189
SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
190
FillRect (di->hdc, &r, di->hbrBk);
191
}
192
193
/* draw chunky horizontal bar from 'start' to 'end' */
194
static void draw_chunk_bar_H (const ProgressDrawInfo* di, int start, int end)
195
{
196
RECT r;
197
int right = di->rect.left + end;
198
r.left = di->rect.left + start;
199
r.top = di->rect.top;
200
r.bottom = di->rect.bottom;
201
while (r.left < right)
202
{
203
r.right = min (r.left + di->ledW, right);
204
FillRect (di->hdc, &r, di->hbrBar);
205
r.left = r.right;
206
r.right = min (r.left + di->ledGap, right);
207
FillRect (di->hdc, &r, di->hbrBk);
208
r.left = r.right;
209
}
210
}
211
212
/* draw chunky vertical bar from 'start' to 'end' */
213
static void draw_chunk_bar_V (const ProgressDrawInfo* di, int start, int end)
214
{
215
RECT r;
216
int top = di->rect.bottom - end;
217
r.left = di->rect.left;
218
r.right = di->rect.right;
219
r.bottom = di->rect.bottom - start;
220
while (r.bottom > top)
221
{
222
r.top = max (r.bottom - di->ledW, top);
223
FillRect (di->hdc, &r, di->hbrBar);
224
r.bottom = r.top;
225
r.top = max (r.bottom - di->ledGap, top);
226
FillRect (di->hdc, &r, di->hbrBk);
227
r.bottom = r.top;
228
}
229
}
230
231
/* drawing functions for "classic" style */
232
static const ProgressDrawProc drawProcClassic[8] = {
233
/* Smooth */
234
/* Horizontal */
235
draw_solid_bar_H, draw_solid_bkg_H,
236
/* Vertical */
237
draw_solid_bar_V, draw_solid_bkg_V,
238
/* Chunky */
239
/* Horizontal */
240
draw_chunk_bar_H, draw_solid_bkg_H,
241
/* Vertical */
242
draw_chunk_bar_V, draw_solid_bkg_V,
243
};
244
245
#if __WINE_COMCTL32_VERSION == 6
246
/* draw themed horizontal bar from 'start' to 'end' */
247
static void draw_theme_bar_H (const ProgressDrawInfo* di, int start, int end)
248
{
249
HTHEME theme = GetWindowTheme (di->infoPtr->Self);
250
RECT r;
251
r.left = di->rect.left + start;
252
r.top = di->rect.top;
253
r.bottom = di->rect.bottom;
254
r.right = di->rect.left + end;
255
DrawThemeBackground (theme, di->hdc, PP_FILL, di->infoPtr->State, &r, NULL);
256
}
257
258
/* draw themed vertical bar from 'start' to 'end' */
259
static void draw_theme_bar_V (const ProgressDrawInfo* di, int start, int end)
260
{
261
HTHEME theme = GetWindowTheme (di->infoPtr->Self);
262
RECT r;
263
r.left = di->rect.left;
264
r.right = di->rect.right;
265
r.bottom = di->rect.bottom - start;
266
r.top = di->rect.bottom - end;
267
DrawThemeBackground (theme, di->hdc, PP_FILLVERT, di->infoPtr->State, &r, NULL);
268
}
269
270
/* draw themed horizontal background from 'start' to 'end' */
271
static void draw_theme_bkg_H (const ProgressDrawInfo* di, int start, int end)
272
{
273
HTHEME theme = GetWindowTheme (di->infoPtr->Self);
274
RECT bgrect, r;
275
276
SetRect(&r, di->rect.left + start, di->rect.top, di->rect.left + end, di->rect.bottom);
277
GetWindowRect(di->infoPtr->Self, &bgrect);
278
MapWindowPoints(di->infoPtr->Self, 0, (POINT *)&bgrect, 2);
279
OffsetRect(&bgrect, -bgrect.left, -bgrect.top);
280
281
DrawThemeBackground (theme, di->hdc, PP_BAR, 0, &bgrect, &r);
282
}
283
284
/* draw themed vertical background from 'start' to 'end' */
285
static void draw_theme_bkg_V (const ProgressDrawInfo* di, int start, int end)
286
{
287
HTHEME theme = GetWindowTheme (di->infoPtr->Self);
288
RECT bgrect, r;
289
290
SetRect(&r, di->rect.left, di->rect.bottom - end, di->rect.right, di->rect.bottom - start);
291
GetWindowRect(di->infoPtr->Self, &bgrect);
292
MapWindowPoints(di->infoPtr->Self, 0, (POINT *)&bgrect, 2);
293
OffsetRect(&bgrect, -bgrect.left, -bgrect.top);
294
295
DrawThemeBackground (theme, di->hdc, PP_BARVERT, 0, &bgrect, &r);
296
}
297
298
/* drawing functions for themed style */
299
static const ProgressDrawProc drawProcThemed[8] = {
300
/* Smooth */
301
/* Horizontal */
302
draw_theme_bar_H, draw_theme_bkg_H,
303
/* Vertical */
304
draw_theme_bar_V, draw_theme_bkg_V,
305
/* Chunky */
306
/* Horizontal */
307
draw_theme_bar_H, draw_theme_bkg_H,
308
/* Vertical */
309
draw_theme_bar_V, draw_theme_bkg_V,
310
};
311
#endif /* __WINE_COMCTL32_VERSION == 6 */
312
313
static void PROGRESS_DrawBackground (const PROGRESS_INFO *infoPtr, HDC hdc, ProgressDrawInfo *pdi)
314
{
315
#if __WINE_COMCTL32_VERSION == 6
316
HTHEME theme = GetWindowTheme (infoPtr->Self);
317
318
if (theme)
319
{
320
int part = (GetWindowLongW (infoPtr->Self, GWL_STYLE) & PBS_VERTICAL) ? PP_BARVERT : PP_BAR;
321
RECT content_rect;
322
323
GetThemeBackgroundContentRect (theme, hdc, part, 0, &pdi->rect, &content_rect);
324
325
/* Exclude content rect - content background will be drawn later */
326
ExcludeClipRect (hdc, content_rect.left, content_rect.top, content_rect.right, content_rect.bottom);
327
if (IsThemeBackgroundPartiallyTransparent (theme, part, 0))
328
DrawThemeParentBackground (infoPtr->Self, hdc, NULL);
329
DrawThemeBackground (theme, hdc, part, 0, &pdi->rect, NULL);
330
SelectClipRgn (hdc, NULL);
331
pdi->rect = content_rect;
332
return;
333
}
334
#endif
335
336
FrameRect (hdc, &pdi->rect, pdi->hbrBk);
337
InflateRect (&pdi->rect, -1, -1);
338
}
339
340
static BOOL PROGRESS_IsSmooth(HWND hwnd)
341
{
342
#if __WINE_COMCTL32_VERSION == 6
343
if (GetWindowTheme(hwnd))
344
return FALSE;
345
#endif
346
347
return GetWindowLongW(hwnd, GWL_STYLE) & PBS_SMOOTH;
348
}
349
350
static const ProgressDrawProc *PROGRESS_GetDrawProcs(HWND hwnd, BOOL smooth, DWORD style)
351
{
352
int proc_idx = (smooth ? 0 : 4) + ((style & PBS_VERTICAL) ? 2 : 0);
353
354
#if __WINE_COMCTL32_VERSION == 6
355
if (GetWindowTheme(hwnd))
356
return &drawProcThemed[proc_idx];
357
#endif
358
359
return &drawProcClassic[proc_idx];
360
}
361
362
/***********************************************************************
363
* PROGRESS_Draw
364
* Draws the progress bar.
365
*/
366
static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc)
367
{
368
int barSize;
369
DWORD dwStyle;
370
BOOL barSmooth;
371
const ProgressDrawProc* drawProcs;
372
ProgressDrawInfo pdi;
373
374
TRACE("(infoPtr=%p, hdc=%p)\n", infoPtr, hdc);
375
376
pdi.infoPtr = infoPtr;
377
pdi.hdc = hdc;
378
379
/* get the required bar brush */
380
if (infoPtr->ColorBar == CLR_DEFAULT)
381
pdi.hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
382
else
383
pdi.hbrBar = CreateSolidBrush (infoPtr->ColorBar);
384
385
if (infoPtr->ColorBk == CLR_DEFAULT)
386
pdi.hbrBk = GetSysColorBrush(COLOR_3DFACE);
387
else
388
pdi.hbrBk = CreateSolidBrush(infoPtr->ColorBk);
389
390
/* get the window style */
391
dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
392
393
/* get client rectangle */
394
GetClientRect (infoPtr->Self, &pdi.rect);
395
PROGRESS_DrawBackground (infoPtr, hdc, &pdi);
396
397
/* compute some drawing parameters */
398
barSmooth = PROGRESS_IsSmooth(infoPtr->Self);
399
drawProcs = PROGRESS_GetDrawProcs(infoPtr->Self, barSmooth, dwStyle);
400
barSize = get_bar_size( dwStyle, &pdi.rect );
401
402
if (!barSmooth)
403
pdi.ledW = get_led_size( infoPtr, dwStyle, &pdi.rect);
404
pdi.ledGap = get_led_gap( infoPtr );
405
406
if (dwStyle & PBS_MARQUEE)
407
{
408
const int ledW = !barSmooth ? (pdi.ledW + pdi.ledGap) : 1;
409
const int leds = (barSize + ledW - 1) / ledW;
410
const int ledMEnd = infoPtr->MarqueePos + MARQUEE_LEDS;
411
412
if (ledMEnd > leds)
413
{
414
/* case 1: the marquee bar extends over the end and wraps around to
415
* the start */
416
const int gapStart = max((ledMEnd - leds) * ledW, 0);
417
const int gapEnd = min(infoPtr->MarqueePos * ledW, barSize);
418
419
drawProcs[0]( &pdi, 0, gapStart);
420
drawProcs[1]( &pdi, gapStart, gapEnd);
421
drawProcs[0]( &pdi, gapEnd, barSize);
422
}
423
else
424
{
425
/* case 2: the marquee bar is between start and end */
426
const int barStart = infoPtr->MarqueePos * ledW;
427
const int barEnd = min (ledMEnd * ledW, barSize);
428
429
drawProcs[1]( &pdi, 0, barStart);
430
drawProcs[0]( &pdi, barStart, barEnd);
431
drawProcs[1]( &pdi, barEnd, barSize);
432
}
433
}
434
else
435
{
436
int barEnd = get_bar_position( infoPtr, dwStyle, &pdi.rect,
437
infoPtr->CurVal);
438
if (!barSmooth)
439
{
440
const int ledW = pdi.ledW + pdi.ledGap;
441
barEnd = min (((barEnd + ledW - 1) / ledW) * ledW, barSize);
442
}
443
drawProcs[0]( &pdi, 0, barEnd);
444
drawProcs[1]( &pdi, barEnd, barSize);
445
}
446
447
/* delete bar brush */
448
if (infoPtr->ColorBar != CLR_DEFAULT) DeleteObject (pdi.hbrBar);
449
if (infoPtr->ColorBk != CLR_DEFAULT) DeleteObject (pdi.hbrBk);
450
451
return 0;
452
}
453
454
/***********************************************************************
455
* PROGRESS_Paint
456
* Draw the progress bar. The background need not be erased.
457
* If dc!=0, it draws on it
458
*/
459
static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc)
460
{
461
PAINTSTRUCT ps;
462
if (hdc) return PROGRESS_Draw (infoPtr, hdc);
463
hdc = BeginPaint (infoPtr->Self, &ps);
464
PROGRESS_Draw (infoPtr, hdc);
465
EndPaint (infoPtr->Self, &ps);
466
return 0;
467
}
468
469
470
/***********************************************************************
471
* Advance marquee progress by one step.
472
*/
473
static void PROGRESS_UpdateMarquee (PROGRESS_INFO *infoPtr)
474
{
475
LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE);
476
RECT rect;
477
int ledWidth, leds;
478
BOOL smooth = PROGRESS_IsSmooth (infoPtr->Self);
479
480
get_client_rect (infoPtr->Self, &rect);
481
482
if (smooth)
483
ledWidth = 1;
484
else
485
ledWidth = get_led_size( infoPtr, style, &rect ) + get_led_gap( infoPtr );
486
487
leds = (get_bar_size( style, &rect ) + ledWidth - 1) /
488
ledWidth;
489
490
/* increment the marquee progress */
491
if (++infoPtr->MarqueePos >= leds)
492
infoPtr->MarqueePos = 0;
493
494
InvalidateRect(infoPtr->Self, &rect, TRUE);
495
UpdateWindow(infoPtr->Self);
496
}
497
498
499
/***********************************************************************
500
* PROGRESS_CoercePos
501
* Makes sure the current position (CurVal) is within bounds.
502
*/
503
static void PROGRESS_CoercePos(PROGRESS_INFO *infoPtr)
504
{
505
if(infoPtr->CurVal < infoPtr->MinVal)
506
infoPtr->CurVal = infoPtr->MinVal;
507
if(infoPtr->CurVal > infoPtr->MaxVal)
508
infoPtr->CurVal = infoPtr->MaxVal;
509
}
510
511
512
/***********************************************************************
513
* PROGRESS_SetFont
514
* Set new Font for progress bar
515
*/
516
static HFONT PROGRESS_SetFont (PROGRESS_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
517
{
518
HFONT hOldFont = infoPtr->Font;
519
infoPtr->Font = hFont;
520
/* Since infoPtr->Font is not used, there is no need for repaint */
521
return hOldFont;
522
}
523
524
static DWORD PROGRESS_SetRange (PROGRESS_INFO *infoPtr, int low, int high)
525
{
526
DWORD res = MAKELONG(LOWORD(infoPtr->MinVal), LOWORD(infoPtr->MaxVal));
527
528
/* if nothing changes, simply return */
529
if(infoPtr->MinVal == low && infoPtr->MaxVal == high) return res;
530
531
infoPtr->MinVal = low;
532
infoPtr->MaxVal = high;
533
PROGRESS_CoercePos(infoPtr);
534
InvalidateRect(infoPtr->Self, NULL, TRUE);
535
return res;
536
}
537
538
static UINT PROGRESS_SetPos (PROGRESS_INFO *infoPtr, INT pos)
539
{
540
DWORD style = GetWindowLongW(infoPtr->Self, GWL_STYLE);
541
542
if (style & PBS_MARQUEE)
543
{
544
PROGRESS_UpdateMarquee(infoPtr);
545
return 1;
546
}
547
else
548
{
549
UINT oldVal;
550
oldVal = infoPtr->CurVal;
551
if (oldVal != pos) {
552
infoPtr->CurVal = pos;
553
PROGRESS_CoercePos(infoPtr);
554
TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
555
PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
556
UpdateWindow( infoPtr->Self );
557
NotifyWinEvent( EVENT_OBJECT_VALUECHANGE, infoPtr->Self, OBJID_CLIENT, 0 );
558
}
559
return oldVal;
560
}
561
}
562
563
static UINT PROGRESS_SetState (HWND hwnd, PROGRESS_INFO *infoPtr, UINT state)
564
{
565
UINT prev_state = infoPtr->State;
566
567
if (state == PBST_NORMAL || state == PBST_PAUSED || state == PBST_ERROR)
568
infoPtr->State = state;
569
else
570
return 0;
571
572
if (state != prev_state)
573
{
574
NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, 0);
575
576
InvalidateRect(hwnd, NULL, TRUE);
577
}
578
return prev_state;
579
}
580
581
static LRESULT PROGRESS_ThemeChanged(HWND hwnd)
582
{
583
#if __WINE_COMCTL32_VERSION == 6
584
DWORD style = GetWindowLongW(hwnd, GWL_EXSTYLE);
585
586
CloseThemeData(GetWindowTheme(hwnd));
587
OpenThemeData(hwnd, L"Progress");
588
589
/* WS_EX_STATICEDGE disappears when the control is themed */
590
if (COMCTL32_IsThemed(hwnd))
591
style &= ~WS_EX_STATICEDGE;
592
else
593
style |= WS_EX_STATICEDGE;
594
SetWindowLongW(hwnd, GWL_EXSTYLE, style);
595
596
InvalidateRect(hwnd, NULL, TRUE);
597
return 0;
598
#else
599
return DefWindowProcW(hwnd, WM_THEMECHANGED, 0, 0);
600
#endif
601
}
602
603
/***********************************************************************
604
* ProgressWindowProc
605
*/
606
static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
607
WPARAM wParam, LPARAM lParam)
608
{
609
PROGRESS_INFO *infoPtr;
610
611
TRACE("hwnd %p, msg %04x, wparam %Ix, lParam %Ix\n", hwnd, message, wParam, lParam);
612
613
infoPtr = (PROGRESS_INFO *)GetWindowLongPtrW(hwnd, 0);
614
615
if (!infoPtr && message != WM_CREATE)
616
return DefWindowProcW( hwnd, message, wParam, lParam );
617
618
switch(message) {
619
case WM_CREATE:
620
{
621
DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
622
623
COMCTL32_OpenThemeForWindow (hwnd, L"Progress");
624
625
dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
626
if (!COMCTL32_IsThemed (hwnd)) dwExStyle |= WS_EX_STATICEDGE;
627
SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle);
628
/* Force recalculation of a non-client area */
629
SetWindowPos(hwnd, 0, 0, 0, 0, 0,
630
SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
631
632
/* allocate memory for info struct */
633
infoPtr = Alloc(sizeof(*infoPtr));
634
if (!infoPtr) return -1;
635
SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
636
637
/* initialize the info struct */
638
infoPtr->Self = hwnd;
639
infoPtr->MinVal = 0;
640
infoPtr->MaxVal = 100;
641
infoPtr->CurVal = 0;
642
infoPtr->Step = 10;
643
infoPtr->MarqueePos = 0;
644
infoPtr->Marquee = FALSE;
645
infoPtr->ColorBar = CLR_DEFAULT;
646
infoPtr->ColorBk = CLR_DEFAULT;
647
infoPtr->Font = 0;
648
infoPtr->State = PBST_NORMAL;
649
650
TRACE("Progress Ctrl creation, hwnd=%p\n", hwnd);
651
return 0;
652
}
653
654
case WM_DESTROY:
655
TRACE("Progress Ctrl destruction, hwnd=%p\n", hwnd);
656
Free (infoPtr);
657
SetWindowLongPtrW(hwnd, 0, 0);
658
COMCTL32_CloseThemeForWindow (hwnd);
659
return 0;
660
661
case WM_ERASEBKGND:
662
return 1;
663
664
case WM_GETFONT:
665
return (LRESULT)infoPtr->Font;
666
667
case WM_SETFONT:
668
return (LRESULT)PROGRESS_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
669
670
case WM_GETOBJECT:
671
if ((LONG)lParam == OBJID_QUERYCLASSNAMEIDX)
672
return 0x1000d;
673
return DefWindowProcW( hwnd, message, wParam, lParam );
674
675
case WM_PRINTCLIENT:
676
case WM_PAINT:
677
return PROGRESS_Paint (infoPtr, (HDC)wParam);
678
679
case WM_TIMER:
680
if (wParam == ID_MARQUEE_TIMER)
681
PROGRESS_UpdateMarquee (infoPtr);
682
return 0;
683
684
case WM_THEMECHANGED:
685
return PROGRESS_ThemeChanged (hwnd);
686
687
case PBM_DELTAPOS:
688
{
689
INT oldVal;
690
oldVal = infoPtr->CurVal;
691
if(wParam != 0) {
692
infoPtr->CurVal += (INT)wParam;
693
PROGRESS_CoercePos (infoPtr);
694
TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
695
PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
696
UpdateWindow( infoPtr->Self );
697
}
698
return oldVal;
699
}
700
701
case PBM_SETPOS:
702
return PROGRESS_SetPos(infoPtr, wParam);
703
704
case PBM_SETRANGE:
705
return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam));
706
707
case PBM_SETSTEP:
708
{
709
INT oldStep;
710
oldStep = infoPtr->Step;
711
infoPtr->Step = (INT)wParam;
712
return oldStep;
713
}
714
715
case PBM_GETSTEP:
716
return infoPtr->Step;
717
718
case PBM_STEPIT:
719
{
720
int oldVal = infoPtr->CurVal;
721
722
if (infoPtr->MinVal != infoPtr->MaxVal)
723
{
724
infoPtr->CurVal += infoPtr->Step;
725
if (infoPtr->CurVal > infoPtr->MaxVal)
726
infoPtr->CurVal = (infoPtr->CurVal - infoPtr->MinVal) % (infoPtr->MaxVal - infoPtr->MinVal) + infoPtr->MinVal;
727
if (infoPtr->CurVal < infoPtr->MinVal)
728
infoPtr->CurVal = (infoPtr->CurVal - infoPtr->MinVal) % (infoPtr->MaxVal - infoPtr->MinVal) + infoPtr->MaxVal;
729
730
if (oldVal != infoPtr->CurVal)
731
{
732
TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
733
PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
734
UpdateWindow( infoPtr->Self );
735
}
736
}
737
738
return oldVal;
739
}
740
741
case PBM_SETRANGE32:
742
return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam);
743
744
case PBM_GETRANGE:
745
if (lParam) {
746
((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
747
((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
748
}
749
return wParam ? infoPtr->MinVal : infoPtr->MaxVal;
750
751
case PBM_GETPOS:
752
return infoPtr->CurVal;
753
754
case PBM_SETBARCOLOR:
755
{
756
COLORREF clr = infoPtr->ColorBar;
757
758
infoPtr->ColorBar = (COLORREF)lParam;
759
InvalidateRect(hwnd, NULL, TRUE);
760
return clr;
761
}
762
763
case PBM_GETBARCOLOR:
764
return infoPtr->ColorBar;
765
766
case PBM_SETBKCOLOR:
767
{
768
COLORREF clr = infoPtr->ColorBk;
769
770
infoPtr->ColorBk = (COLORREF)lParam;
771
InvalidateRect(hwnd, NULL, TRUE);
772
return clr;
773
}
774
775
case PBM_GETBKCOLOR:
776
return infoPtr->ColorBk;
777
778
case PBM_SETSTATE:
779
return PROGRESS_SetState(hwnd, infoPtr, wParam);
780
781
case PBM_GETSTATE:
782
return infoPtr->State;
783
784
case PBM_SETMARQUEE:
785
if(wParam != 0)
786
{
787
UINT period = lParam ? (UINT)lParam : DEFAULT_MARQUEE_PERIOD;
788
infoPtr->Marquee = TRUE;
789
SetTimer(infoPtr->Self, ID_MARQUEE_TIMER, period, NULL);
790
}
791
else
792
{
793
infoPtr->Marquee = FALSE;
794
KillTimer(infoPtr->Self, ID_MARQUEE_TIMER);
795
}
796
return infoPtr->Marquee;
797
798
default:
799
if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message))
800
ERR("unknown msg %04x, wp %Ix, lp %Ix\n", message, wParam, lParam );
801
return DefWindowProcW( hwnd, message, wParam, lParam );
802
}
803
}
804
805
806
/***********************************************************************
807
* PROGRESS_Register [Internal]
808
*
809
* Registers the progress bar window class.
810
*/
811
void PROGRESS_Register (void)
812
{
813
WNDCLASSW wndClass;
814
815
ZeroMemory (&wndClass, sizeof(wndClass));
816
wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
817
wndClass.lpfnWndProc = ProgressWindowProc;
818
wndClass.cbClsExtra = 0;
819
wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
820
wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
821
wndClass.lpszClassName = PROGRESS_CLASSW;
822
823
RegisterClassW (&wndClass);
824
}
825
826
827
/***********************************************************************
828
* PROGRESS_Unregister [Internal]
829
*
830
* Unregisters the progress bar window class.
831
*/
832
void PROGRESS_Unregister (void)
833
{
834
UnregisterClassW (PROGRESS_CLASSW, NULL);
835
}
836
837