cfwl_widget.cpp revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
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 "xfa/fwl/cfwl_widget.h" 8 9#include <algorithm> 10#include <utility> 11#include <vector> 12 13#include "third_party/base/stl_util.h" 14#include "xfa/fde/tto/fde_textout.h" 15#include "xfa/fwl/cfwl_app.h" 16#include "xfa/fwl/cfwl_combobox.h" 17#include "xfa/fwl/cfwl_event.h" 18#include "xfa/fwl/cfwl_eventmouse.h" 19#include "xfa/fwl/cfwl_form.h" 20#include "xfa/fwl/cfwl_messagekey.h" 21#include "xfa/fwl/cfwl_messagekillfocus.h" 22#include "xfa/fwl/cfwl_messagemouse.h" 23#include "xfa/fwl/cfwl_messagemousewheel.h" 24#include "xfa/fwl/cfwl_messagesetfocus.h" 25#include "xfa/fwl/cfwl_notedriver.h" 26#include "xfa/fwl/cfwl_themebackground.h" 27#include "xfa/fwl/cfwl_themepart.h" 28#include "xfa/fwl/cfwl_themetext.h" 29#include "xfa/fwl/cfwl_widgetmgr.h" 30#include "xfa/fwl/ifwl_themeprovider.h" 31#include "xfa/fxfa/xfa_ffapp.h" 32 33#define FWL_STYLEEXT_MNU_Vert (1L << 0) 34#define FWL_WGT_CalcHeight 2048 35#define FWL_WGT_CalcWidth 2048 36#define FWL_WGT_CalcMultiLineDefWidth 120.0f 37 38CFWL_Widget::CFWL_Widget(const CFWL_App* app, 39 std::unique_ptr<CFWL_WidgetProperties> properties, 40 CFWL_Widget* pOuter) 41 : m_pOwnerApp(app), 42 m_pWidgetMgr(app->GetWidgetMgr()), 43 m_pProperties(std::move(properties)), 44 m_pOuter(pOuter), 45 m_iLock(0), 46 m_pLayoutItem(nullptr), 47 m_nEventKey(0), 48 m_pDelegate(nullptr) { 49 ASSERT(m_pWidgetMgr); 50 51 CFWL_Widget* pParent = m_pProperties->m_pParent; 52 m_pWidgetMgr->InsertWidget(pParent, this); 53 if (IsChild()) 54 return; 55 56 CFWL_Widget* pOwner = m_pProperties->m_pOwner; 57 if (pOwner) 58 m_pWidgetMgr->SetOwner(pOwner, this); 59} 60 61CFWL_Widget::~CFWL_Widget() { 62 NotifyDriver(); 63 m_pWidgetMgr->RemoveWidget(this); 64} 65 66bool CFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const { 67 return false; 68} 69 70CFX_RectF CFWL_Widget::GetAutosizedWidgetRect() { 71 return CFX_RectF(); 72} 73 74CFX_RectF CFWL_Widget::GetWidgetRect() { 75 return m_pProperties->m_rtWidget; 76} 77 78void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) { 79 if (HasBorder()) { 80 FX_FLOAT fBorder = GetBorderSize(true); 81 rect.Inflate(fBorder, fBorder); 82 } 83} 84 85void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) { 86 m_pProperties->m_rtWidget = rect; 87} 88 89CFX_RectF CFWL_Widget::GetClientRect() { 90 return GetEdgeRect(); 91} 92 93void CFWL_Widget::SetParent(CFWL_Widget* pParent) { 94 m_pProperties->m_pParent = pParent; 95 m_pWidgetMgr->SetParent(pParent, this); 96} 97 98uint32_t CFWL_Widget::GetStyles() const { 99 return m_pProperties->m_dwStyles; 100} 101 102void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded, 103 uint32_t dwStylesRemoved) { 104 m_pProperties->m_dwStyles = 105 (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded; 106} 107 108uint32_t CFWL_Widget::GetStylesEx() const { 109 return m_pProperties->m_dwStyleExes; 110} 111uint32_t CFWL_Widget::GetStates() const { 112 return m_pProperties->m_dwStates; 113} 114 115void CFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded, 116 uint32_t dwStylesExRemoved) { 117 m_pProperties->m_dwStyleExes = 118 (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded; 119} 120 121static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr, 122 CFWL_Widget* widget, 123 CFWL_NoteDriver* noteDriver) { 124 CFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget); 125 while (child) { 126 noteDriver->NotifyTargetHide(child); 127 NotifyHideChildWidget(widgetMgr, child, noteDriver); 128 child = widgetMgr->GetNextSiblingWidget(child); 129 } 130} 131 132void CFWL_Widget::SetStates(uint32_t dwStates) { 133 m_pProperties->m_dwStates |= dwStates; 134 if (!(dwStates & FWL_WGTSTATE_Invisible)) 135 return; 136 137 CFWL_NoteDriver* noteDriver = 138 static_cast<CFWL_NoteDriver*>(GetOwnerApp()->GetNoteDriver()); 139 CFWL_WidgetMgr* widgetMgr = GetOwnerApp()->GetWidgetMgr(); 140 noteDriver->NotifyTargetHide(this); 141 CFWL_Widget* child = widgetMgr->GetFirstChildWidget(this); 142 while (child) { 143 noteDriver->NotifyTargetHide(child); 144 NotifyHideChildWidget(widgetMgr, child, noteDriver); 145 child = widgetMgr->GetNextSiblingWidget(child); 146 } 147 return; 148} 149 150void CFWL_Widget::RemoveStates(uint32_t dwStates) { 151 m_pProperties->m_dwStates &= ~dwStates; 152} 153 154FWL_WidgetHit CFWL_Widget::HitTest(const CFX_PointF& point) { 155 if (GetClientRect().Contains(point)) 156 return FWL_WidgetHit::Client; 157 if (HasBorder() && GetRelativeRect().Contains(point)) 158 return FWL_WidgetHit::Border; 159 return FWL_WidgetHit::Unknown; 160} 161 162CFX_PointF CFWL_Widget::TransformTo(CFWL_Widget* pWidget, 163 const CFX_PointF& point) { 164 if (m_pWidgetMgr->IsFormDisabled()) { 165 CFX_SizeF szOffset; 166 if (IsParent(pWidget)) { 167 szOffset = GetOffsetFromParent(pWidget); 168 } else { 169 szOffset = pWidget->GetOffsetFromParent(this); 170 szOffset.width = -szOffset.width; 171 szOffset.height = -szOffset.height; 172 } 173 return point + CFX_PointF(szOffset.width, szOffset.height); 174 } 175 176 CFX_PointF ret = point; 177 CFWL_Widget* parent = GetParent(); 178 if (parent) 179 ret = GetMatrix().Transform(ret + GetWidgetRect().TopLeft()); 180 181 CFWL_Widget* form1 = m_pWidgetMgr->GetSystemFormWidget(this); 182 if (!form1) 183 return ret; 184 185 if (!pWidget) 186 return ret + form1->GetWidgetRect().TopLeft(); 187 188 CFWL_Widget* form2 = m_pWidgetMgr->GetSystemFormWidget(pWidget); 189 if (!form2) 190 return ret; 191 if (form1 != form2) { 192 ret += form1->GetWidgetRect().TopLeft(); 193 ret -= form2->GetWidgetRect().TopLeft(); 194 } 195 196 parent = pWidget->GetParent(); 197 if (!parent) 198 return ret; 199 200 CFX_Matrix m; 201 m.SetReverse(pWidget->GetMatrix()); 202 return m.Transform(ret) - pWidget->GetWidgetRect().TopLeft(); 203} 204 205CFX_Matrix CFWL_Widget::GetMatrix() { 206 if (!m_pProperties) 207 return CFX_Matrix(); 208 209 CFWL_Widget* parent = GetParent(); 210 std::vector<CFWL_Widget*> parents; 211 while (parent) { 212 parents.push_back(parent); 213 parent = parent->GetParent(); 214 } 215 216 CFX_Matrix matrix; 217 CFX_Matrix ctmOnParent; 218 CFX_RectF rect; 219 int32_t count = pdfium::CollectionSize<int32_t>(parents); 220 for (int32_t i = count - 2; i >= 0; i--) { 221 parent = parents[i]; 222 if (parent->m_pProperties) 223 ctmOnParent.SetIdentity(); 224 rect = parent->GetWidgetRect(); 225 matrix.Concat(ctmOnParent, true); 226 matrix.Translate(rect.left, rect.top, true); 227 } 228 CFX_Matrix m; 229 m.SetIdentity(); 230 matrix.Concat(m, true); 231 parents.clear(); 232 return matrix; 233} 234 235IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const { 236 return m_pProperties->m_pThemeProvider; 237} 238 239void CFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { 240 m_pProperties->m_pThemeProvider = pThemeProvider; 241} 242 243bool CFWL_Widget::IsEnabled() const { 244 return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0; 245} 246 247bool CFWL_Widget::HasBorder() const { 248 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border); 249} 250 251bool CFWL_Widget::IsVisible() const { 252 return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0; 253} 254 255bool CFWL_Widget::IsOverLapper() const { 256 return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) == 257 FWL_WGTSTYLE_OverLapper; 258} 259 260bool CFWL_Widget::IsPopup() const { 261 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup); 262} 263 264bool CFWL_Widget::IsChild() const { 265 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child); 266} 267 268CFX_RectF CFWL_Widget::GetEdgeRect() { 269 CFX_RectF rtEdge(0, 0, m_pProperties->m_rtWidget.width, 270 m_pProperties->m_rtWidget.height); 271 if (HasBorder()) { 272 FX_FLOAT fCX = GetBorderSize(true); 273 FX_FLOAT fCY = GetBorderSize(false); 274 rtEdge.Deflate(fCX, fCY); 275 } 276 return rtEdge; 277} 278 279FX_FLOAT CFWL_Widget::GetBorderSize(bool bCX) { 280 IFWL_ThemeProvider* theme = GetAvailableTheme(); 281 if (!theme) 282 return 0.0f; 283 return bCX ? theme->GetCXBorderSize() : theme->GetCYBorderSize(); 284} 285 286CFX_RectF CFWL_Widget::GetRelativeRect() { 287 return CFX_RectF(0, 0, m_pProperties->m_rtWidget.width, 288 m_pProperties->m_rtWidget.height); 289} 290 291IFWL_ThemeProvider* CFWL_Widget::GetAvailableTheme() { 292 if (m_pProperties->m_pThemeProvider) 293 return m_pProperties->m_pThemeProvider; 294 295 CFWL_Widget* pUp = this; 296 do { 297 pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup) 298 ? m_pWidgetMgr->GetOwnerWidget(pUp) 299 : m_pWidgetMgr->GetParentWidget(pUp); 300 if (pUp) { 301 IFWL_ThemeProvider* pRet = pUp->GetThemeProvider(); 302 if (pRet) 303 return pRet; 304 } 305 } while (pUp); 306 return nullptr; 307} 308 309CFWL_Widget* CFWL_Widget::GetRootOuter() { 310 CFWL_Widget* pRet = m_pOuter; 311 if (!pRet) 312 return nullptr; 313 314 while (CFWL_Widget* pOuter = pRet->GetOuter()) 315 pRet = pOuter; 316 return pRet; 317} 318 319CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText, 320 IFWL_ThemeProvider* pTheme, 321 bool bMultiLine) { 322 if (!pTheme) 323 return CFX_SizeF(); 324 325 CFWL_ThemeText calPart; 326 calPart.m_pWidget = this; 327 calPart.m_wsText = wsText; 328 calPart.m_dwTTOStyles = 329 bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine; 330 calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; 331 FX_FLOAT fWidth = 332 bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth; 333 CFX_RectF rect(0, 0, fWidth, FWL_WGT_CalcHeight); 334 pTheme->CalcTextRect(&calPart, rect); 335 return CFX_SizeF(rect.width, rect.height); 336} 337 338void CFWL_Widget::CalcTextRect(const CFX_WideString& wsText, 339 IFWL_ThemeProvider* pTheme, 340 uint32_t dwTTOStyles, 341 int32_t iTTOAlign, 342 CFX_RectF& rect) { 343 CFWL_ThemeText calPart; 344 calPart.m_pWidget = this; 345 calPart.m_wsText = wsText; 346 calPart.m_dwTTOStyles = dwTTOStyles; 347 calPart.m_iTTOAlign = iTTOAlign; 348 pTheme->CalcTextRect(&calPart, rect); 349} 350 351void CFWL_Widget::SetFocus(bool bFocus) { 352 if (m_pWidgetMgr->IsFormDisabled()) 353 return; 354 355 const CFWL_App* pApp = GetOwnerApp(); 356 if (!pApp) 357 return; 358 359 CFWL_NoteDriver* pDriver = 360 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); 361 if (!pDriver) 362 return; 363 364 CFWL_Widget* curFocus = pDriver->GetFocus(); 365 if (bFocus && curFocus != this) 366 pDriver->SetFocus(this); 367 else if (!bFocus && curFocus == this) 368 pDriver->SetFocus(nullptr); 369} 370 371void CFWL_Widget::SetGrab(bool bSet) { 372 const CFWL_App* pApp = GetOwnerApp(); 373 if (!pApp) 374 return; 375 376 CFWL_NoteDriver* pDriver = 377 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); 378 pDriver->SetGrab(this, bSet); 379} 380 381void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight, 382 FX_FLOAT fMaxHeight, 383 const CFX_RectF& rtAnchor, 384 CFX_RectF& rtPopup) { 385 if (GetClassID() == FWL_Type::ComboBox) { 386 if (m_pWidgetMgr->IsFormDisabled()) { 387 m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor, 388 rtPopup); 389 return; 390 } 391 GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup); 392 return; 393 } 394 if (GetClassID() == FWL_Type::DateTimePicker && 395 m_pWidgetMgr->IsFormDisabled()) { 396 m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor, 397 rtPopup); 398 return; 399 } 400 GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup); 401} 402 403bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight, 404 FX_FLOAT fMaxHeight, 405 const CFX_RectF& rtAnchor, 406 CFX_RectF& rtPopup) { 407 if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) { 408 bool bLeft = m_pProperties->m_rtWidget.left < 0; 409 FX_FLOAT fRight = rtAnchor.right() + rtPopup.width; 410 CFX_PointF point = TransformTo(nullptr, CFX_PointF()); 411 if (fRight + point.x > 0.0f || bLeft) { 412 rtPopup = CFX_RectF(rtAnchor.left - rtPopup.width, rtAnchor.top, 413 rtPopup.width, rtPopup.height); 414 } else { 415 rtPopup = CFX_RectF(rtAnchor.right(), rtAnchor.top, rtPopup.width, 416 rtPopup.height); 417 } 418 rtPopup.Offset(point.x, point.y); 419 return true; 420 } 421 422 FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height; 423 CFX_PointF point = TransformTo(nullptr, point); 424 if (fBottom + point.y > 0.0f) { 425 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height, 426 rtPopup.width, rtPopup.height); 427 } else { 428 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width, 429 rtPopup.height); 430 } 431 rtPopup.Offset(point.x, point.y); 432 return true; 433} 434 435bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight, 436 FX_FLOAT fMaxHeight, 437 const CFX_RectF& rtAnchor, 438 CFX_RectF& rtPopup) { 439 FX_FLOAT fPopHeight = rtPopup.height; 440 if (rtPopup.height > fMaxHeight) 441 fPopHeight = fMaxHeight; 442 else if (rtPopup.height < fMinHeight) 443 fPopHeight = fMinHeight; 444 445 FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width); 446 FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight; 447 CFX_PointF point = TransformTo(nullptr, CFX_PointF()); 448 if (fBottom + point.y > 0.0f) { 449 rtPopup = 450 CFX_RectF(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight); 451 } else { 452 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight); 453 } 454 455 rtPopup.Offset(point.x, point.y); 456 return true; 457} 458 459bool CFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight, 460 FX_FLOAT fMaxHeight, 461 const CFX_RectF& rtAnchor, 462 CFX_RectF& rtPopup) { 463 CFX_PointF point = TransformTo(nullptr, CFX_PointF()); 464 if (rtAnchor.bottom() + point.y > 0.0f) { 465 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height, 466 rtPopup.width, rtPopup.height); 467 } else { 468 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width, 469 rtPopup.height); 470 } 471 rtPopup.Offset(point.x, point.y); 472 return true; 473} 474 475void CFWL_Widget::RegisterEventTarget(CFWL_Widget* pEventSource) { 476 const CFWL_App* pApp = GetOwnerApp(); 477 if (!pApp) 478 return; 479 480 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver(); 481 if (!pNoteDriver) 482 return; 483 484 pNoteDriver->RegisterEventTarget(this, pEventSource); 485} 486 487void CFWL_Widget::UnregisterEventTarget() { 488 const CFWL_App* pApp = GetOwnerApp(); 489 if (!pApp) 490 return; 491 492 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver(); 493 if (!pNoteDriver) 494 return; 495 496 pNoteDriver->UnregisterEventTarget(this); 497} 498 499void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) { 500 if (m_pOuter) { 501 m_pOuter->GetDelegate()->OnProcessEvent(pEvent); 502 return; 503 } 504 const CFWL_App* pApp = GetOwnerApp(); 505 if (!pApp) 506 return; 507 508 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver(); 509 if (!pNoteDriver) 510 return; 511 pNoteDriver->SendEvent(pEvent); 512} 513 514void CFWL_Widget::Repaint() { 515 RepaintRect(CFX_RectF(0, 0, m_pProperties->m_rtWidget.width, 516 m_pProperties->m_rtWidget.height)); 517} 518 519void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) { 520 m_pWidgetMgr->RepaintWidget(this, pRect); 521} 522 523void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics, 524 CFWL_Part iPartBk, 525 IFWL_ThemeProvider* pTheme, 526 const CFX_Matrix* pMatrix) { 527 CFWL_ThemeBackground param; 528 param.m_pWidget = this; 529 param.m_iPart = iPartBk; 530 param.m_pGraphics = pGraphics; 531 if (pMatrix) 532 param.m_matrix.Concat(*pMatrix, true); 533 param.m_rtPart = GetRelativeRect(); 534 pTheme->DrawBackground(¶m); 535} 536 537void CFWL_Widget::DrawBorder(CFX_Graphics* pGraphics, 538 CFWL_Part iPartBorder, 539 IFWL_ThemeProvider* pTheme, 540 const CFX_Matrix* pMatrix) { 541 CFWL_ThemeBackground param; 542 param.m_pWidget = this; 543 param.m_iPart = iPartBorder; 544 param.m_pGraphics = pGraphics; 545 if (pMatrix) 546 param.m_matrix.Concat(*pMatrix, true); 547 param.m_rtPart = GetRelativeRect(); 548 pTheme->DrawBackground(¶m); 549} 550 551void CFWL_Widget::NotifyDriver() { 552 const CFWL_App* pApp = GetOwnerApp(); 553 if (!pApp) 554 return; 555 556 CFWL_NoteDriver* pDriver = 557 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); 558 if (!pDriver) 559 return; 560 561 pDriver->NotifyTargetDestroy(this); 562} 563 564CFX_SizeF CFWL_Widget::GetOffsetFromParent(CFWL_Widget* pParent) { 565 if (pParent == this) 566 return CFX_SizeF(); 567 568 CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr(); 569 if (!pWidgetMgr) 570 return CFX_SizeF(); 571 572 CFX_SizeF szRet(m_pProperties->m_rtWidget.left, 573 m_pProperties->m_rtWidget.top); 574 575 CFWL_Widget* pDstWidget = GetParent(); 576 while (pDstWidget && pDstWidget != pParent) { 577 CFX_RectF rtDst = pDstWidget->GetWidgetRect(); 578 szRet += CFX_SizeF(rtDst.left, rtDst.top); 579 pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget); 580 } 581 return szRet; 582} 583 584bool CFWL_Widget::IsParent(CFWL_Widget* pParent) { 585 CFWL_Widget* pUpWidget = GetParent(); 586 while (pUpWidget) { 587 if (pUpWidget == pParent) 588 return true; 589 pUpWidget = pUpWidget->GetParent(); 590 } 591 return false; 592} 593 594void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) { 595 if (!pMessage->m_pDstTarget) 596 return; 597 598 CFWL_Widget* pWidget = pMessage->m_pDstTarget; 599 switch (pMessage->GetType()) { 600 case CFWL_Message::Type::Mouse: { 601 CFWL_MessageMouse* pMsgMouse = static_cast<CFWL_MessageMouse*>(pMessage); 602 603 CFWL_EventMouse evt(pWidget, pWidget); 604 evt.m_dwCmd = pMsgMouse->m_dwCmd; 605 pWidget->DispatchEvent(&evt); 606 break; 607 } 608 default: 609 break; 610 } 611} 612 613void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {} 614 615void CFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics, 616 const CFX_Matrix* pMatrix) {} 617