| 1 |
/******************************************************************************* |
|---|
| 2 |
* Copyright (c) 2000, 2008 IBM Corporation and others. |
|---|
| 3 |
* All rights reserved. This program and the accompanying materials |
|---|
| 4 |
* are made available under the terms of the Eclipse Public License v1.0 |
|---|
| 5 |
* which accompanies this distribution, and is available at |
|---|
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
|---|
| 7 |
* |
|---|
| 8 |
* Contributors: |
|---|
| 9 |
* IBM Corporation - initial API and implementation |
|---|
| 10 |
* Port to the D programming language: |
|---|
| 11 |
* Frank Benoit <benoit@tionex.de> |
|---|
| 12 |
*******************************************************************************/ |
|---|
| 13 |
module dwt.widgets.Scrollable; |
|---|
| 14 |
|
|---|
| 15 |
import dwt.DWT; |
|---|
| 16 |
import dwt.DWTException; |
|---|
| 17 |
|
|---|
| 18 |
import dwt.graphics.Rectangle; |
|---|
| 19 |
|
|---|
| 20 |
import dwt.internal.win32.OS; |
|---|
| 21 |
|
|---|
| 22 |
import dwt.widgets.Composite; |
|---|
| 23 |
import dwt.widgets.Control; |
|---|
| 24 |
import dwt.widgets.Decorations; |
|---|
| 25 |
import dwt.widgets.Event; |
|---|
| 26 |
import dwt.widgets.ScrollBar; |
|---|
| 27 |
import dwt.widgets.Widget; |
|---|
| 28 |
|
|---|
| 29 |
import dwt.dwthelper.utils; |
|---|
| 30 |
//import tango.util.log.Trace; |
|---|
| 31 |
void trc( long line ){ |
|---|
| 32 |
//Trace.formatln( "Scrollable {}", line ); |
|---|
| 33 |
} |
|---|
| 34 |
|
|---|
| 35 |
/** |
|---|
| 36 |
* This class is the abstract superclass of all classes which |
|---|
| 37 |
* represent controls that have standard scroll bars. |
|---|
| 38 |
* <dl> |
|---|
| 39 |
* <dt><b>Styles:</b></dt> |
|---|
| 40 |
* <dd>H_SCROLL, V_SCROLL</dd> |
|---|
| 41 |
* <dt><b>Events:</b> |
|---|
| 42 |
* <dd>(none)</dd> |
|---|
| 43 |
* </dl> |
|---|
| 44 |
* <p> |
|---|
| 45 |
* IMPORTANT: This class is intended to be subclassed <em>only</em> |
|---|
| 46 |
* within the DWT implementation. |
|---|
| 47 |
* </p> |
|---|
| 48 |
* |
|---|
| 49 |
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
|---|
| 50 |
*/ |
|---|
| 51 |
|
|---|
| 52 |
public abstract class Scrollable : Control { |
|---|
| 53 |
|
|---|
| 54 |
alias Control.windowProc windowProc; |
|---|
| 55 |
|
|---|
| 56 |
ScrollBar horizontalBar, verticalBar; |
|---|
| 57 |
|
|---|
| 58 |
/** |
|---|
| 59 |
* Prevents uninitialized instances from being created outside the package. |
|---|
| 60 |
*/ |
|---|
| 61 |
this () { |
|---|
| 62 |
} |
|---|
| 63 |
|
|---|
| 64 |
/** |
|---|
| 65 |
* Constructs a new instance of this class given its parent |
|---|
| 66 |
* and a style value describing its behavior and appearance. |
|---|
| 67 |
* <p> |
|---|
| 68 |
* The style value is either one of the style constants defined in |
|---|
| 69 |
* class <code>DWT</code> which is applicable to instances of this |
|---|
| 70 |
* class, or must be built by <em>bitwise OR</em>'ing together |
|---|
| 71 |
* (that is, using the <code>int</code> "|" operator) two or more |
|---|
| 72 |
* of those <code>DWT</code> style constants. The class description |
|---|
| 73 |
* lists the style constants that are applicable to the class. |
|---|
| 74 |
* Style bits are also inherited from superclasses. |
|---|
| 75 |
* </p> |
|---|
| 76 |
* |
|---|
| 77 |
* @param parent a composite control which will be the parent of the new instance (cannot be null) |
|---|
| 78 |
* @param style the style of control to construct |
|---|
| 79 |
* |
|---|
| 80 |
* @exception IllegalArgumentException <ul> |
|---|
| 81 |
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
|---|
| 82 |
* </ul> |
|---|
| 83 |
* @exception DWTException <ul> |
|---|
| 84 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> |
|---|
| 85 |
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> |
|---|
| 86 |
* </ul> |
|---|
| 87 |
* |
|---|
| 88 |
* @see DWT#H_SCROLL |
|---|
| 89 |
* @see DWT#V_SCROLL |
|---|
| 90 |
* @see Widget#checkSubclass |
|---|
| 91 |
* @see Widget#getStyle |
|---|
| 92 |
*/ |
|---|
| 93 |
public this (Composite parent, int style) { |
|---|
| 94 |
super (parent, style); |
|---|
| 95 |
} |
|---|
| 96 |
|
|---|
| 97 |
override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { |
|---|
| 98 |
if (handle is null) return 0; |
|---|
| 99 |
return OS.DefWindowProc (hwnd, msg, wParam, lParam); |
|---|
| 100 |
} |
|---|
| 101 |
|
|---|
| 102 |
/** |
|---|
| 103 |
* Given a desired <em>client area</em> for the receiver |
|---|
| 104 |
* (as described by the arguments), returns the bounding |
|---|
| 105 |
* rectangle which would be required to produce that client |
|---|
| 106 |
* area. |
|---|
| 107 |
* <p> |
|---|
| 108 |
* In other words, it returns a rectangle such that, if the |
|---|
| 109 |
* receiver's bounds were set to that rectangle, the area |
|---|
| 110 |
* of the receiver which is capable of displaying data |
|---|
| 111 |
* (that is, not covered by the "trimmings") would be the |
|---|
| 112 |
* rectangle described by the arguments (relative to the |
|---|
| 113 |
* receiver's parent). |
|---|
| 114 |
* </p> |
|---|
| 115 |
* |
|---|
| 116 |
* @param x the desired x coordinate of the client area |
|---|
| 117 |
* @param y the desired y coordinate of the client area |
|---|
| 118 |
* @param width the desired width of the client area |
|---|
| 119 |
* @param height the desired height of the client area |
|---|
| 120 |
* @return the required bounds to produce the given client area |
|---|
| 121 |
* |
|---|
| 122 |
* @exception DWTException <ul> |
|---|
| 123 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 124 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 125 |
* </ul> |
|---|
| 126 |
* |
|---|
| 127 |
* @see #getClientArea |
|---|
| 128 |
*/ |
|---|
| 129 |
public Rectangle computeTrim (int x, int y, int width, int height) { |
|---|
| 130 |
checkWidget (); |
|---|
| 131 |
auto scrolledHandle_ = scrolledHandle (); |
|---|
| 132 |
RECT rect; |
|---|
| 133 |
OS.SetRect (&rect, x, y, x + width, y + height); |
|---|
| 134 |
int bits1 = OS.GetWindowLong (scrolledHandle_, OS.GWL_STYLE); |
|---|
| 135 |
int bits2 = OS.GetWindowLong (scrolledHandle_, OS.GWL_EXSTYLE); |
|---|
| 136 |
OS.AdjustWindowRectEx (&rect, bits1, false, bits2); |
|---|
| 137 |
if (horizontalBar !is null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL); |
|---|
| 138 |
if (verticalBar !is null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL); |
|---|
| 139 |
int nWidth = rect.right - rect.left, nHeight = rect.bottom - rect.top; |
|---|
| 140 |
return new Rectangle (rect.left, rect.top, nWidth, nHeight); |
|---|
| 141 |
} |
|---|
| 142 |
|
|---|
| 143 |
ScrollBar createScrollBar (int type) { |
|---|
| 144 |
ScrollBar bar = new ScrollBar (this, type); |
|---|
| 145 |
if ((state & CANVAS) !is 0) { |
|---|
| 146 |
bar.setMaximum (100); |
|---|
| 147 |
bar.setThumb (10); |
|---|
| 148 |
} |
|---|
| 149 |
return bar; |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
override void createWidget () { |
|---|
| 153 |
super.createWidget (); |
|---|
| 154 |
if ((style & DWT.H_SCROLL) !is 0) horizontalBar = createScrollBar (DWT.H_SCROLL); |
|---|
| 155 |
if ((style & DWT.V_SCROLL) !is 0) verticalBar = createScrollBar (DWT.V_SCROLL); |
|---|
| 156 |
} |
|---|
| 157 |
|
|---|
| 158 |
void destroyScrollBar (int type) { |
|---|
| 159 |
auto hwnd = scrolledHandle (); |
|---|
| 160 |
int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE); |
|---|
| 161 |
if ((type & DWT.HORIZONTAL) !is 0) { |
|---|
| 162 |
style &= ~DWT.H_SCROLL; |
|---|
| 163 |
bits &= ~OS.WS_HSCROLL; |
|---|
| 164 |
} |
|---|
| 165 |
if ((type & DWT.VERTICAL) !is 0) { |
|---|
| 166 |
style &= ~DWT.V_SCROLL; |
|---|
| 167 |
bits &= ~OS.WS_VSCROLL; |
|---|
| 168 |
} |
|---|
| 169 |
OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits); |
|---|
| 170 |
} |
|---|
| 171 |
|
|---|
| 172 |
/** |
|---|
| 173 |
* Returns a rectangle which describes the area of the |
|---|
| 174 |
* receiver which is capable of displaying data (that is, |
|---|
| 175 |
* not covered by the "trimmings"). |
|---|
| 176 |
* |
|---|
| 177 |
* @return the client area |
|---|
| 178 |
* |
|---|
| 179 |
* @exception DWTException <ul> |
|---|
| 180 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 181 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 182 |
* </ul> |
|---|
| 183 |
* |
|---|
| 184 |
* @see #computeTrim |
|---|
| 185 |
*/ |
|---|
| 186 |
public Rectangle getClientArea () { |
|---|
| 187 |
checkWidget (); |
|---|
| 188 |
forceResize (); |
|---|
| 189 |
RECT rect; |
|---|
| 190 |
auto scrolledHandle_ = scrolledHandle (); |
|---|
| 191 |
OS.GetClientRect (scrolledHandle_, &rect); |
|---|
| 192 |
int x = rect.left, y = rect.top; |
|---|
| 193 |
int width = rect.right - rect.left; |
|---|
| 194 |
int height = rect.bottom - rect.top; |
|---|
| 195 |
if (scrolledHandle_ !is handle) { |
|---|
| 196 |
OS.GetClientRect (handle, &rect); |
|---|
| 197 |
OS.MapWindowPoints(handle, scrolledHandle_, cast(POINT*)&rect, 2); |
|---|
| 198 |
x = -rect.left; |
|---|
| 199 |
y = -rect.top; |
|---|
| 200 |
} |
|---|
| 201 |
return new Rectangle (x, y, width, height); |
|---|
| 202 |
} |
|---|
| 203 |
|
|---|
| 204 |
/** |
|---|
| 205 |
* Returns the receiver's horizontal scroll bar if it has |
|---|
| 206 |
* one, and null if it does not. |
|---|
| 207 |
* |
|---|
| 208 |
* @return the horizontal scroll bar (or null) |
|---|
| 209 |
* |
|---|
| 210 |
* @exception DWTException <ul> |
|---|
| 211 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 212 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 213 |
* </ul> |
|---|
| 214 |
*/ |
|---|
| 215 |
public ScrollBar getHorizontalBar () { |
|---|
| 216 |
checkWidget (); |
|---|
| 217 |
return horizontalBar; |
|---|
| 218 |
} |
|---|
| 219 |
|
|---|
| 220 |
/** |
|---|
| 221 |
* Returns the receiver's vertical scroll bar if it has |
|---|
| 222 |
* one, and null if it does not. |
|---|
| 223 |
* |
|---|
| 224 |
* @return the vertical scroll bar (or null) |
|---|
| 225 |
* |
|---|
| 226 |
* @exception DWTException <ul> |
|---|
| 227 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 228 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 229 |
* </ul> |
|---|
| 230 |
*/ |
|---|
| 231 |
public ScrollBar getVerticalBar () { |
|---|
| 232 |
checkWidget (); |
|---|
| 233 |
return verticalBar; |
|---|
| 234 |
} |
|---|
| 235 |
|
|---|
| 236 |
override void releaseChildren (bool destroy) { |
|---|
| 237 |
if (horizontalBar !is null) { |
|---|
| 238 |
horizontalBar.release (false); |
|---|
| 239 |
horizontalBar = null; |
|---|
| 240 |
} |
|---|
| 241 |
if (verticalBar !is null) { |
|---|
| 242 |
verticalBar.release (false); |
|---|
| 243 |
verticalBar = null; |
|---|
| 244 |
} |
|---|
| 245 |
super.releaseChildren (destroy); |
|---|
| 246 |
} |
|---|
| 247 |
|
|---|
| 248 |
HANDLE scrolledHandle () { |
|---|
| 249 |
return handle; |
|---|
| 250 |
} |
|---|
| 251 |
|
|---|
| 252 |
override int widgetExtStyle () { |
|---|
| 253 |
return super.widgetExtStyle (); |
|---|
| 254 |
/* |
|---|
| 255 |
* This code is intentionally commented. In future, |
|---|
| 256 |
* we may wish to support different standard Windows |
|---|
| 257 |
* edge styles. The issue here is that not all of |
|---|
| 258 |
* these styles are available on the other platforms |
|---|
| 259 |
* this would need to be a hint. |
|---|
| 260 |
*/ |
|---|
| 261 |
// if ((style & DWT.BORDER) !is 0) return OS.WS_EX_CLIENTEDGE; |
|---|
| 262 |
// if ((style & DWT.SHADOW_IN) !is 0) return OS.WS_EX_STATICEDGE; |
|---|
| 263 |
// return super.widgetExtStyle (); |
|---|
| 264 |
} |
|---|
| 265 |
|
|---|
| 266 |
override int widgetStyle () { |
|---|
| 267 |
int bits = super.widgetStyle () | OS.WS_TABSTOP; |
|---|
| 268 |
if ((style & DWT.H_SCROLL) !is 0) bits |= OS.WS_HSCROLL; |
|---|
| 269 |
if ((style & DWT.V_SCROLL) !is 0) bits |= OS.WS_VSCROLL; |
|---|
| 270 |
return bits; |
|---|
| 271 |
} |
|---|
| 272 |
|
|---|
| 273 |
override String windowClass () { |
|---|
| 274 |
return display.windowClass(); |
|---|
| 275 |
} |
|---|
| 276 |
|
|---|
| 277 |
override int windowProc () { |
|---|
| 278 |
return display.windowProc; |
|---|
| 279 |
} |
|---|
| 280 |
|
|---|
| 281 |
override LRESULT WM_HSCROLL (int wParam, int lParam) { |
|---|
| 282 |
trc(__LINE__); |
|---|
| 283 |
LRESULT result = super.WM_HSCROLL (wParam, lParam); |
|---|
| 284 |
if (result !is null) return result; |
|---|
| 285 |
|
|---|
| 286 |
/* |
|---|
| 287 |
* Bug on WinCE. lParam should be NULL when the message is not sent |
|---|
| 288 |
* by a scroll bar control, but it contains the handle to the window. |
|---|
| 289 |
* When the message is sent by a scroll bar control, it correctly |
|---|
| 290 |
* contains the handle to the scroll bar. The fix is to check for |
|---|
| 291 |
* both. |
|---|
| 292 |
*/ |
|---|
| 293 |
if (horizontalBar !is null && (lParam is 0 || lParam is cast(int)handle)) { |
|---|
| 294 |
return wmScroll (horizontalBar, (state & CANVAS) !is 0, handle, OS.WM_HSCROLL, wParam, lParam); |
|---|
| 295 |
} |
|---|
| 296 |
return result; |
|---|
| 297 |
} |
|---|
| 298 |
|
|---|
| 299 |
override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { |
|---|
| 300 |
trc(__LINE__); |
|---|
| 301 |
int scrollRemainder = display.scrollRemainder; |
|---|
| 302 |
LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam); |
|---|
| 303 |
if (result !is null) return result; |
|---|
| 304 |
/* |
|---|
| 305 |
* Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL. |
|---|
| 306 |
*/ |
|---|
| 307 |
if ((state & CANVAS) !is 0) { |
|---|
| 308 |
if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) !is 0) return result; |
|---|
| 309 |
bool vertical = verticalBar !is null && verticalBar.getEnabled (); |
|---|
| 310 |
bool horizontal = horizontalBar !is null && horizontalBar.getEnabled (); |
|---|
| 311 |
int msg = vertical ? OS.WM_VSCROLL : horizontal ? OS.WM_HSCROLL : 0; |
|---|
| 312 |
if (msg is 0) return result; |
|---|
| 313 |
int linesToScroll; |
|---|
| 314 |
OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &linesToScroll, 0); |
|---|
| 315 |
int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam); |
|---|
| 316 |
bool pageScroll = linesToScroll is OS.WHEEL_PAGESCROLL; |
|---|
| 317 |
if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { |
|---|
| 318 |
ScrollBar bar = vertical ? verticalBar : horizontalBar; |
|---|
| 319 |
SCROLLINFO info; |
|---|
| 320 |
info.cbSize = SCROLLINFO.sizeof; |
|---|
| 321 |
info.fMask = OS.SIF_POS; |
|---|
| 322 |
OS.GetScrollInfo (handle, bar.scrollBarType (), &info); |
|---|
| 323 |
if (vertical && !pageScroll) delta *= linesToScroll; |
|---|
| 324 |
int increment = pageScroll ? bar.getPageIncrement () : bar.getIncrement (); |
|---|
| 325 |
info.nPos -= increment * delta / OS.WHEEL_DELTA; |
|---|
| 326 |
OS.SetScrollInfo (handle, bar.scrollBarType (), &info, true); |
|---|
| 327 |
OS.SendMessage (handle, msg, OS.SB_THUMBPOSITION, 0); |
|---|
| 328 |
} else { |
|---|
| 329 |
int code = 0; |
|---|
| 330 |
if (pageScroll) { |
|---|
| 331 |
code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP; |
|---|
| 332 |
} else { |
|---|
| 333 |
code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP; |
|---|
| 334 |
if (msg is OS.WM_VSCROLL) delta *= linesToScroll; |
|---|
| 335 |
} |
|---|
| 336 |
/* Check if the delta and the remainder have the same direction (sign) */ |
|---|
| 337 |
if ((delta ^ scrollRemainder) >= 0) delta += scrollRemainder; |
|---|
| 338 |
int count = Math.abs (delta) / OS.WHEEL_DELTA; |
|---|
| 339 |
for (int i=0; i<count; i++) { |
|---|
| 340 |
OS.SendMessage (handle, msg, code, 0); |
|---|
| 341 |
} |
|---|
| 342 |
} |
|---|
| 343 |
return LRESULT.ZERO; |
|---|
| 344 |
} |
|---|
| 345 |
|
|---|
| 346 |
/* |
|---|
| 347 |
* When the native widget scrolls inside WM_MOUSEWHEEL, it |
|---|
| 348 |
* may or may not send a WM_VSCROLL or WM_HSCROLL to do the |
|---|
| 349 |
* actual scrolling. This depends on the implementation of |
|---|
| 350 |
* each native widget. In order to ensure that application |
|---|
| 351 |
* code is notified when the scroll bar moves, compare the |
|---|
| 352 |
* scroll bar position before and after the WM_MOUSEWHEEL. |
|---|
| 353 |
* If the native control sends a WM_VSCROLL or WM_HSCROLL, |
|---|
| 354 |
* then the application has already been notified. If not |
|---|
| 355 |
* explicitly send the event. |
|---|
| 356 |
*/ |
|---|
| 357 |
int vPosition = verticalBar is null ? 0 : verticalBar.getSelection (); |
|---|
| 358 |
int hPosition = horizontalBar is null ? 0 : horizontalBar.getSelection (); |
|---|
| 359 |
int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam); |
|---|
| 360 |
if (verticalBar !is null) { |
|---|
| 361 |
int position = verticalBar.getSelection (); |
|---|
| 362 |
if (position !is vPosition) { |
|---|
| 363 |
Event event = new Event (); |
|---|
| 364 |
event.detail = position < vPosition ? DWT.PAGE_UP : DWT.PAGE_DOWN; |
|---|
| 365 |
verticalBar.sendEvent (DWT.Selection, event); |
|---|
| 366 |
} |
|---|
| 367 |
} |
|---|
| 368 |
if (horizontalBar !is null) { |
|---|
| 369 |
int position = horizontalBar.getSelection (); |
|---|
| 370 |
if (position !is hPosition) { |
|---|
| 371 |
Event event = new Event (); |
|---|
| 372 |
event.detail = position < hPosition ? DWT.PAGE_UP : DWT.PAGE_DOWN; |
|---|
| 373 |
horizontalBar.sendEvent (DWT.Selection, event); |
|---|
| 374 |
} |
|---|
| 375 |
} |
|---|
| 376 |
return new LRESULT (code); |
|---|
| 377 |
} |
|---|
| 378 |
|
|---|
| 379 |
override LRESULT WM_SIZE (int wParam, int lParam) { |
|---|
| 380 |
trc(__LINE__); |
|---|
| 381 |
int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam); |
|---|
| 382 |
super.WM_SIZE (wParam, lParam); |
|---|
| 383 |
// widget may be disposed at this point |
|---|
| 384 |
if (code is 0) return LRESULT.ZERO; |
|---|
| 385 |
return new LRESULT (code); |
|---|
| 386 |
} |
|---|
| 387 |
|
|---|
| 388 |
override LRESULT WM_VSCROLL (int wParam, int lParam) { |
|---|
| 389 |
trc(__LINE__); |
|---|
| 390 |
LRESULT result = super.WM_VSCROLL (wParam, lParam); |
|---|
| 391 |
if (result !is null) return result; |
|---|
| 392 |
/* |
|---|
| 393 |
* Bug on WinCE. lParam should be NULL when the message is not sent |
|---|
| 394 |
* by a scroll bar control, but it contains the handle to the window. |
|---|
| 395 |
* When the message is sent by a scroll bar control, it correctly |
|---|
| 396 |
* contains the handle to the scroll bar. The fix is to check for |
|---|
| 397 |
* both. |
|---|
| 398 |
*/ |
|---|
| 399 |
if (verticalBar !is null && (lParam is 0 || lParam is cast(int)handle)) { |
|---|
| 400 |
return wmScroll (verticalBar, (state & CANVAS) !is 0, handle, OS.WM_VSCROLL, wParam, lParam); |
|---|
| 401 |
} |
|---|
| 402 |
return result; |
|---|
| 403 |
} |
|---|
| 404 |
|
|---|
| 405 |
override LRESULT wmNCPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) { |
|---|
| 406 |
LRESULT result = super.wmNCPaint (hwnd, wParam, lParam); |
|---|
| 407 |
if (result !is null) return result; |
|---|
| 408 |
/* |
|---|
| 409 |
* Bug in Windows. On XP only (not Vista), Windows sometimes |
|---|
| 410 |
* does not redraw the bottom right corner of a window that |
|---|
| 411 |
* has scroll bars, causing pixel corruption. The fix is to |
|---|
| 412 |
* always draw the corner. |
|---|
| 413 |
*/ |
|---|
| 414 |
if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { |
|---|
| 415 |
if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) { |
|---|
| 416 |
int bits1 = OS.GetWindowLong (hwnd, OS.GWL_STYLE); |
|---|
| 417 |
if ((bits1 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) { |
|---|
| 418 |
RECT windowRect; |
|---|
| 419 |
OS.GetWindowRect (hwnd, &windowRect); |
|---|
| 420 |
RECT trimRect; |
|---|
| 421 |
int bits2 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); |
|---|
| 422 |
OS.AdjustWindowRectEx (&trimRect, bits1, false, bits2); |
|---|
| 423 |
bool hVisible = false, vVisible = false; |
|---|
| 424 |
SCROLLBARINFO psbi; |
|---|
| 425 |
psbi.cbSize = SCROLLBARINFO.sizeof; |
|---|
| 426 |
if (OS.GetScrollBarInfo (hwnd, OS.OBJID_HSCROLL, &psbi)) { |
|---|
| 427 |
hVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0; |
|---|
| 428 |
} |
|---|
| 429 |
if (OS.GetScrollBarInfo (hwnd, OS.OBJID_VSCROLL, &psbi)) { |
|---|
| 430 |
vVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0; |
|---|
| 431 |
} |
|---|
| 432 |
RECT cornerRect; |
|---|
| 433 |
cornerRect.right = windowRect.right - windowRect.left - trimRect.right; |
|---|
| 434 |
cornerRect.bottom = windowRect.bottom - windowRect.top - trimRect.bottom; |
|---|
| 435 |
cornerRect.left = cornerRect.right - (hVisible ? OS.GetSystemMetrics (OS.SM_CXVSCROLL) : 0); |
|---|
| 436 |
cornerRect.top = cornerRect.bottom - (vVisible ? OS.GetSystemMetrics (OS.SM_CYHSCROLL) : 0); |
|---|
| 437 |
if (cornerRect.left !is cornerRect.right && cornerRect.top !is cornerRect.bottom) { |
|---|
| 438 |
auto hDC = OS.GetWindowDC (hwnd); |
|---|
| 439 |
OS.FillRect (hDC, &cornerRect, cast(HANDLE)( OS.COLOR_BTNFACE + 1)); |
|---|
| 440 |
Decorations shell = menuShell (); |
|---|
| 441 |
if ((shell.style & DWT.RESIZE) !is 0) { |
|---|
| 442 |
auto hwndScroll = shell.scrolledHandle (); |
|---|
| 443 |
bool drawGripper = hwnd is hwndScroll; |
|---|
| 444 |
if (!drawGripper) { |
|---|
| 445 |
RECT shellRect; |
|---|
| 446 |
OS.GetClientRect (hwndScroll, &shellRect); |
|---|
| 447 |
OS.MapWindowPoints (hwndScroll, null, cast(POINT*)&shellRect, 2); |
|---|
| 448 |
drawGripper = shellRect.right is windowRect.right && shellRect.bottom is windowRect.bottom; |
|---|
| 449 |
} |
|---|
| 450 |
if (drawGripper) { |
|---|
| 451 |
OS.DrawThemeBackground (display.hScrollBarTheme(), hDC, OS.SBP_SIZEBOX, 0, &cornerRect, null); |
|---|
| 452 |
} |
|---|
| 453 |
} |
|---|
| 454 |
OS.ReleaseDC (hwnd, hDC); |
|---|
| 455 |
} |
|---|
| 456 |
} |
|---|
| 457 |
} |
|---|
| 458 |
} |
|---|
| 459 |
return result; |
|---|
| 460 |
} |
|---|
| 461 |
|
|---|
| 462 |
LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) { |
|---|
| 463 |
LRESULT result = null; |
|---|
| 464 |
if (update) { |
|---|
| 465 |
int type = msg is OS.WM_HSCROLL ? OS.SB_HORZ : OS.SB_VERT; |
|---|
| 466 |
SCROLLINFO info; |
|---|
| 467 |
info.cbSize = SCROLLINFO.sizeof; |
|---|
| 468 |
info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE; |
|---|
| 469 |
OS.GetScrollInfo (hwnd, type, &info); |
|---|
| 470 |
info.fMask = OS.SIF_POS; |
|---|
| 471 |
int code = OS.LOWORD (wParam); |
|---|
| 472 |
switch (code) { |
|---|
| 473 |
case OS.SB_ENDSCROLL: return null; |
|---|
| 474 |
case OS.SB_THUMBPOSITION: |
|---|
| 475 |
case OS.SB_THUMBTRACK: |
|---|
| 476 |
/* |
|---|
| 477 |
* Note: On WinCE, the value in SB_THUMBPOSITION is relative to nMin. |
|---|
| 478 |
* Same for SB_THUMBPOSITION 'except' for the very first thumb track |
|---|
| 479 |
* message which has the actual value of nMin. This is a problem when |
|---|
| 480 |
* nMin is not zero. |
|---|
| 481 |
*/ |
|---|
| 482 |
info.nPos = info.nTrackPos; |
|---|
| 483 |
break; |
|---|
| 484 |
case OS.SB_TOP: |
|---|
| 485 |
info.nPos = info.nMin; |
|---|
| 486 |
break; |
|---|
| 487 |
case OS.SB_BOTTOM: |
|---|
| 488 |
info.nPos = info.nMax; |
|---|
| 489 |
break; |
|---|
| 490 |
case OS.SB_LINEDOWN: |
|---|
| 491 |
info.nPos += bar.getIncrement (); |
|---|
| 492 |
break; |
|---|
| 493 |
case OS.SB_LINEUP: |
|---|
| 494 |
int increment = bar.getIncrement (); |
|---|
| 495 |
info.nPos = Math.max (info.nMin, info.nPos - increment); |
|---|
| 496 |
break; |
|---|
| 497 |
case OS.SB_PAGEDOWN: |
|---|
| 498 |
info.nPos += bar.getPageIncrement (); |
|---|
| 499 |
break; |
|---|
| 500 |
case OS.SB_PAGEUP: |
|---|
| 501 |
int pageIncrement = bar.getPageIncrement (); |
|---|
| 502 |
info.nPos = Math.max (info.nMin, info.nPos - pageIncrement); |
|---|
| 503 |
break; |
|---|
| 504 |
default: |
|---|
| 505 |
} |
|---|
| 506 |
OS.SetScrollInfo (hwnd, type, &info, true); |
|---|
| 507 |
} else { |
|---|
| 508 |
int /*long*/ code = callWindowProc (hwnd, msg, wParam, lParam); |
|---|
| 509 |
result = code is 0 ? LRESULT.ZERO : new LRESULT (code); |
|---|
| 510 |
} |
|---|
| 511 |
bar.wmScrollChild (wParam, lParam); |
|---|
| 512 |
return result; |
|---|
| 513 |
} |
|---|
| 514 |
|
|---|
| 515 |
} |
|---|