1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.Windows.API;
9
10 namespace System.Windows
11 {
12 public nothrow ControlCreateParams& ScrollableControlControlCreateParams(ControlCreateParams& controlCreateParams, Control* child)
13 {
14 return controlCreateParams.SetWindowClassName("System.Windows.ScrollableControl").SetBackgroundColor(child->BackgroundColor());
15 }
16
17 public class ScrollableControlCreateParams
18 {
19 public nothrow ScrollableControlCreateParams(ControlCreateParams& controlCreateParams_, Control* child_) :
20 controlCreateParams(controlCreateParams_), child(child_)
21 {
22 }
23 public nothrow ScrollableControlCreateParams& Defaults()
24 {
25 return *this;
26 }
27 public ControlCreateParams& controlCreateParams;
28 public Control* child;
29 }
30
31 public class ScrollableControl : Control
32 {
33 public ScrollableControl(Control* child_, const Point& location, const Size& size, Dock dock, Anchors anchors) :
34 base("System.Windows.ScrollableControl", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
35 child_->BackgroundColor(), "scrollableControl", location, size, dock, anchors), container(this), child(child_),
36 verticalScrollUnit(0), horizontalScrollUnit(0), vpage(0u), vpos(0), vmin(0), vmax(0), hpage(0u), hpos(0), hmin(0), hmax(0),
37 verticalScrollBarShown(false), horizontalScrollBarShown(false)
38 {
39 container.AddChild(child);
40 }
41 public ScrollableControl(ScrollableControlCreateParams& createParams) :
42 base(createParams.controlCreateParams), container(this), child(createParams.child),
43 verticalScrollUnit(0), horizontalScrollUnit(0), vpage(0u), vpos(0), vmin(0), vmax(0), hpage(0u), hpos(0), hmin(0), hmax(0),
44 verticalScrollBarShown(false), horizontalScrollBarShown(false)
45 {
46 container.AddChild(child);
47 }
48 protected override nothrow bool IsDecoratorControl() const
49 {
50 return true;
51 }
52 protected override void OnLocationChanged()
53 {
54 base->OnLocationChanged();
55 child->SetLocation(Point());
56 child->SetSize(GetSize());
57 }
58 protected override void OnSizeChanged(uint windowState)
59 {
60 base->OnSizeChanged(windowState);
61 child->SetLocation(Point());
62 child->SetSize(GetSize());
63 }
64 protected override void OnChildSizeChanged(ControlEventArgs& args)
65 {
66 base->OnChildSizeChanged(args);
67 ChildSizeOrContentSizeChanged(args);
68 }
69 protected override void OnChildContentChanged(ControlEventArgs& args)
70 {
71 base->OnChildContentChanged(args);
72 hpos = 0;
73 vpos = 0;
74 }
75 protected override void OnChildContentLocationChanged(ControlEventArgs& args)
76 {
77 base->OnChildContentLocationChanged(args);
78 scrolledChild = args.control;
79 Point childContentLocation = scrolledChild->ContentLocation();
80 Pair<int, int> scrollUnits = scrolledChild->GetScrollUnits();
81 int verticalScrollUnit = scrollUnits.first;
82 int horizontalScrollUnit = scrollUnits.second;
83 vpos = childContentLocation.y / verticalScrollUnit;
84 SetScrollInfo(Handle(), ScrollBar.SB_VERT, ScrollInfoMask.SIF_POS, true, 0u, vpos, 0, 0);
85 hpos = childContentLocation.x / horizontalScrollUnit;
86 SetScrollInfo(Handle(), ScrollBar.SB_HORZ, ScrollInfoMask.SIF_POS, true, 0u, hpos, 0, 0);
87 }
88 private void ChildSizeOrContentSizeChanged(ControlEventArgs& args)
89 {
90 scrolledChild = args.control;
91 Pair<int, int> scrollUnits = scrolledChild->GetScrollUnits();
92 verticalScrollUnit = scrollUnits.first;
93 horizontalScrollUnit = scrollUnits.second;
94 Size scrolledChildClientSize = scrolledChild->GetSize();
95 Size scrolledChildContentSize = scrolledChild->ContentSize();
96 if (scrolledChildContentSize.h > scrolledChildClientSize.h)
97 {
98 vmin = 0;
99 vmax = 1;
100 vpage = 1u;
101 if (verticalScrollUnit > 0)
102 {
103 vmax = cast<int>(scrolledChildContentSize.h / verticalScrollUnit);
104 vpage = cast<uint>(scrolledChildClientSize.h / verticalScrollUnit);
105 }
106 SetScrollInfo(Handle(), ScrollBar.SB_VERT, cast<ScrollInfoMask>(ScrollInfoMask.SIF_POS | ScrollInfoMask.SIF_PAGE | ScrollInfoMask.SIF_RANGE), true,
107 vpage, vpos, vmin, vmax);
108 ShowScrollBar(Handle(), ScrollBar.SB_VERT, true);
109 verticalScrollBarShown = true;
110 }
111 else
112 {
113 ShowScrollBar(Handle(), ScrollBar.SB_VERT, false);
114 verticalScrollBarShown = false;
115 }
116 if (scrolledChildContentSize.w > scrolledChildClientSize.w)
117 {
118 hmin = 0;
119 hmax = 1;
120 hpage = 1u;
121 if (horizontalScrollUnit > 0)
122 {
123 hmax = cast<int>(scrolledChildContentSize.w / horizontalScrollUnit);
124 hpage = cast<uint>(scrolledChildClientSize.w / horizontalScrollUnit);
125 }
126 SetScrollInfo(Handle(), ScrollBar.SB_HORZ, cast<ScrollInfoMask>(ScrollInfoMask.SIF_POS | ScrollInfoMask.SIF_PAGE | ScrollInfoMask.SIF_RANGE), true,
127 hpage, hpos, hmin, hmax);
128 ShowScrollBar(Handle(), ScrollBar.SB_HORZ, true);
129 horizontalScrollBarShown = true;
130 }
131 else
132 {
133 ShowScrollBar(Handle(), ScrollBar.SB_HORZ, false);
134 horizontalScrollBarShown = false;
135 }
136 }
137 protected override void OnChildContentSizeChanged(ControlEventArgs& args)
138 {
139 base->OnChildContentSizeChanged(args);
140 ChildSizeOrContentSizeChanged(args);
141 }
142 protected override void OnChildGotFocus(ControlEventArgs& args)
143 {
144 base->OnChildGotFocus(args);
145 Control* parentControl = ParentControl();
146 if (parentControl != null)
147 {
148 parentControl->OnChildGotFocus(args);
149 }
150 }
151 protected override void OnChildLostFocus(ControlEventArgs& args)
152 {
153 base->OnChildLostFocus(args);
154 Control* parentControl = ParentControl();
155 if (parentControl != null)
156 {
157 parentControl->OnChildLostFocus(args);
158 }
159 }
160 protected override void OnHScroll(ScrollEventArgs& args)
161 {
162 base->OnHScroll(args);
163 int trackPos;
164 GetScrollInfo(Handle(), ScrollBar.SB_HORZ, hpage, hpos, hmin, hmax, trackPos);
165 int prevHPos = hpos;
166 switch (args.request)
167 {
168 case SB_LINELEFT:
169 {
170 --hpos;
171 break;
172 }
173 case SB_LINERIGHT:
174 {
175 ++hpos;
176 break;
177 }
178 case SB_PAGELEFT:
179 {
180 hpos = hpos - cast<int>(hpage);
181 break;
182 }
183 case SB_PAGERIGHT:
184 {
185 hpos = hpos + cast<int>(hpage);
186 break;
187 }
188 case SB_THUMBTRACK:
189 {
190 hpos = trackPos;
191 break;
192 }
193 }
194 SetScrollInfo(Handle(), ScrollBar.SB_HORZ, ScrollInfoMask.SIF_POS, true, 0u, hpos, 0, 0);
195 GetScrollInfo(Handle(), ScrollBar.SB_HORZ, hpage, hpos, hmin, hmax, trackPos);
196 if (prevHPos != hpos)
197 {
198 scrolledChild->SetContentLocationInternal(Point(horizontalScrollUnit * hpos, verticalScrollUnit * vpos));
199 int xAmount = horizontalScrollUnit * (prevHPos - hpos);
200 Rect updateRect = MakeUpdateRect(xAmount, 0);
201 ScrollWindowEx(scrolledChild->Handle(), xAmount, 0, null, null, updateRect);
202 if (scrolledChild->IsDoubleBuffered())
203 {
204 scrolledChild->Invalidate();
205 }
206 }
207 }
208 public override void ScrollLineDown()
209 {
210 int trackPos;
211 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
212 int prevVPos = vpos;
213 if (vpos != vmax)
214 {
215 ++vpos;
216 SetScrollInfo(Handle(), ScrollBar.SB_VERT, ScrollInfoMask.SIF_POS, true, 0u, vpos, 0, 0);
217 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
218 if (prevVPos != vpos)
219 {
220 scrolledChild->SetContentLocationInternal(Point(horizontalScrollUnit * hpos, verticalScrollUnit * vpos));
221 int yAmount = verticalScrollUnit * (prevVPos - vpos);
222 Rect updateRect = MakeUpdateRect(0, yAmount);
223 ScrollWindowEx(scrolledChild->Handle(), 0, yAmount, null, null, updateRect);
224 if (scrolledChild->IsDoubleBuffered())
225 {
226 scrolledChild->Invalidate();
227 }
228 }
229 }
230 }
231 public override void ScrollLineUp()
232 {
233 int trackPos;
234 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
235 int prevVPos = vpos;
236 if (vpos != vmin)
237 {
238 --vpos;
239 SetScrollInfo(Handle(), ScrollBar.SB_VERT, ScrollInfoMask.SIF_POS, true, 0u, vpos, 0, 0);
240 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
241 if (prevVPos != vpos)
242 {
243 scrolledChild->SetContentLocationInternal(Point(horizontalScrollUnit * hpos, verticalScrollUnit * vpos));
244 int yAmount = verticalScrollUnit * (prevVPos - vpos);
245 Rect updateRect = MakeUpdateRect(0, yAmount);
246 ScrollWindowEx(scrolledChild->Handle(), 0, yAmount, null, null, updateRect);
247 if (scrolledChild->IsDoubleBuffered())
248 {
249 scrolledChild->Invalidate();
250 }
251 }
252 }
253 }
254 protected override void OnVScroll(ScrollEventArgs& args)
255 {
256 base->OnVScroll(args);
257 int trackPos;
258 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
259 int prevVPos = vpos;
260 switch (args.request)
261 {
262 case SB_TOP:
263 {
264 vpos = vmin;
265 break;
266 }
267 case SB_BOTTOM:
268 {
269 vpos = vmax;
270 break;
271 }
272 case SB_LINEUP:
273 {
274 --vpos;
275 break;
276 }
277 case SB_LINEDOWN:
278 {
279 ++vpos;
280 break;
281 }
282 case SB_PAGEUP:
283 {
284 vpos = vpos - cast<int>(vpage);
285 break;
286 }
287 case SB_PAGEDOWN:
288 {
289 vpos = vpos + cast<int>(vpage);
290 break;
291 }
292 case SB_THUMBTRACK:
293 {
294 vpos = trackPos;
295 break;
296 }
297 }
298 SetScrollInfo(Handle(), ScrollBar.SB_VERT, ScrollInfoMask.SIF_POS, true, 0u, vpos, 0, 0);
299 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
300 if (prevVPos != vpos)
301 {
302 scrolledChild->SetContentLocationInternal(Point(horizontalScrollUnit * hpos, verticalScrollUnit * vpos));
303 int yAmount = verticalScrollUnit * (prevVPos - vpos);
304 Rect updateRect = MakeUpdateRect(0, yAmount);
305 ScrollWindowEx(scrolledChild->Handle(), 0, yAmount, null, null, updateRect);
306 if (scrolledChild->IsDoubleBuffered())
307 {
308 scrolledChild->Invalidate();
309 }
310 }
311 }
312 protected override void OnMouseWheel(MouseWheelEventArgs& args)
313 {
314 base->OnMouseWheel(args);
315 if (!args.handled)
316 {
317 if (verticalScrollBarShown)
318 {
319 int trackPos;
320 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
321 int prevVPos = vpos;
322 vpos = cast<int>(vpos - args.distance / (2.0 * verticalScrollUnit));
323 SetScrollInfo(Handle(), ScrollBar.SB_VERT, ScrollInfoMask.SIF_POS, true, 0u, vpos, 0, 0);
324 GetScrollInfo(Handle(), ScrollBar.SB_VERT, vpage, vpos, vmin, vmax, trackPos);
325 if (prevVPos != vpos)
326 {
327 Point contentLocation(horizontalScrollUnit * hpos, verticalScrollUnit * vpos);
328 scrolledChild->SetContentLocationInternal(contentLocation);
329 int yAmount = verticalScrollUnit * (prevVPos - vpos);
330 Rect updateRect = MakeUpdateRect(0, yAmount);
331 ScrollWindowEx(scrolledChild->Handle(), 0, yAmount, null, null, updateRect);
332 if (scrolledChild->IsDoubleBuffered())
333 {
334 scrolledChild->Invalidate();
335 }
336 }
337 args.handled = true;
338 }
339 }
340 }
341 protected override void TranslateChildGraphics(Graphics& graphics)
342 {
343 int dx = -hpos * horizontalScrollUnit;
344 int dy = -vpos * verticalScrollUnit;
345 if (dx != 0 || dy != 0)
346 {
347 graphics.TranslateTransformChecked(dx, dy);
348 }
349 }
350 protected override void TranslateMousePos(Point& location)
351 {
352 int dx = hpos * horizontalScrollUnit;
353 int dy = vpos * verticalScrollUnit;
354 location.x = location.x + dx;
355 location.y = location.y + dy;
356 }
357 protected override void TranslateContentLocation(Point& location)
358 {
359 int dx = hpos * horizontalScrollUnit;
360 int dy = vpos * verticalScrollUnit;
361 location.x = location.x - dx;
362 location.y = location.y - dy;
363 }
364 internal override nothrow Control* GetFirstEnabledTabStopControl() const
365 {
366 return child->GetFirstEnabledTabStopControl();
367 }
368 internal override nothrow Control* GetLastEnabledTabStopControl() const
369 {
370 return child->GetLastEnabledTabStopControl();
371 }
372 private nothrow Rect MakeUpdateRect(int xAmount, int yAmount)
373 {
374 Point loc(0, 0);
375 Size size = scrolledChild->GetSize();
376 if (xAmount < 0)
377 {
378 loc.x = size.w + xAmount;
379 }
380 if (xAmount != 0)
381 {
382 size.w = Abs(xAmount);
383 }
384 if (yAmount < 0)
385 {
386 loc.y = size.h + yAmount;
387 }
388 if (yAmount != 0)
389 {
390 size.h = Abs(yAmount);
391 }
392 Rect updateRect(loc, size);
393 updateRect.Inflate(horizontalScrollUnit, verticalScrollUnit);
394 return updateRect;
395 }
396 private Container container;
397 private Control* child;
398 private Control* scrolledChild;
399 private int verticalScrollUnit;
400 private int horizontalScrollUnit;
401 private uint vpage;
402 private int vpos;
403 private int vmin;
404 private int vmax;
405 private uint hpage;
406 private int hpos;
407 private int hmin;
408 private int hmax;
409 private bool verticalScrollBarShown;
410 private bool horizontalScrollBarShown;
411 }
412 }