Release 971130
[wine] / controls / progress.c
1 /*              
2  * Progress control
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  *
6  * TODO:
7  *   - I do not know what to to on WM_[SG]ET_FONT
8  * Problems:
9  *   - I think I do not compute correctly the numer of leds to be drawn
10  */
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include "windows.h"
15 #include "syscolor.h"
16 #include "sysmetrics.h"
17 #include "progress.h"
18 #include "graphics.h"
19 #include "heap.h"
20 #include "win.h"
21 #include "stddebug.h"
22 #include "debug.h"
23
24 /* Control configuration constants */
25
26 #define LED_WIDTH  8
27 #define LED_GAP    2
28
29 /* Work constants */
30
31 #define UNKNOWN_PARAM(msg, wParam, lParam) dprintf_progress(stddeb, \
32         "Progress Ctrl: Unknown parameter(s) for message " #msg     \
33         "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam); 
34
35 #define PROGRESS_GetInfoPtr(wndPtr) ((PROGRESS_INFO *)wndPtr->wExtra)
36
37
38 /***********************************************************************
39  *           PROGRESS_Paint
40  * Draw the arrows. The background need not be erased.
41  * If dc!=0, it draws on it
42  */
43 static void PROGRESS_Paint(WND *wndPtr, HDC32 dc)
44 {
45   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
46   HBRUSH32 ledBrush;
47   int rightBar, rightMost;
48   PAINTSTRUCT32 ps;
49   RECT32 rect;
50   HDC32 hdc;
51
52   dprintf_progress(stddeb, "Progress Bar: paint pos=%d min=%d, max=%d\n",
53                    infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
54
55   /* get a dc */
56   hdc = dc==0 ? BeginPaint32(wndPtr->hwndSelf, &ps) : dc;
57
58   /* get the required brush */
59   ledBrush = GetSysColorBrush32(COLOR_HIGHLIGHT);
60
61   /* get rect for the bar, adjusted for the border */
62   GetClientRect32(wndPtr->hwndSelf, &rect);
63
64   /* draw the border */
65   DrawEdge32(hdc, &rect, BDR_SUNKENOUTER, BF_RECT|BF_ADJUST|BF_MIDDLE);
66   rect.left++; rect.right--; rect.top++; rect.bottom--;
67   rightMost = rect.right;
68
69   /* compute extent of progress bar */
70   rightBar = rect.left + 
71     MulDiv32(infoPtr->CurVal-infoPtr->MinVal,
72              rect.right - rect.left,
73              infoPtr->MaxVal-infoPtr->MinVal);
74
75   /* now draw the bar */
76   while(rect.left < rightBar) { 
77     rect.right = rect.left+LED_WIDTH;
78     FillRect32(hdc, &rect, ledBrush);
79     rect.left  = rect.right+LED_GAP;
80   }
81
82   /* clean-up */  
83   if(!dc)
84     EndPaint32(wndPtr->hwndSelf, &ps);
85 }
86
87 /***********************************************************************
88  *           PROGRESS_CoercePos
89  * Makes sure the current position (CUrVal) is within bounds.
90  */
91 static void PROGRESS_CoercePos(WND *wndPtr)
92 {
93   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
94
95   if(infoPtr->CurVal < infoPtr->MinVal)
96     infoPtr->CurVal = infoPtr->MinVal;
97   if(infoPtr->CurVal > infoPtr->MaxVal)
98     infoPtr->CurVal = infoPtr->MaxVal;
99 }
100
101 /***********************************************************************
102  *           ProgressWindowProc
103  */
104 LRESULT WINAPI ProgressWindowProc(HWND32 hwnd, UINT32 message, 
105                                   WPARAM32 wParam, LPARAM lParam)
106 {
107   WND *wndPtr = WIN_FindWndPtr(hwnd);
108   PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
109   UINT32 temp;
110
111   switch(message)
112     {
113     case WM_CREATE:
114       /* initialize the info struct */
115       infoPtr->MinVal=0; 
116       infoPtr->MaxVal=100;
117       infoPtr->CurVal=0; 
118       infoPtr->Step=10;
119       dprintf_updown(stddeb, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
120       break;
121     
122     case WM_DESTROY:
123       dprintf_updown(stddeb, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
124       break;
125
126     case WM_ERASEBKGND:
127       /* pretend to erase it here, but we will do it in the paint
128          function to avoid flicker */
129       return 1;
130         
131     case WM_GETFONT:
132       /* FIXME: What do we need to do? */
133       break;
134
135     case WM_SETFONT:
136       /* FIXME: What do we need to do? */
137       break;
138
139     case WM_PAINT:
140       PROGRESS_Paint(wndPtr, wParam);
141       break;
142     
143     case PBM_DELTAPOS:
144       if(lParam)
145         UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
146       temp = infoPtr->CurVal;
147       if(wParam != 0){
148         infoPtr->CurVal += (UINT16)wParam;
149         PROGRESS_CoercePos(wndPtr);
150         PROGRESS_Paint(wndPtr, 0);
151       }
152       return temp;
153
154     case PBM_SETPOS:
155       if (lParam)
156         UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
157       temp = infoPtr->CurVal;
158       if(temp != wParam){
159         infoPtr->CurVal = (UINT16)wParam;
160         PROGRESS_CoercePos(wndPtr);
161         PROGRESS_Paint(wndPtr, 0);
162       }
163       return temp;          
164       
165     case PBM_SETRANGE:
166       if (wParam)
167         UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
168       temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
169       if(temp != lParam){
170         infoPtr->MinVal = LOWORD(lParam); 
171         infoPtr->MaxVal = HIWORD(lParam);
172         if(infoPtr->MaxVal <= infoPtr->MinVal)
173           infoPtr->MaxVal = infoPtr->MinVal+1;
174         PROGRESS_CoercePos(wndPtr);
175         PROGRESS_Paint(wndPtr, 0);
176       }
177       return temp;
178
179     case PBM_SETSTEP:
180       if (lParam)
181         UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
182       temp = infoPtr->Step;   
183       infoPtr->Step = (UINT16)wParam;   
184       return temp;
185
186     case PBM_STEPIT:
187       if (wParam || lParam)
188         UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
189       temp = infoPtr->CurVal;   
190       infoPtr->CurVal += infoPtr->Step;
191       if(infoPtr->CurVal > infoPtr->MaxVal)
192         infoPtr->CurVal = infoPtr->MinVal;
193       if(temp != infoPtr->CurVal)
194         PROGRESS_Paint(wndPtr, 0);
195       return temp;
196     
197     default: 
198       if (message >= WM_USER) 
199         fprintf( stderr, "Progress Ctrl: unknown msg %04x wp=%04x lp=%08lx\n", 
200                  message, wParam, lParam );
201       return DefWindowProc32A( hwnd, message, wParam, lParam ); 
202     } 
203
204     return 0;
205 }
206
207
208