PWL_ScrollBar.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
1// Copyright 2014 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" 8 9#include "core/fxge/cfx_pathdata.h" 10#include "core/fxge/cfx_renderdevice.h" 11#include "fpdfsdk/pdfwindow/PWL_Utils.h" 12#include "fpdfsdk/pdfwindow/PWL_Wnd.h" 13 14PWL_FLOATRANGE::PWL_FLOATRANGE() { 15 Default(); 16} 17 18PWL_FLOATRANGE::PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max) { 19 Set(min, max); 20} 21 22void PWL_FLOATRANGE::Default() { 23 fMin = 0; 24 fMax = 0; 25} 26 27void PWL_FLOATRANGE::Set(FX_FLOAT min, FX_FLOAT max) { 28 if (min > max) { 29 fMin = max; 30 fMax = min; 31 } else { 32 fMin = min; 33 fMax = max; 34 } 35} 36 37bool PWL_FLOATRANGE::In(FX_FLOAT x) const { 38 return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) && 39 (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax)); 40} 41 42FX_FLOAT PWL_FLOATRANGE::GetWidth() const { 43 return fMax - fMin; 44} 45 46PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() { 47 Default(); 48} 49 50void PWL_SCROLL_PRIVATEDATA::Default() { 51 ScrollRange.Default(); 52 fScrollPos = ScrollRange.fMin; 53 fClientWidth = 0; 54 fBigStep = 10; 55 fSmallStep = 1; 56} 57 58void PWL_SCROLL_PRIVATEDATA::SetScrollRange(FX_FLOAT min, FX_FLOAT max) { 59 ScrollRange.Set(min, max); 60 61 if (IsFloatSmaller(fScrollPos, ScrollRange.fMin)) 62 fScrollPos = ScrollRange.fMin; 63 if (IsFloatBigger(fScrollPos, ScrollRange.fMax)) 64 fScrollPos = ScrollRange.fMax; 65} 66 67void PWL_SCROLL_PRIVATEDATA::SetClientWidth(FX_FLOAT width) { 68 fClientWidth = width; 69} 70 71void PWL_SCROLL_PRIVATEDATA::SetSmallStep(FX_FLOAT step) { 72 fSmallStep = step; 73} 74 75void PWL_SCROLL_PRIVATEDATA::SetBigStep(FX_FLOAT step) { 76 fBigStep = step; 77} 78 79bool PWL_SCROLL_PRIVATEDATA::SetPos(FX_FLOAT pos) { 80 if (ScrollRange.In(pos)) { 81 fScrollPos = pos; 82 return true; 83 } 84 return false; 85} 86 87void PWL_SCROLL_PRIVATEDATA::AddSmall() { 88 if (!SetPos(fScrollPos + fSmallStep)) 89 SetPos(ScrollRange.fMax); 90} 91 92void PWL_SCROLL_PRIVATEDATA::SubSmall() { 93 if (!SetPos(fScrollPos - fSmallStep)) 94 SetPos(ScrollRange.fMin); 95} 96 97void PWL_SCROLL_PRIVATEDATA::AddBig() { 98 if (!SetPos(fScrollPos + fBigStep)) 99 SetPos(ScrollRange.fMax); 100} 101 102void PWL_SCROLL_PRIVATEDATA::SubBig() { 103 if (!SetPos(fScrollPos - fBigStep)) 104 SetPos(ScrollRange.fMin); 105} 106 107CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, 108 PWL_SBBUTTON_TYPE eButtonType) { 109 m_eScrollBarType = eScrollBarType; 110 m_eSBButtonType = eButtonType; 111 112 m_bMouseDown = false; 113} 114 115CPWL_SBButton::~CPWL_SBButton() {} 116 117CFX_ByteString CPWL_SBButton::GetClassName() const { 118 return "CPWL_SBButton"; 119} 120 121void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) { 122 cp.eCursorType = FXCT_ARROW; 123} 124 125void CPWL_SBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { 126 CPWL_Wnd::GetThisAppearanceStream(sAppStream); 127 128 if (!IsVisible()) 129 return; 130 131 CFX_ByteTextBuf sButton; 132 133 CFX_FloatRect rectWnd = GetWindowRect(); 134 135 if (rectWnd.IsEmpty()) 136 return; 137 138 sAppStream << "q\n"; 139 140 CFX_FloatPoint ptCenter = GetCenterPoint(); 141 142 switch (m_eScrollBarType) { 143 case SBT_HSCROLL: 144 switch (m_eSBButtonType) { 145 case PSBT_MIN: { 146 CFX_FloatPoint pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 147 ptCenter.y); 148 CFX_FloatPoint pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 149 ptCenter.y + PWL_TRIANGLE_HALFLEN); 150 CFX_FloatPoint pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 151 ptCenter.y - PWL_TRIANGLE_HALFLEN); 152 153 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 154 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 155 sButton << "0 g\n"; 156 sButton << pt1.x << " " << pt1.y << " m\n"; 157 sButton << pt2.x << " " << pt2.y << " l\n"; 158 sButton << pt3.x << " " << pt3.y << " l\n"; 159 sButton << pt1.x << " " << pt1.y << " l f\n"; 160 161 sAppStream << sButton; 162 } 163 } break; 164 case PSBT_MAX: { 165 CFX_FloatPoint pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 166 ptCenter.y); 167 CFX_FloatPoint pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 168 ptCenter.y + PWL_TRIANGLE_HALFLEN); 169 CFX_FloatPoint pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 170 ptCenter.y - PWL_TRIANGLE_HALFLEN); 171 172 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 173 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 174 sButton << "0 g\n"; 175 sButton << pt1.x << " " << pt1.y << " m\n"; 176 sButton << pt2.x << " " << pt2.y << " l\n"; 177 sButton << pt3.x << " " << pt3.y << " l\n"; 178 sButton << pt1.x << " " << pt1.y << " l f\n"; 179 180 sAppStream << sButton; 181 } 182 } break; 183 default: 184 break; 185 } 186 break; 187 case SBT_VSCROLL: 188 switch (m_eSBButtonType) { 189 case PSBT_MIN: { 190 CFX_FloatPoint pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN, 191 ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); 192 CFX_FloatPoint pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN, 193 ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); 194 CFX_FloatPoint pt3(ptCenter.x, 195 ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); 196 197 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 198 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 199 sButton << "0 g\n"; 200 sButton << pt1.x << " " << pt1.y << " m\n"; 201 sButton << pt2.x << " " << pt2.y << " l\n"; 202 sButton << pt3.x << " " << pt3.y << " l\n"; 203 sButton << pt1.x << " " << pt1.y << " l f\n"; 204 205 sAppStream << sButton; 206 } 207 } break; 208 case PSBT_MAX: { 209 CFX_FloatPoint pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN, 210 ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); 211 CFX_FloatPoint pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN, 212 ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); 213 CFX_FloatPoint pt3(ptCenter.x, 214 ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); 215 216 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 217 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 218 sButton << "0 g\n"; 219 sButton << pt1.x << " " << pt1.y << " m\n"; 220 sButton << pt2.x << " " << pt2.y << " l\n"; 221 sButton << pt3.x << " " << pt3.y << " l\n"; 222 sButton << pt1.x << " " << pt1.y << " l f\n"; 223 224 sAppStream << sButton; 225 } 226 } break; 227 default: 228 break; 229 } 230 break; 231 default: 232 break; 233 } 234 235 sAppStream << "Q\n"; 236} 237 238void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, 239 CFX_Matrix* pUser2Device) { 240 if (!IsVisible()) 241 return; 242 243 CFX_FloatRect rectWnd = GetWindowRect(); 244 if (rectWnd.IsEmpty()) 245 return; 246 247 CFX_FloatPoint ptCenter = GetCenterPoint(); 248 int32_t nTransparancy = GetTransparency(); 249 250 switch (m_eScrollBarType) { 251 case SBT_HSCROLL: 252 CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); 253 switch (m_eSBButtonType) { 254 case PSBT_MIN: { 255 CFX_FloatPoint pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 256 ptCenter.y); 257 CFX_FloatPoint pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 258 ptCenter.y + PWL_TRIANGLE_HALFLEN); 259 CFX_FloatPoint pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 260 ptCenter.y - PWL_TRIANGLE_HALFLEN); 261 262 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 263 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 264 CFX_PathData path; 265 266 path.SetPointCount(4); 267 path.SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO); 268 path.SetPoint(1, pt2.x, pt2.y, FXPT_LINETO); 269 path.SetPoint(2, pt3.x, pt3.y, FXPT_LINETO); 270 path.SetPoint(3, pt1.x, pt1.y, FXPT_LINETO); 271 272 pDevice->DrawPath(&path, pUser2Device, nullptr, 273 CPWL_Utils::PWLColorToFXColor( 274 PWL_DEFAULT_BLACKCOLOR, nTransparancy), 275 0, FXFILL_ALTERNATE); 276 } 277 } break; 278 case PSBT_MAX: { 279 CFX_FloatPoint pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, 280 ptCenter.y); 281 CFX_FloatPoint pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 282 ptCenter.y + PWL_TRIANGLE_HALFLEN); 283 CFX_FloatPoint pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, 284 ptCenter.y - PWL_TRIANGLE_HALFLEN); 285 286 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && 287 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { 288 CFX_PathData path; 289 290 path.SetPointCount(4); 291 path.SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO); 292 path.SetPoint(1, pt2.x, pt2.y, FXPT_LINETO); 293 path.SetPoint(2, pt3.x, pt3.y, FXPT_LINETO); 294 path.SetPoint(3, pt1.x, pt1.y, FXPT_LINETO); 295 296 pDevice->DrawPath(&path, pUser2Device, nullptr, 297 CPWL_Utils::PWLColorToFXColor( 298 PWL_DEFAULT_BLACKCOLOR, nTransparancy), 299 0, FXFILL_ALTERNATE); 300 } 301 } break; 302 default: 303 break; 304 } 305 break; 306 case SBT_VSCROLL: 307 switch (m_eSBButtonType) { 308 case PSBT_MIN: { 309 // draw border 310 CFX_FloatRect rcDraw = rectWnd; 311 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 312 ArgbEncode(nTransparancy, 100, 100, 100), 313 0.0f); 314 315 // draw inner border 316 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); 317 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 318 ArgbEncode(nTransparancy, 255, 255, 255), 319 1.0f); 320 321 // draw background 322 323 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f); 324 325 if (IsEnabled()) 326 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw, 327 nTransparancy, 80, 220); 328 else 329 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, 330 ArgbEncode(255, 255, 255, 255)); 331 332 // draw arrow 333 334 if (rectWnd.top - rectWnd.bottom > 6.0f) { 335 FX_FLOAT fX = rectWnd.left + 1.5f; 336 FX_FLOAT fY = rectWnd.bottom; 337 CFX_FloatPoint pts[7] = {CFX_FloatPoint(fX + 2.5f, fY + 4.0f), 338 CFX_FloatPoint(fX + 2.5f, fY + 3.0f), 339 CFX_FloatPoint(fX + 4.5f, fY + 5.0f), 340 CFX_FloatPoint(fX + 6.5f, fY + 3.0f), 341 CFX_FloatPoint(fX + 6.5f, fY + 4.0f), 342 CFX_FloatPoint(fX + 4.5f, fY + 6.0f), 343 CFX_FloatPoint(fX + 2.5f, fY + 4.0f)}; 344 345 if (IsEnabled()) 346 CPWL_Utils::DrawFillArea( 347 pDevice, pUser2Device, pts, 7, 348 ArgbEncode(nTransparancy, 255, 255, 255)); 349 else 350 CPWL_Utils::DrawFillArea(pDevice, pUser2Device, pts, 7, 351 CPWL_Utils::PWLColorToFXColor( 352 PWL_DEFAULT_HEAVYGRAYCOLOR, 255)); 353 } 354 } break; 355 case PSBT_MAX: { 356 // draw border 357 CFX_FloatRect rcDraw = rectWnd; 358 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 359 ArgbEncode(nTransparancy, 100, 100, 100), 360 0.0f); 361 362 // draw inner border 363 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); 364 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 365 ArgbEncode(nTransparancy, 255, 255, 255), 366 1.0f); 367 368 // draw background 369 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f); 370 if (IsEnabled()) 371 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw, 372 nTransparancy, 80, 220); 373 else 374 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, 375 ArgbEncode(255, 255, 255, 255)); 376 377 // draw arrow 378 379 if (rectWnd.top - rectWnd.bottom > 6.0f) { 380 FX_FLOAT fX = rectWnd.left + 1.5f; 381 FX_FLOAT fY = rectWnd.bottom; 382 383 CFX_FloatPoint pts[7] = {CFX_FloatPoint(fX + 2.5f, fY + 5.0f), 384 CFX_FloatPoint(fX + 2.5f, fY + 6.0f), 385 CFX_FloatPoint(fX + 4.5f, fY + 4.0f), 386 CFX_FloatPoint(fX + 6.5f, fY + 6.0f), 387 CFX_FloatPoint(fX + 6.5f, fY + 5.0f), 388 CFX_FloatPoint(fX + 4.5f, fY + 3.0f), 389 CFX_FloatPoint(fX + 2.5f, fY + 5.0f)}; 390 391 if (IsEnabled()) 392 CPWL_Utils::DrawFillArea( 393 pDevice, pUser2Device, pts, 7, 394 ArgbEncode(nTransparancy, 255, 255, 255)); 395 else 396 CPWL_Utils::DrawFillArea(pDevice, pUser2Device, pts, 7, 397 CPWL_Utils::PWLColorToFXColor( 398 PWL_DEFAULT_HEAVYGRAYCOLOR, 255)); 399 } 400 } break; 401 case PSBT_POS: { 402 // draw border 403 CFX_FloatRect rcDraw = rectWnd; 404 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 405 ArgbEncode(nTransparancy, 100, 100, 100), 406 0.0f); 407 408 // draw inner border 409 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); 410 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, 411 ArgbEncode(nTransparancy, 255, 255, 255), 412 1.0f); 413 414 if (IsEnabled()) { 415 // draw shadow effect 416 417 CFX_FloatPoint ptTop = 418 CFX_FloatPoint(rectWnd.left, rectWnd.top - 1.0f); 419 CFX_FloatPoint ptBottom = 420 CFX_FloatPoint(rectWnd.left, rectWnd.bottom + 1.0f); 421 422 ptTop.x += 1.5f; 423 ptBottom.x += 1.5f; 424 425 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 426 ArgbEncode(nTransparancy, 210, 210, 210), 427 1.0f); 428 429 ptTop.x += 1.0f; 430 ptBottom.x += 1.0f; 431 432 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 433 ArgbEncode(nTransparancy, 220, 220, 220), 434 1.0f); 435 436 ptTop.x += 1.0f; 437 ptBottom.x += 1.0f; 438 439 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 440 ArgbEncode(nTransparancy, 240, 240, 240), 441 1.0f); 442 443 ptTop.x += 1.0f; 444 ptBottom.x += 1.0f; 445 446 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 447 ArgbEncode(nTransparancy, 240, 240, 240), 448 1.0f); 449 450 ptTop.x += 1.0f; 451 ptBottom.x += 1.0f; 452 453 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 454 ArgbEncode(nTransparancy, 210, 210, 210), 455 1.0f); 456 457 ptTop.x += 1.0f; 458 ptBottom.x += 1.0f; 459 460 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 461 ArgbEncode(nTransparancy, 180, 180, 180), 462 1.0f); 463 464 ptTop.x += 1.0f; 465 ptBottom.x += 1.0f; 466 467 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 468 ArgbEncode(nTransparancy, 150, 150, 150), 469 1.0f); 470 471 ptTop.x += 1.0f; 472 ptBottom.x += 1.0f; 473 474 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 475 ArgbEncode(nTransparancy, 150, 150, 150), 476 1.0f); 477 478 ptTop.x += 1.0f; 479 ptBottom.x += 1.0f; 480 481 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 482 ArgbEncode(nTransparancy, 180, 180, 180), 483 1.0f); 484 485 ptTop.x += 1.0f; 486 ptBottom.x += 1.0f; 487 488 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, 489 ArgbEncode(nTransparancy, 210, 210, 210), 490 1.0f); 491 } else { 492 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, 493 ArgbEncode(255, 255, 255, 255)); 494 } 495 496 // draw friction 497 498 if (rectWnd.Height() > 8.0f) { 499 FX_COLORREF crStroke = ArgbEncode(nTransparancy, 120, 120, 120); 500 if (!IsEnabled()) 501 crStroke = CPWL_Utils::PWLColorToFXColor( 502 PWL_DEFAULT_HEAVYGRAYCOLOR, 255); 503 504 FX_FLOAT nFrictionWidth = 5.0f; 505 FX_FLOAT nFrictionHeight = 5.5f; 506 507 CFX_FloatPoint ptLeft = 508 CFX_FloatPoint(ptCenter.x - nFrictionWidth / 2.0f, 509 ptCenter.y - nFrictionHeight / 2.0f + 0.5f); 510 CFX_FloatPoint ptRight = 511 CFX_FloatPoint(ptCenter.x + nFrictionWidth / 2.0f, 512 ptCenter.y - nFrictionHeight / 2.0f + 0.5f); 513 514 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, 515 crStroke, 1.0f); 516 517 ptLeft.y += 2.0f; 518 ptRight.y += 2.0f; 519 520 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, 521 crStroke, 1.0f); 522 523 ptLeft.y += 2.0f; 524 ptRight.y += 2.0f; 525 526 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, 527 crStroke, 1.0f); 528 } 529 } break; 530 default: 531 break; 532 } 533 break; 534 default: 535 break; 536 } 537} 538 539bool CPWL_SBButton::OnLButtonDown(const CFX_FloatPoint& point, uint32_t nFlag) { 540 CPWL_Wnd::OnLButtonDown(point, nFlag); 541 542 if (CPWL_Wnd* pParent = GetParentWindow()) 543 pParent->OnNotify(this, PNM_LBUTTONDOWN, 0, (intptr_t)&point); 544 545 m_bMouseDown = true; 546 SetCapture(); 547 548 return true; 549} 550 551bool CPWL_SBButton::OnLButtonUp(const CFX_FloatPoint& point, uint32_t nFlag) { 552 CPWL_Wnd::OnLButtonUp(point, nFlag); 553 554 if (CPWL_Wnd* pParent = GetParentWindow()) 555 pParent->OnNotify(this, PNM_LBUTTONUP, 0, (intptr_t)&point); 556 557 m_bMouseDown = false; 558 ReleaseCapture(); 559 560 return true; 561} 562 563bool CPWL_SBButton::OnMouseMove(const CFX_FloatPoint& point, uint32_t nFlag) { 564 CPWL_Wnd::OnMouseMove(point, nFlag); 565 566 if (CPWL_Wnd* pParent = GetParentWindow()) { 567 pParent->OnNotify(this, PNM_MOUSEMOVE, 0, (intptr_t)&point); 568 } 569 570 return true; 571} 572 573CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType) 574 : m_sbType(sbType), 575 m_pMinButton(nullptr), 576 m_pMaxButton(nullptr), 577 m_pPosButton(nullptr), 578 m_bMouseDown(false), 579 m_bMinOrMax(false), 580 m_bNotifyForever(true) {} 581 582CPWL_ScrollBar::~CPWL_ScrollBar() {} 583 584CFX_ByteString CPWL_ScrollBar::GetClassName() const { 585 return "CPWL_ScrollBar"; 586} 587 588void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) { 589 cp.eCursorType = FXCT_ARROW; 590} 591 592void CPWL_ScrollBar::RePosChildWnd() { 593 CFX_FloatRect rcClient = GetClientRect(); 594 CFX_FloatRect rcMinButton, rcMaxButton; 595 FX_FLOAT fBWidth = 0; 596 597 switch (m_sbType) { 598 case SBT_HSCROLL: 599 if (rcClient.right - rcClient.left > 600 PWL_SCROLLBAR_BUTTON_WIDTH * 2 + PWL_SCROLLBAR_POSBUTTON_MINWIDTH + 601 2) { 602 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, 603 rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH, 604 rcClient.top); 605 rcMaxButton = 606 CFX_FloatRect(rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH, 607 rcClient.bottom, rcClient.right, rcClient.top); 608 } else { 609 fBWidth = (rcClient.right - rcClient.left - 610 PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) / 611 2; 612 613 if (fBWidth > 0) { 614 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, 615 rcClient.left + fBWidth, rcClient.top); 616 rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom, 617 rcClient.right, rcClient.top); 618 } else { 619 SetVisible(false); 620 } 621 } 622 break; 623 case SBT_VSCROLL: 624 if (IsFloatBigger(rcClient.top - rcClient.bottom, 625 PWL_SCROLLBAR_BUTTON_WIDTH * 2 + 626 PWL_SCROLLBAR_POSBUTTON_MINWIDTH + 2)) { 627 rcMinButton = CFX_FloatRect(rcClient.left, 628 rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH, 629 rcClient.right, rcClient.top); 630 rcMaxButton = 631 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, 632 rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH); 633 } else { 634 fBWidth = (rcClient.top - rcClient.bottom - 635 PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) / 636 2; 637 638 if (IsFloatBigger(fBWidth, 0)) { 639 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth, 640 rcClient.right, rcClient.top); 641 rcMaxButton = 642 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, 643 rcClient.bottom + fBWidth); 644 } else { 645 SetVisible(false); 646 } 647 } 648 break; 649 } 650 651 if (m_pMinButton) 652 m_pMinButton->Move(rcMinButton, true, false); 653 if (m_pMaxButton) 654 m_pMaxButton->Move(rcMaxButton, true, false); 655 MovePosButton(false); 656} 657 658void CPWL_ScrollBar::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { 659 CFX_FloatRect rectWnd = GetWindowRect(); 660 661 if (IsVisible() && !rectWnd.IsEmpty()) { 662 CFX_ByteTextBuf sButton; 663 664 sButton << "q\n"; 665 sButton << "0 w\n" 666 << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true) 667 .AsStringC(); 668 sButton << rectWnd.left << " " << rectWnd.bottom << " " 669 << rectWnd.right - rectWnd.left << " " 670 << rectWnd.top - rectWnd.bottom << " re b Q\n"; 671 672 sAppStream << sButton; 673 } 674} 675 676void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice, 677 CFX_Matrix* pUser2Device) { 678 CFX_FloatRect rectWnd = GetWindowRect(); 679 680 if (IsVisible() && !rectWnd.IsEmpty()) { 681 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd, 682 GetBackgroundColor(), GetTransparency()); 683 684 CPWL_Utils::DrawStrokeLine( 685 pDevice, pUser2Device, 686 CFX_FloatPoint(rectWnd.left + 2.0f, rectWnd.top - 2.0f), 687 CFX_FloatPoint(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f), 688 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); 689 690 CPWL_Utils::DrawStrokeLine( 691 pDevice, pUser2Device, 692 CFX_FloatPoint(rectWnd.right - 2.0f, rectWnd.top - 2.0f), 693 CFX_FloatPoint(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f), 694 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); 695 } 696} 697 698bool CPWL_ScrollBar::OnLButtonDown(const CFX_FloatPoint& point, 699 uint32_t nFlag) { 700 CPWL_Wnd::OnLButtonDown(point, nFlag); 701 702 if (HasFlag(PWS_AUTOTRANSPARENT)) { 703 if (GetTransparency() != 255) { 704 SetTransparency(255); 705 InvalidateRect(); 706 } 707 } 708 709 CFX_FloatRect rcMinArea, rcMaxArea; 710 711 if (m_pPosButton && m_pPosButton->IsVisible()) { 712 CFX_FloatRect rcClient = GetClientRect(); 713 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); 714 715 switch (m_sbType) { 716 case SBT_HSCROLL: 717 rcMinArea = 718 CFX_FloatRect(rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH, 719 rcClient.bottom, rcPosButton.left, rcClient.top); 720 rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom, 721 rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH, 722 rcClient.top); 723 724 break; 725 case SBT_VSCROLL: 726 rcMinArea = 727 CFX_FloatRect(rcClient.left, rcPosButton.top, rcClient.right, 728 rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH); 729 rcMaxArea = CFX_FloatRect(rcClient.left, 730 rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH, 731 rcClient.right, rcPosButton.bottom); 732 break; 733 } 734 735 rcMinArea.Normalize(); 736 rcMaxArea.Normalize(); 737 738 if (rcMinArea.Contains(point.x, point.y)) { 739 m_sData.SubBig(); 740 MovePosButton(true); 741 NotifyScrollWindow(); 742 } 743 744 if (rcMaxArea.Contains(point.x, point.y)) { 745 m_sData.AddBig(); 746 MovePosButton(true); 747 NotifyScrollWindow(); 748 } 749 } 750 751 return true; 752} 753 754bool CPWL_ScrollBar::OnLButtonUp(const CFX_FloatPoint& point, uint32_t nFlag) { 755 CPWL_Wnd::OnLButtonUp(point, nFlag); 756 757 if (HasFlag(PWS_AUTOTRANSPARENT)) { 758 if (GetTransparency() != PWL_SCROLLBAR_TRANSPARANCY) { 759 SetTransparency(PWL_SCROLLBAR_TRANSPARANCY); 760 InvalidateRect(); 761 } 762 } 763 764 EndTimer(); 765 m_bMouseDown = false; 766 767 return true; 768} 769 770void CPWL_ScrollBar::OnNotify(CPWL_Wnd* pWnd, 771 uint32_t msg, 772 intptr_t wParam, 773 intptr_t lParam) { 774 CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); 775 776 switch (msg) { 777 case PNM_LBUTTONDOWN: 778 if (pWnd == m_pMinButton) { 779 OnMinButtonLBDown(*(CFX_FloatPoint*)lParam); 780 } 781 782 if (pWnd == m_pMaxButton) { 783 OnMaxButtonLBDown(*(CFX_FloatPoint*)lParam); 784 } 785 786 if (pWnd == m_pPosButton) { 787 OnPosButtonLBDown(*(CFX_FloatPoint*)lParam); 788 } 789 break; 790 case PNM_LBUTTONUP: 791 if (pWnd == m_pMinButton) { 792 OnMinButtonLBUp(*(CFX_FloatPoint*)lParam); 793 } 794 795 if (pWnd == m_pMaxButton) { 796 OnMaxButtonLBUp(*(CFX_FloatPoint*)lParam); 797 } 798 799 if (pWnd == m_pPosButton) { 800 OnPosButtonLBUp(*(CFX_FloatPoint*)lParam); 801 } 802 break; 803 case PNM_MOUSEMOVE: 804 if (pWnd == m_pMinButton) { 805 OnMinButtonMouseMove(*(CFX_FloatPoint*)lParam); 806 } 807 808 if (pWnd == m_pMaxButton) { 809 OnMaxButtonMouseMove(*(CFX_FloatPoint*)lParam); 810 } 811 812 if (pWnd == m_pPosButton) { 813 OnPosButtonMouseMove(*(CFX_FloatPoint*)lParam); 814 } 815 break; 816 case PNM_SETSCROLLINFO: { 817 PWL_SCROLL_INFO* pInfo = reinterpret_cast<PWL_SCROLL_INFO*>(lParam); 818 if (pInfo && *pInfo != m_OriginInfo) { 819 m_OriginInfo = *pInfo; 820 FX_FLOAT fMax = 821 pInfo->fContentMax - pInfo->fContentMin - pInfo->fPlateWidth; 822 fMax = fMax > 0.0f ? fMax : 0.0f; 823 SetScrollRange(0, fMax, pInfo->fPlateWidth); 824 SetScrollStep(pInfo->fBigStep, pInfo->fSmallStep); 825 } 826 } break; 827 case PNM_SETSCROLLPOS: { 828 FX_FLOAT fPos = *(FX_FLOAT*)lParam; 829 switch (m_sbType) { 830 case SBT_HSCROLL: 831 fPos = fPos - m_OriginInfo.fContentMin; 832 break; 833 case SBT_VSCROLL: 834 fPos = m_OriginInfo.fContentMax - fPos; 835 break; 836 } 837 SetScrollPos(fPos); 838 } break; 839 } 840} 841 842void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) { 843 PWL_CREATEPARAM scp = cp; 844 scp.pParentWnd = this; 845 scp.dwBorderWidth = 2; 846 scp.nBorderStyle = BorderStyle::BEVELED; 847 848 scp.dwFlags = 849 PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP; 850 851 if (!m_pMinButton) { 852 m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN); 853 m_pMinButton->Create(scp); 854 } 855 856 if (!m_pMaxButton) { 857 m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX); 858 m_pMaxButton->Create(scp); 859 } 860 861 if (!m_pPosButton) { 862 m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS); 863 m_pPosButton->SetVisible(false); 864 m_pPosButton->Create(scp); 865 } 866} 867 868FX_FLOAT CPWL_ScrollBar::GetScrollBarWidth() const { 869 if (!IsVisible()) 870 return 0; 871 872 return PWL_SCROLLBAR_WIDTH; 873} 874 875void CPWL_ScrollBar::SetScrollRange(FX_FLOAT fMin, 876 FX_FLOAT fMax, 877 FX_FLOAT fClientWidth) { 878 if (m_pPosButton) { 879 m_sData.SetScrollRange(fMin, fMax); 880 m_sData.SetClientWidth(fClientWidth); 881 882 if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) { 883 m_pPosButton->SetVisible(false); 884 } else { 885 m_pPosButton->SetVisible(true); 886 MovePosButton(true); 887 } 888 } 889} 890 891void CPWL_ScrollBar::SetScrollPos(FX_FLOAT fPos) { 892 FX_FLOAT fOldPos = m_sData.fScrollPos; 893 894 m_sData.SetPos(fPos); 895 896 if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) 897 MovePosButton(true); 898} 899 900void CPWL_ScrollBar::SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep) { 901 m_sData.SetBigStep(fBigStep); 902 m_sData.SetSmallStep(fSmallStep); 903} 904 905void CPWL_ScrollBar::MovePosButton(bool bRefresh) { 906 ASSERT(m_pMinButton); 907 ASSERT(m_pMaxButton); 908 909 if (m_pPosButton->IsVisible()) { 910 CFX_FloatRect rcClient; 911 CFX_FloatRect rcPosArea, rcPosButton; 912 913 rcClient = GetClientRect(); 914 rcPosArea = GetScrollArea(); 915 916 FX_FLOAT fLeft, fRight, fTop, fBottom; 917 918 switch (m_sbType) { 919 case SBT_HSCROLL: 920 fLeft = TrueToFace(m_sData.fScrollPos); 921 fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); 922 923 if (fRight - fLeft < PWL_SCROLLBAR_POSBUTTON_MINWIDTH) 924 fRight = fLeft + PWL_SCROLLBAR_POSBUTTON_MINWIDTH; 925 926 if (fRight > rcPosArea.right) { 927 fRight = rcPosArea.right; 928 fLeft = fRight - PWL_SCROLLBAR_POSBUTTON_MINWIDTH; 929 } 930 931 rcPosButton = 932 CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top); 933 934 break; 935 case SBT_VSCROLL: 936 fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); 937 fTop = TrueToFace(m_sData.fScrollPos); 938 939 if (IsFloatSmaller(fTop - fBottom, PWL_SCROLLBAR_POSBUTTON_MINWIDTH)) 940 fBottom = fTop - PWL_SCROLLBAR_POSBUTTON_MINWIDTH; 941 942 if (IsFloatSmaller(fBottom, rcPosArea.bottom)) { 943 fBottom = rcPosArea.bottom; 944 fTop = fBottom + PWL_SCROLLBAR_POSBUTTON_MINWIDTH; 945 } 946 947 rcPosButton = 948 CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop); 949 950 break; 951 } 952 953 m_pPosButton->Move(rcPosButton, true, bRefresh); 954 } 955} 956 957void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_FloatPoint& point) { 958 m_sData.SubSmall(); 959 MovePosButton(true); 960 NotifyScrollWindow(); 961 962 m_bMinOrMax = true; 963 964 EndTimer(); 965 BeginTimer(100); 966} 967 968void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_FloatPoint& point) {} 969 970void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_FloatPoint& point) {} 971 972void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_FloatPoint& point) { 973 m_sData.AddSmall(); 974 MovePosButton(true); 975 NotifyScrollWindow(); 976 977 m_bMinOrMax = false; 978 979 EndTimer(); 980 BeginTimer(100); 981} 982 983void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_FloatPoint& point) {} 984 985void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_FloatPoint& point) {} 986 987void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_FloatPoint& point) { 988 m_bMouseDown = true; 989 990 if (m_pPosButton) { 991 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); 992 993 switch (m_sbType) { 994 case SBT_HSCROLL: 995 m_nOldPos = point.x; 996 m_fOldPosButton = rcPosButton.left; 997 break; 998 case SBT_VSCROLL: 999 m_nOldPos = point.y; 1000 m_fOldPosButton = rcPosButton.top; 1001 break; 1002 } 1003 } 1004} 1005 1006void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_FloatPoint& point) { 1007 if (m_bMouseDown) { 1008 if (!m_bNotifyForever) 1009 NotifyScrollWindow(); 1010 } 1011 m_bMouseDown = false; 1012} 1013 1014void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_FloatPoint& point) { 1015 FX_FLOAT fOldScrollPos = m_sData.fScrollPos; 1016 1017 FX_FLOAT fNewPos = 0; 1018 1019 switch (m_sbType) { 1020 case SBT_HSCROLL: 1021 if (FXSYS_fabs(point.x - m_nOldPos) < 1) 1022 return; 1023 fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos); 1024 break; 1025 case SBT_VSCROLL: 1026 if (FXSYS_fabs(point.y - m_nOldPos) < 1) 1027 return; 1028 fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos); 1029 break; 1030 } 1031 1032 if (m_bMouseDown) { 1033 switch (m_sbType) { 1034 case SBT_HSCROLL: 1035 1036 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { 1037 fNewPos = m_sData.ScrollRange.fMin; 1038 } 1039 1040 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { 1041 fNewPos = m_sData.ScrollRange.fMax; 1042 } 1043 1044 m_sData.SetPos(fNewPos); 1045 1046 break; 1047 case SBT_VSCROLL: 1048 1049 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { 1050 fNewPos = m_sData.ScrollRange.fMin; 1051 } 1052 1053 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { 1054 fNewPos = m_sData.ScrollRange.fMax; 1055 } 1056 1057 m_sData.SetPos(fNewPos); 1058 1059 break; 1060 } 1061 1062 if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) { 1063 MovePosButton(true); 1064 1065 if (m_bNotifyForever) 1066 NotifyScrollWindow(); 1067 } 1068 } 1069} 1070 1071void CPWL_ScrollBar::NotifyScrollWindow() { 1072 if (CPWL_Wnd* pParent = GetParentWindow()) { 1073 FX_FLOAT fPos; 1074 switch (m_sbType) { 1075 case SBT_HSCROLL: 1076 fPos = m_OriginInfo.fContentMin + m_sData.fScrollPos; 1077 break; 1078 case SBT_VSCROLL: 1079 fPos = m_OriginInfo.fContentMax - m_sData.fScrollPos; 1080 break; 1081 } 1082 pParent->OnNotify(this, PNM_SCROLLWINDOW, (intptr_t)m_sbType, 1083 (intptr_t)&fPos); 1084 } 1085} 1086 1087CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const { 1088 CFX_FloatRect rcClient = GetClientRect(); 1089 CFX_FloatRect rcArea; 1090 1091 if (!m_pMinButton || !m_pMaxButton) 1092 return rcClient; 1093 1094 CFX_FloatRect rcMin = m_pMinButton->GetWindowRect(); 1095 CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect(); 1096 1097 FX_FLOAT fMinWidth = rcMin.right - rcMin.left; 1098 FX_FLOAT fMinHeight = rcMin.top - rcMin.bottom; 1099 FX_FLOAT fMaxWidth = rcMax.right - rcMax.left; 1100 FX_FLOAT fMaxHeight = rcMax.top - rcMax.bottom; 1101 1102 switch (m_sbType) { 1103 case SBT_HSCROLL: 1104 if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) { 1105 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, 1106 rcClient.right - fMaxWidth - 1, rcClient.top); 1107 } else { 1108 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, 1109 rcClient.left + fMinWidth + 1, rcClient.top); 1110 } 1111 break; 1112 case SBT_VSCROLL: 1113 if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) { 1114 rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, 1115 rcClient.right, rcClient.top - fMaxHeight - 1); 1116 } else { 1117 rcArea = 1118 CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, 1119 rcClient.right, rcClient.bottom + fMinHeight + 1); 1120 } 1121 break; 1122 } 1123 1124 rcArea.Normalize(); 1125 1126 return rcArea; 1127} 1128 1129FX_FLOAT CPWL_ScrollBar::TrueToFace(FX_FLOAT fTrue) { 1130 CFX_FloatRect rcPosArea; 1131 rcPosArea = GetScrollArea(); 1132 1133 FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; 1134 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; 1135 1136 FX_FLOAT fFace = 0; 1137 1138 switch (m_sbType) { 1139 case SBT_HSCROLL: 1140 fFace = rcPosArea.left + 1141 fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth; 1142 break; 1143 case SBT_VSCROLL: 1144 fFace = rcPosArea.top - 1145 fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth; 1146 break; 1147 } 1148 1149 return fFace; 1150} 1151 1152FX_FLOAT CPWL_ScrollBar::FaceToTrue(FX_FLOAT fFace) { 1153 CFX_FloatRect rcPosArea; 1154 rcPosArea = GetScrollArea(); 1155 1156 FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; 1157 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; 1158 1159 FX_FLOAT fTrue = 0; 1160 1161 switch (m_sbType) { 1162 case SBT_HSCROLL: 1163 fTrue = (fFace - rcPosArea.left) * fFactWidth / 1164 (rcPosArea.right - rcPosArea.left); 1165 break; 1166 case SBT_VSCROLL: 1167 fTrue = (rcPosArea.top - fFace) * fFactWidth / 1168 (rcPosArea.top - rcPosArea.bottom); 1169 break; 1170 } 1171 1172 return fTrue; 1173} 1174 1175void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) { 1176 CreateButtons(cp); 1177} 1178 1179void CPWL_ScrollBar::TimerProc() { 1180 PWL_SCROLL_PRIVATEDATA sTemp = m_sData; 1181 if (m_bMinOrMax) 1182 m_sData.SubSmall(); 1183 else 1184 m_sData.AddSmall(); 1185 1186 if (sTemp != m_sData) { 1187 MovePosButton(true); 1188 NotifyScrollWindow(); 1189 } 1190} 1191