Changed some treeview related definitions.
[wine] / dlls / comctl32 / progress.c
1 /*              
2  * Progress control
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  *
6  */
7
8 #include "windows.h"
9 #include "commctrl.h"
10 #include "progress.h"
11 #include "win.h"
12 #include "debug.h"
13
14
15 /* Control configuration constants */
16
17 #define LED_GAP    2
18
19 /* Work constants */
20
21 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(progress, \
22         "Unknown parameter(s) for message " #msg     \
23         "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam); 
24
25 #define PROGRESS_GetInfoPtr(wndPtr) ((PROGRESS_INFO *)wndPtr->wExtra[0])
26
27
28 /***********************************************************************
29  * PROGRESS_Draw
30  * Draws the progress bar.
31  */
32 static void
33 PROGRESS_Draw (WND *wndPtr, HDC32 hdc)
34 {
35   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
36   HBRUSH32 hbrBar, hbrBk;
37   int rightBar, rightMost, ledWidth;
38   RECT32 rect;
39
40   TRACE(progress, "refresh pos=%d min=%d, max=%d\n",
41                infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
42
43   /* get the required bar brush */
44   if (infoPtr->ColorBar == CLR_DEFAULT)
45     hbrBar = GetSysColorBrush32(COLOR_HIGHLIGHT);
46   else
47     hbrBar = CreateSolidBrush32 (infoPtr->ColorBar);
48
49   /* get the required background brush */
50   if (infoPtr->ColorBk == CLR_DEFAULT)
51     hbrBk = GetSysColorBrush32 (COLOR_3DFACE);
52   else
53     hbrBk = CreateSolidBrush32 (infoPtr->ColorBk);
54
55   /* get client rectangle */
56   GetClientRect32 (wndPtr->hwndSelf, &rect);
57
58   /* draw the background */
59   FillRect32(hdc, &rect, hbrBk);
60
61   rect.left++; rect.right--; rect.top++; rect.bottom--;
62
63   /* compute extent of progress bar */
64   if (wndPtr->dwStyle & PBS_VERTICAL)
65   {
66     rightBar = rect.bottom - 
67       MulDiv32(infoPtr->CurVal-infoPtr->MinVal,
68                rect.bottom - rect.top,
69                infoPtr->MaxVal-infoPtr->MinVal);
70     ledWidth = MulDiv32 ((rect.right - rect.left), 2, 3);
71     rightMost = rect.top;
72   }
73   else
74   {
75     rightBar = rect.left + 
76       MulDiv32(infoPtr->CurVal-infoPtr->MinVal,
77                rect.right - rect.left,
78                infoPtr->MaxVal-infoPtr->MinVal);
79     ledWidth = MulDiv32 ((rect.bottom - rect.top), 2, 3);
80     rightMost = rect.right;
81   }
82
83   /* now draw the bar */
84   if (wndPtr->dwStyle & PBS_SMOOTH)
85   {
86     if (wndPtr->dwStyle & PBS_VERTICAL)
87       rect.top = rightBar;
88     else
89       rect.right = rightBar;
90     FillRect32(hdc, &rect, hbrBar);
91   }
92   else
93   {
94     if (wndPtr->dwStyle & PBS_VERTICAL)
95       while(rect.bottom > rightBar) { 
96         rect.top = rect.bottom-ledWidth;
97         if (rect.top < rightMost)
98           rect.top = rightMost;
99         FillRect32(hdc, &rect, hbrBar);
100         rect.bottom = rect.top-LED_GAP;
101       }
102     else
103       while(rect.left < rightBar) { 
104         rect.right = rect.left+ledWidth;
105         if (rect.right > rightMost)
106           rect.right = rightMost;
107         FillRect32(hdc, &rect, hbrBar);
108         rect.left  = rect.right+LED_GAP;
109       }
110   }
111
112   /* delete bar brush */
113   if (infoPtr->ColorBar != CLR_DEFAULT)
114       DeleteObject32 (hbrBar);
115
116   /* delete background brush */
117   if (infoPtr->ColorBk != CLR_DEFAULT)
118       DeleteObject32 (hbrBk);
119 }
120
121 /***********************************************************************
122  * PROGRESS_Refresh
123  * Draw the progress bar. The background need not be erased.
124  */
125 static void
126 PROGRESS_Refresh (WND *wndPtr)
127 {
128     HDC32 hdc;
129
130     hdc = GetDC32 (wndPtr->hwndSelf);
131     PROGRESS_Draw (wndPtr, hdc);
132     ReleaseDC32 (wndPtr->hwndSelf, hdc);
133 }
134
135 /***********************************************************************
136  * PROGRESS_Paint
137  * Draw the progress bar. The background need not be erased.
138  * If dc!=0, it draws on it
139  */
140 static void
141 PROGRESS_Paint (WND *wndPtr)
142 {
143     PAINTSTRUCT32 ps;
144     HDC32 hdc;
145
146     hdc = BeginPaint32 (wndPtr->hwndSelf, &ps);
147     PROGRESS_Draw (wndPtr, hdc);
148     EndPaint32 (wndPtr->hwndSelf, &ps);
149 }
150
151
152 /***********************************************************************
153  *           PROGRESS_CoercePos
154  * Makes sure the current position (CUrVal) is within bounds.
155  */
156 static void PROGRESS_CoercePos(WND *wndPtr)
157 {
158   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
159
160   if(infoPtr->CurVal < infoPtr->MinVal)
161     infoPtr->CurVal = infoPtr->MinVal;
162   if(infoPtr->CurVal > infoPtr->MaxVal)
163     infoPtr->CurVal = infoPtr->MaxVal;
164 }
165
166
167 /***********************************************************************
168  *           PROGRESS_SetFont
169  * Set new Font for progress bar
170  */
171 static HFONT32
172 PROGRESS_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
173 {
174   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
175   HFONT32 hOldFont = infoPtr->hFont;
176
177   infoPtr->hFont = (HFONT32)wParam;
178   if (LOWORD(lParam))
179     PROGRESS_Refresh (wndPtr);
180   return hOldFont;
181 }
182
183
184 /***********************************************************************
185  *           ProgressWindowProc
186  */
187 LRESULT WINAPI ProgressWindowProc(HWND32 hwnd, UINT32 message, 
188                                   WPARAM32 wParam, LPARAM lParam)
189 {
190   WND *wndPtr = WIN_FindWndPtr(hwnd);
191   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
192   UINT32 temp;
193
194   switch(message)
195     {
196     case WM_NCCREATE:
197       wndPtr->dwExStyle |= WS_EX_STATICEDGE;
198       return TRUE;
199
200     case WM_CREATE:
201       /* allocate memory for info struct */
202       infoPtr = 
203         (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
204       wndPtr->wExtra[0] = (DWORD)infoPtr;
205
206       /* initialize the info struct */
207       infoPtr->MinVal=0; 
208       infoPtr->MaxVal=100;
209       infoPtr->CurVal=0; 
210       infoPtr->Step=10;
211       infoPtr->ColorBar=CLR_DEFAULT;
212       infoPtr->ColorBk=CLR_DEFAULT;
213       infoPtr->hFont=(HANDLE32)NULL;
214       TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
215       break;
216     
217     case WM_DESTROY:
218       TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
219       COMCTL32_Free (infoPtr);
220       break;
221
222     case WM_ERASEBKGND:
223       /* pretend to erase it here, but we will do it in the paint
224          function to avoid flicker */
225       return 1;
226         
227     case WM_GETFONT:
228       return (LRESULT)infoPtr->hFont;
229
230     case WM_SETFONT:
231       return PROGRESS_SetFont (wndPtr, wParam, lParam);
232 /*      break; */
233
234     case WM_PAINT:
235       PROGRESS_Paint (wndPtr);
236       break;
237     
238     case PBM_DELTAPOS:
239       if(lParam)
240         UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
241       temp = infoPtr->CurVal;
242       if(wParam != 0){
243         infoPtr->CurVal += (UINT16)wParam;
244         PROGRESS_CoercePos(wndPtr);
245         PROGRESS_Refresh (wndPtr);
246       }
247       return temp;
248
249     case PBM_SETPOS:
250       if (lParam)
251         UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
252       temp = infoPtr->CurVal;
253       if(temp != wParam){
254         infoPtr->CurVal = (UINT16)wParam;
255         PROGRESS_CoercePos(wndPtr);
256         PROGRESS_Refresh (wndPtr);
257       }
258       return temp;          
259       
260     case PBM_SETRANGE:
261       if (wParam)
262         UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
263       temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
264       if(temp != lParam){
265         infoPtr->MinVal = LOWORD(lParam); 
266         infoPtr->MaxVal = HIWORD(lParam);
267         if(infoPtr->MaxVal <= infoPtr->MinVal)
268           infoPtr->MaxVal = infoPtr->MinVal+1;
269         PROGRESS_CoercePos(wndPtr);
270         PROGRESS_Refresh (wndPtr);
271       }
272       return temp;
273
274     case PBM_SETSTEP:
275       if (lParam)
276         UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
277       temp = infoPtr->Step;   
278       infoPtr->Step = (UINT16)wParam;   
279       return temp;
280
281     case PBM_STEPIT:
282       if (wParam || lParam)
283         UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
284       temp = infoPtr->CurVal;   
285       infoPtr->CurVal += infoPtr->Step;
286       if(infoPtr->CurVal > infoPtr->MaxVal)
287         infoPtr->CurVal = infoPtr->MinVal;
288       if(temp != infoPtr->CurVal)
289         PROGRESS_Refresh (wndPtr);
290       return temp;
291
292     case PBM_SETRANGE32:
293       temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
294       if((infoPtr->MinVal != (INT32)wParam) ||
295          (infoPtr->MaxVal != (INT32)lParam)) {
296         infoPtr->MinVal = (INT32)wParam;
297         infoPtr->MaxVal = (INT32)lParam;
298         if(infoPtr->MaxVal <= infoPtr->MinVal)
299           infoPtr->MaxVal = infoPtr->MinVal+1;
300         PROGRESS_CoercePos(wndPtr);
301         PROGRESS_Refresh (wndPtr);
302       }
303       return temp;
304     
305     case PBM_GETRANGE:
306       if (lParam){
307         ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
308         ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
309       }
310       return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
311
312     case PBM_GETPOS:
313       if (wParam || lParam)
314         UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
315       return (infoPtr->CurVal);
316
317     case PBM_SETBARCOLOR:
318       if (wParam)
319         UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
320       infoPtr->ColorBar = (COLORREF)lParam;     
321       PROGRESS_Refresh (wndPtr);
322       break;
323
324     case PBM_SETBKCOLOR:
325       if (wParam)
326         UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
327       infoPtr->ColorBk = (COLORREF)lParam;
328       PROGRESS_Refresh (wndPtr);
329       break;
330
331     default: 
332       if (message >= WM_USER) 
333         ERR(progress, "unknown msg %04x wp=%04x lp=%08lx\n", 
334                     message, wParam, lParam );
335       return DefWindowProc32A( hwnd, message, wParam, lParam ); 
336     } 
337
338     return 0;
339 }
340
341
342 /***********************************************************************
343  * PROGRESS_Register [Internal]
344  *
345  * Registers the progress bar window class.
346  */
347
348 VOID
349 PROGRESS_Register (VOID)
350 {
351     WNDCLASS32A wndClass;
352
353     if (GlobalFindAtom32A (PROGRESS_CLASS32A)) return;
354
355     ZeroMemory (&wndClass, sizeof( WNDCLASS32A));
356     wndClass.style         = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
357     wndClass.lpfnWndProc   = (WNDPROC32)ProgressWindowProc;
358     wndClass.cbClsExtra    = 0;
359     wndClass.cbWndExtra    = sizeof (PROGRESS_INFO *);
360     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
361     wndClass.lpszClassName = PROGRESS_CLASS32A;
362
363     RegisterClass32A (&wndClass);
364 }
365
366
367 /***********************************************************************
368  * PROGRESS_Unregister [Internal]
369  *
370  * Unregisters the progress bar window class.
371  */
372
373 VOID
374 PROGRESS_Unregister (VOID)
375 {
376     if (GlobalFindAtom32A (PROGRESS_CLASS32A))
377         UnregisterClass32A (PROGRESS_CLASS32A, (HINSTANCE32)NULL);
378 }
379