Fixed a silly VGA-emulation palette bug.
[wine/multimedia.git] / dlls / comctl32 / progress.c
bloba7a3fc7968af448ae3c4f2834ff0b9f0e2956db8
1 /*
2 * Progress control
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998, 1999 Eric Kohl
7 */
9 #include "commctrl.h"
10 #include "progress.h"
11 #include "win.h"
12 #include "debug.h"
15 /* Control configuration constants */
17 #define LED_GAP 2
19 /* Work constants */
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);
25 #define PROGRESS_GetInfoPtr(hwnd) ((PROGRESS_INFO *)GetWindowLongA(hwnd, 0))
28 /***********************************************************************
29 * PROGRESS_Draw
30 * Draws the progress bar.
32 static void
33 PROGRESS_Draw (HWND hwnd, HDC hdc)
35 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
36 HBRUSH hbrBar, hbrBk;
37 int rightBar, rightMost, ledWidth;
38 RECT rect;
39 DWORD dwStyle;
41 TRACE(progress, "refresh pos=%d min=%d, max=%d\n",
42 infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
44 /* get the required bar brush */
45 if (infoPtr->ColorBar == CLR_DEFAULT)
46 hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT);
47 else
48 hbrBar = CreateSolidBrush (infoPtr->ColorBar);
50 /* get the required background brush */
51 if (infoPtr->ColorBk == CLR_DEFAULT)
52 hbrBk = GetSysColorBrush (COLOR_3DFACE);
53 else
54 hbrBk = CreateSolidBrush (infoPtr->ColorBk);
56 /* get client rectangle */
57 GetClientRect (hwnd, &rect);
59 /* draw the background */
60 FillRect(hdc, &rect, hbrBk);
62 rect.left++; rect.right--; rect.top++; rect.bottom--;
64 /* get the window style */
65 dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
67 /* compute extent of progress bar */
68 if (dwStyle & PBS_VERTICAL)
70 rightBar = rect.bottom -
71 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
72 rect.bottom - rect.top,
73 infoPtr->MaxVal-infoPtr->MinVal);
74 ledWidth = MulDiv ((rect.right - rect.left), 2, 3);
75 rightMost = rect.top;
77 else
79 rightBar = rect.left +
80 MulDiv(infoPtr->CurVal-infoPtr->MinVal,
81 rect.right - rect.left,
82 infoPtr->MaxVal-infoPtr->MinVal);
83 ledWidth = MulDiv ((rect.bottom - rect.top), 2, 3);
84 rightMost = rect.right;
87 /* now draw the bar */
88 if (dwStyle & PBS_SMOOTH)
90 if (dwStyle & PBS_VERTICAL)
91 rect.top = rightBar;
92 else
93 rect.right = rightBar;
94 FillRect(hdc, &rect, hbrBar);
96 else
98 if (dwStyle & PBS_VERTICAL)
100 while(rect.bottom > rightBar) {
101 rect.top = rect.bottom-ledWidth;
102 if (rect.top < rightMost)
103 rect.top = rightMost;
104 FillRect(hdc, &rect, hbrBar);
105 rect.bottom = rect.top-LED_GAP;
108 else {
109 while(rect.left < rightBar) {
110 rect.right = rect.left+ledWidth;
111 if (rect.right > rightMost)
112 rect.right = rightMost;
113 FillRect(hdc, &rect, hbrBar);
114 rect.left = rect.right+LED_GAP;
119 /* delete bar brush */
120 if (infoPtr->ColorBar != CLR_DEFAULT)
121 DeleteObject (hbrBar);
123 /* delete background brush */
124 if (infoPtr->ColorBk != CLR_DEFAULT)
125 DeleteObject (hbrBk);
128 /***********************************************************************
129 * PROGRESS_Refresh
130 * Draw the progress bar. The background need not be erased.
132 static void
133 PROGRESS_Refresh (HWND hwnd)
135 HDC hdc;
137 hdc = GetDC (hwnd);
138 PROGRESS_Draw (hwnd, hdc);
139 ReleaseDC (hwnd, hdc);
142 /***********************************************************************
143 * PROGRESS_Paint
144 * Draw the progress bar. The background need not be erased.
145 * If dc!=0, it draws on it
147 static void
148 PROGRESS_Paint (HWND hwnd)
150 PAINTSTRUCT ps;
151 HDC hdc;
153 hdc = BeginPaint (hwnd, &ps);
154 PROGRESS_Draw (hwnd, hdc);
155 EndPaint (hwnd, &ps);
159 /***********************************************************************
160 * PROGRESS_CoercePos
161 * Makes sure the current position (CUrVal) is within bounds.
163 static void PROGRESS_CoercePos(HWND hwnd)
165 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
167 if(infoPtr->CurVal < infoPtr->MinVal)
168 infoPtr->CurVal = infoPtr->MinVal;
169 if(infoPtr->CurVal > infoPtr->MaxVal)
170 infoPtr->CurVal = infoPtr->MaxVal;
174 /***********************************************************************
175 * PROGRESS_SetFont
176 * Set new Font for progress bar
178 static HFONT
179 PROGRESS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
181 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
182 HFONT hOldFont = infoPtr->hFont;
184 infoPtr->hFont = (HFONT)wParam;
185 if (LOWORD(lParam))
186 PROGRESS_Refresh (hwnd);
187 return hOldFont;
191 /***********************************************************************
192 * ProgressWindowProc
194 LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message,
195 WPARAM wParam, LPARAM lParam)
197 PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(hwnd);
198 UINT temp;
200 switch(message)
202 case WM_NCCREATE:
204 DWORD dwExStyle;
205 dwExStyle = GetWindowLongA (hwnd, GWL_EXSTYLE);
206 SetWindowLongA (hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_STATICEDGE);
208 return TRUE;
210 case WM_CREATE:
211 /* allocate memory for info struct */
212 infoPtr =
213 (PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
214 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
216 /* initialize the info struct */
217 infoPtr->MinVal=0;
218 infoPtr->MaxVal=100;
219 infoPtr->CurVal=0;
220 infoPtr->Step=10;
221 infoPtr->ColorBar=CLR_DEFAULT;
222 infoPtr->ColorBk=CLR_DEFAULT;
223 infoPtr->hFont=(HANDLE)NULL;
224 TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
225 break;
227 case WM_DESTROY:
228 TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
229 COMCTL32_Free (infoPtr);
230 break;
232 case WM_ERASEBKGND:
233 /* pretend to erase it here, but we will do it in the paint
234 function to avoid flicker */
235 return 1;
237 case WM_GETFONT:
238 return (LRESULT)infoPtr->hFont;
240 case WM_SETFONT:
241 return PROGRESS_SetFont (hwnd, wParam, lParam);
243 case WM_PAINT:
244 PROGRESS_Paint (hwnd);
245 break;
247 case PBM_DELTAPOS:
248 if(lParam)
249 UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
250 temp = infoPtr->CurVal;
251 if(wParam != 0){
252 infoPtr->CurVal += (UINT16)wParam;
253 PROGRESS_CoercePos (hwnd);
254 PROGRESS_Refresh (hwnd);
256 return temp;
258 case PBM_SETPOS:
259 if (lParam)
260 UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
261 temp = infoPtr->CurVal;
262 if(temp != wParam){
263 infoPtr->CurVal = (UINT16)wParam;
264 PROGRESS_CoercePos(hwnd);
265 PROGRESS_Refresh (hwnd);
267 return temp;
269 case PBM_SETRANGE:
270 if (wParam)
271 UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
272 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
273 if(temp != lParam){
274 infoPtr->MinVal = LOWORD(lParam);
275 infoPtr->MaxVal = HIWORD(lParam);
276 if(infoPtr->MaxVal <= infoPtr->MinVal)
277 infoPtr->MaxVal = infoPtr->MinVal+1;
278 PROGRESS_CoercePos(hwnd);
279 PROGRESS_Refresh (hwnd);
281 return temp;
283 case PBM_SETSTEP:
284 if (lParam)
285 UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
286 temp = infoPtr->Step;
287 infoPtr->Step = (UINT16)wParam;
288 return temp;
290 case PBM_STEPIT:
291 if (wParam || lParam)
292 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
293 temp = infoPtr->CurVal;
294 infoPtr->CurVal += infoPtr->Step;
295 if(infoPtr->CurVal > infoPtr->MaxVal)
296 infoPtr->CurVal = infoPtr->MinVal;
297 if(temp != infoPtr->CurVal)
298 PROGRESS_Refresh (hwnd);
299 return temp;
301 case PBM_SETRANGE32:
302 temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
303 if((infoPtr->MinVal != (INT)wParam) ||
304 (infoPtr->MaxVal != (INT)lParam)) {
305 infoPtr->MinVal = (INT)wParam;
306 infoPtr->MaxVal = (INT)lParam;
307 if(infoPtr->MaxVal <= infoPtr->MinVal)
308 infoPtr->MaxVal = infoPtr->MinVal+1;
309 PROGRESS_CoercePos(hwnd);
310 PROGRESS_Refresh (hwnd);
312 return temp;
314 case PBM_GETRANGE:
315 if (lParam){
316 ((PPBRANGE)lParam)->iLow = infoPtr->MinVal;
317 ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal;
319 return (wParam) ? infoPtr->MinVal : infoPtr->MaxVal;
321 case PBM_GETPOS:
322 if (wParam || lParam)
323 UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
324 return (infoPtr->CurVal);
326 case PBM_SETBARCOLOR:
327 if (wParam)
328 UNKNOWN_PARAM(PBM_SETBARCOLOR, wParam, lParam);
329 infoPtr->ColorBar = (COLORREF)lParam;
330 PROGRESS_Refresh (hwnd);
331 break;
333 case PBM_SETBKCOLOR:
334 if (wParam)
335 UNKNOWN_PARAM(PBM_SETBKCOLOR, wParam, lParam);
336 infoPtr->ColorBk = (COLORREF)lParam;
337 PROGRESS_Refresh (hwnd);
338 break;
340 default:
341 if (message >= WM_USER)
342 ERR(progress, "unknown msg %04x wp=%04x lp=%08lx\n",
343 message, wParam, lParam );
344 return DefWindowProcA( hwnd, message, wParam, lParam );
347 return 0;
351 /***********************************************************************
352 * PROGRESS_Register [Internal]
354 * Registers the progress bar window class.
357 VOID
358 PROGRESS_Register (VOID)
360 WNDCLASSA wndClass;
362 if (GlobalFindAtomA (PROGRESS_CLASSA)) return;
364 ZeroMemory (&wndClass, sizeof( WNDCLASSA));
365 wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
366 wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc;
367 wndClass.cbClsExtra = 0;
368 wndClass.cbWndExtra = sizeof (PROGRESS_INFO *);
369 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
370 wndClass.lpszClassName = PROGRESS_CLASSA;
372 RegisterClassA (&wndClass);
376 /***********************************************************************
377 * PROGRESS_Unregister [Internal]
379 * Unregisters the progress bar window class.
382 VOID
383 PROGRESS_Unregister (VOID)
385 if (GlobalFindAtomA (PROGRESS_CLASSA))
386 UnregisterClassA (PROGRESS_CLASSA, (HINSTANCE)NULL);