Large-scale renaming of all Win32 functions and types to use the
[wine.git] / dlls / comctl32 / progress.c
blob5559d9620d4c15db1fdb5ceb688ed850b38e74ad
1 /*
2 * Progress control
4 * Copyright 1997 Dimitrie O. Paun
6 */
8 #include "commctrl.h"
9 #include "progress.h"
10 #include "win.h"
11 #include "debug.h"
14 /* Control configuration constants */
16 #define LED_GAP 2
18 /* Work constants */
20 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(progress, \
21 "Unknown parameter(s) for message " #msg \
22 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
24 #define PROGRESS_GetInfoPtr(wndPtr) ((PROGRESS_INFO *)wndPtr->wExtra[0])
27 /***********************************************************************
28 * PROGRESS_Draw
29 * Draws the progress bar.
31 static void
32 PROGRESS_Draw (WND *wndPtr, HDC hdc)
34 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
35 HBRUSH hbrBar, hbrBk;
36 int rightBar, rightMost, ledWidth;
37 RECT rect;
39 TRACE(progress, "refresh pos=%d min=%d, max=%d\n",
40 infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
42 /* get the required bar brush */
43 if (infoPtr->ColorBar == CLR_DEFAULT)
44 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
45 else
46 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
48 /* get the required background brush */
49 if (infoPtr->ColorBk == CLR_DEFAULT)
50 hbrBk = GetSysColorBrush (COLOR_3DFACE);
51 else
52 hbrBk = CreateSolidBrush (infoPtr->ColorBk);
54 /* get client rectangle */
55 GetClientRect (wndPtr->hwndSelf, &rect);
57 /* draw the background */
58 FillRect(hdc, &rect, hbrBk);
60 rect.left++; rect.right--; rect.top++; rect.bottom--;
62 /* compute extent of progress bar */
63 if (wndPtr->dwStyle & PBS_VERTICAL)
65 rightBar = rect.bottom -
66 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
67 rect.bottom - rect.top,
68 infoPtr->MaxVal-infoPtr->MinVal);
69 ledWidth = MulDiv ((rect.right - rect.left), 2, 3);
70 rightMost = rect.top;
72 else
74 rightBar = rect.left +
75 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
76 rect.right - rect.left,
77 infoPtr->MaxVal-infoPtr->MinVal);
78 ledWidth = MulDiv ((rect.bottom - rect.top), 2, 3);
79 rightMost = rect.right;
82 /* now draw the bar */
83 if (wndPtr->dwStyle & PBS_SMOOTH)
85 if (wndPtr->dwStyle & PBS_VERTICAL)
86 rect.top = rightBar;
87 else
88 rect.right = rightBar;
89 FillRect(hdc, &rect, hbrBar);
91 else
93 if (wndPtr->dwStyle & PBS_VERTICAL)
94 while(rect.bottom > rightBar) {
95 rect.top = rect.bottom-ledWidth;
96 if (rect.top < rightMost)
97 rect.top = rightMost;
98 FillRect(hdc, &rect, hbrBar);
99 rect.bottom = rect.top-LED_GAP;
101 else
102 while(rect.left < rightBar) {
103 rect.right = rect.left+ledWidth;
104 if (rect.right > rightMost)
105 rect.right = rightMost;
106 FillRect(hdc, &rect, hbrBar);
107 rect.left = rect.right+LED_GAP;
111 /* delete bar brush */
112 if (infoPtr->ColorBar != CLR_DEFAULT)
113 DeleteObject (hbrBar);
115 /* delete background brush */
116 if (infoPtr->ColorBk != CLR_DEFAULT)
117 DeleteObject (hbrBk);
120 /***********************************************************************
121 * PROGRESS_Refresh
122 * Draw the progress bar. The background need not be erased.
124 static void
125 PROGRESS_Refresh (WND *wndPtr)
127 HDC hdc;
129 hdc = GetDC (wndPtr->hwndSelf);
130 PROGRESS_Draw (wndPtr, hdc);
131 ReleaseDC (wndPtr->hwndSelf, hdc);
134 /***********************************************************************
135 * PROGRESS_Paint
136 * Draw the progress bar. The background need not be erased.
137 * If dc!=0, it draws on it
139 static void
140 PROGRESS_Paint (WND *wndPtr)
142 PAINTSTRUCT ps;
143 HDC hdc;
145 hdc = BeginPaint (wndPtr->hwndSelf, &ps);
146 PROGRESS_Draw (wndPtr, hdc);
147 EndPaint (wndPtr->hwndSelf, &ps);
151 /***********************************************************************
152 * PROGRESS_CoercePos
153 * Makes sure the current position (CUrVal) is within bounds.
155 static void PROGRESS_CoercePos(WND *wndPtr)
157 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
159 if(infoPtr->CurVal < infoPtr->MinVal)
160 infoPtr->CurVal = infoPtr->MinVal;
161 if(infoPtr->CurVal > infoPtr->MaxVal)
162 infoPtr->CurVal = infoPtr->MaxVal;
166 /***********************************************************************
167 * PROGRESS_SetFont
168 * Set new Font for progress bar
170 static HFONT
171 PROGRESS_SetFont (WND *wndPtr, WPARAM wParam, LPARAM lParam)
173 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
174 HFONT hOldFont = infoPtr->hFont;
176 infoPtr->hFont = (HFONT)wParam;
177 if (LOWORD(lParam))
178 PROGRESS_Refresh (wndPtr);
179 return hOldFont;
183 /***********************************************************************
184 * ProgressWindowProc
186 LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
187 WPARAM wParam, LPARAM lParam)
189 WND *wndPtr = WIN_FindWndPtr(hwnd);
190 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
191 UINT temp;
193 switch(message)
195 case WM_NCCREATE:
196 wndPtr->dwExStyle |= WS_EX_STATICEDGE;
197 return TRUE;
199 case WM_CREATE:
200 /* allocate memory for info struct */
201 infoPtr =
202 (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
203 wndPtr->wExtra[0] = (DWORD)infoPtr;
205 /* initialize the info struct */
206 infoPtr->MinVal=0;
207 infoPtr->MaxVal=100;
208 infoPtr->CurVal=0;
209 infoPtr->Step=10;
210 infoPtr->ColorBar=CLR_DEFAULT;
211 infoPtr->ColorBk=CLR_DEFAULT;
212 infoPtr->hFont=(HANDLE)NULL;
213 TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
214 break;
216 case WM_DESTROY:
217 TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
218 COMCTL32_Free (infoPtr);
219 break;
221 case WM_ERASEBKGND:
222 /* pretend to erase it here, but we will do it in the paint
223 function to avoid flicker */
224 return 1;
226 case WM_GETFONT:
227 return (LRESULT)infoPtr->hFont;
229 case WM_SETFONT:
230 return PROGRESS_SetFont (wndPtr, wParam, lParam);
231 /* break; */
233 case WM_PAINT:
234 PROGRESS_Paint (wndPtr);
235 break;
237 case PBM_DELTAPOS:
238 if(lParam)
239 UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
240 temp = infoPtr->CurVal;
241 if(wParam != 0){
242 infoPtr->CurVal += (UINT16)wParam;
243 PROGRESS_CoercePos(wndPtr);
244 PROGRESS_Refresh (wndPtr);
246 return temp;
248 case PBM_SETPOS:
249 if (lParam)
250 UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
251 temp = infoPtr->CurVal;
252 if(temp != wParam){
253 infoPtr->CurVal = (UINT16)wParam;
254 PROGRESS_CoercePos(wndPtr);
255 PROGRESS_Refresh (wndPtr);
257 return temp;
259 case PBM_SETRANGE16:
260 if (wParam)
261 UNKNOWN_PARAM(PBM_SETRANGE16, wParam, lParam);
262 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
263 if(temp != lParam){
264 infoPtr->MinVal = LOWORD(lParam);
265 infoPtr->MaxVal = HIWORD(lParam);
266 if(infoPtr->MaxVal <= infoPtr->MinVal)
267 infoPtr->MaxVal = infoPtr->MinVal+1;
268 PROGRESS_CoercePos(wndPtr);
269 PROGRESS_Refresh (wndPtr);
271 return temp;
273 case PBM_SETSTEP:
274 if (lParam)
275 UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
276 temp = infoPtr->Step;
277 infoPtr->Step = (UINT16)wParam;
278 return temp;
280 case PBM_STEPIT:
281 if (wParam || lParam)
282 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
283 temp = infoPtr->CurVal;
284 infoPtr->CurVal += infoPtr->Step;
285 if(infoPtr->CurVal > infoPtr->MaxVal)
286 infoPtr->CurVal = infoPtr->MinVal;
287 if(temp != infoPtr->CurVal)
288 PROGRESS_Refresh (wndPtr);
289 return temp;
291 case PBM_SETRANGE:
292 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
293 if((infoPtr->MinVal != (INT)wParam) ||
294 (infoPtr->MaxVal != (INT)lParam)) {
295 infoPtr->MinVal = (INT)wParam;
296 infoPtr->MaxVal = (INT)lParam;
297 if(infoPtr->MaxVal <= infoPtr->MinVal)
298 infoPtr->MaxVal = infoPtr->MinVal+1;
299 PROGRESS_CoercePos(wndPtr);
300 PROGRESS_Refresh (wndPtr);
302 return temp;
304 case PBM_GETRANGE:
305 if (lParam){
306 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
307 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
309 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
311 case PBM_GETPOS:
312 if (wParam || lParam)
313 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
314 return (infoPtr->CurVal);
316 case PBM_SETBARCOLOR:
317 if (wParam)
318 UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
319 infoPtr->ColorBar = (COLORREF)lParam;
320 PROGRESS_Refresh (wndPtr);
321 break;
323 case PBM_SETBKCOLOR:
324 if (wParam)
325 UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
326 infoPtr->ColorBk = (COLORREF)lParam;
327 PROGRESS_Refresh (wndPtr);
328 break;
330 default:
331 if (message >= WM_USER)
332 ERR(progress, "unknown msg %04x wp=%04x lp=%08lx\n",
333 message, wParam, lParam );
334 return DefWindowProcA( hwnd, message, wParam, lParam );
337 return 0;
341 /***********************************************************************
342 * PROGRESS_Register [Internal]
344 * Registers the progress bar window class.
347 VOID
348 PROGRESS_Register (VOID)
350 WNDCLASSA wndClass;
352 if (GlobalFindAtomA (PROGRESS_CLASSA)) return;
354 ZeroMemory (&wndClass, sizeof( WNDCLASSA));
355 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
356 wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc;
357 wndClass.cbClsExtra = 0;
358 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
359 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
360 wndClass.lpszClassName = PROGRESS_CLASSA;
362 RegisterClassA (&wndClass);
366 /***********************************************************************
367 * PROGRESS_Unregister [Internal]
369 * Unregisters the progress bar window class.
372 VOID
373 PROGRESS_Unregister (VOID)
375 if (GlobalFindAtomA (PROGRESS_CLASSA))
376 UnregisterClassA (PROGRESS_CLASSA, (HINSTANCE)NULL);