Home | History | Annotate | Download | only in basewidget
      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/src/foxitlib.h"
      8 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
      9 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     11 #include "xfa/src/fwl/src/basewidget/include/fwl_pushbuttonimp.h"
     12 
     13 // static
     14 IFWL_PushButton* IFWL_PushButton::Create(
     15     const CFWL_WidgetImpProperties& properties,
     16     IFWL_Widget* pOuter) {
     17   IFWL_PushButton* pPushButton = new IFWL_PushButton;
     18   CFWL_PushButtonImp* pPushButtonImpl =
     19       new CFWL_PushButtonImp(properties, pOuter);
     20   pPushButton->SetImpl(pPushButtonImpl);
     21   pPushButtonImpl->SetInterface(pPushButton);
     22   return pPushButton;
     23 }
     24 IFWL_PushButton::IFWL_PushButton() {
     25 }
     26 
     27 CFWL_PushButtonImp::CFWL_PushButtonImp(
     28     const CFWL_WidgetImpProperties& properties,
     29     IFWL_Widget* pOuter)
     30     : CFWL_WidgetImp(properties, pOuter),
     31       m_bBtnDown(FALSE),
     32       m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
     33       m_iTTOAlign(FDE_TTOALIGNMENT_Center) {
     34   m_rtClient.Set(0, 0, 0, 0);
     35   m_rtCaption.Set(0, 0, 0, 0);
     36 }
     37 CFWL_PushButtonImp::~CFWL_PushButtonImp() {}
     38 FWL_ERR CFWL_PushButtonImp::GetClassName(CFX_WideString& wsClass) const {
     39   wsClass = FWL_CLASS_PushButton;
     40   return FWL_ERR_Succeeded;
     41 }
     42 FX_DWORD CFWL_PushButtonImp::GetClassID() const {
     43   return FWL_CLASSHASH_PushButton;
     44 }
     45 FWL_ERR CFWL_PushButtonImp::Initialize() {
     46   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
     47     return FWL_ERR_Indefinite;
     48   m_pDelegate = new CFWL_PushButtonImpDelegate(this);
     49   return FWL_ERR_Succeeded;
     50 }
     51 FWL_ERR CFWL_PushButtonImp::Finalize() {
     52   delete m_pDelegate;
     53   m_pDelegate = nullptr;
     54   return CFWL_WidgetImp::Finalize();
     55 }
     56 FWL_ERR CFWL_PushButtonImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
     57   if (bAutoSize) {
     58     rect.Set(0, 0, 0, 0);
     59     if (m_pProperties->m_pThemeProvider == NULL) {
     60       m_pProperties->m_pThemeProvider = GetAvailableTheme();
     61     }
     62     CFX_WideString wsCaption;
     63     IFWL_PushButtonDP* pData =
     64         static_cast<IFWL_PushButtonDP*>(m_pProperties->m_pDataProvider);
     65     if (pData) {
     66       pData->GetCaption(m_pInterface, wsCaption);
     67     }
     68     int32_t iLen = wsCaption.GetLength();
     69     if (iLen > 0) {
     70       CFX_SizeF sz = CalcTextSize(wsCaption, m_pProperties->m_pThemeProvider);
     71       rect.Set(0, 0, sz.x, sz.y);
     72     }
     73     FX_FLOAT* fcaption =
     74         static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_PSB_Margin));
     75     rect.Inflate(*fcaption, *fcaption);
     76     CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
     77   } else {
     78     rect = m_pProperties->m_rtWidget;
     79   }
     80   return FWL_ERR_Succeeded;
     81 }
     82 FWL_ERR CFWL_PushButtonImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
     83   if ((dwStates & FWL_WGTSTATE_Disabled) && bSet) {
     84     m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled;
     85     return FWL_ERR_Succeeded;
     86   }
     87   return CFWL_WidgetImp::SetStates(dwStates, bSet);
     88 }
     89 FWL_ERR CFWL_PushButtonImp::Update() {
     90   if (IsLocked()) {
     91     return FWL_ERR_Indefinite;
     92   }
     93   if (!m_pProperties->m_pThemeProvider) {
     94     m_pProperties->m_pThemeProvider = GetAvailableTheme();
     95   }
     96   UpdateTextOutStyles();
     97   GetClientRect(m_rtClient);
     98   m_rtCaption = m_rtClient;
     99   FX_FLOAT* fcaption =
    100       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_PSB_Margin));
    101   m_rtCaption.Inflate(-*fcaption, -*fcaption);
    102   return FWL_ERR_Succeeded;
    103 }
    104 FWL_ERR CFWL_PushButtonImp::DrawWidget(CFX_Graphics* pGraphics,
    105                                        const CFX_Matrix* pMatrix) {
    106   if (!pGraphics)
    107     return FWL_ERR_Indefinite;
    108   if (!m_pProperties->m_pThemeProvider)
    109     return FWL_ERR_Indefinite;
    110   IFWL_PushButtonDP* pData =
    111       static_cast<IFWL_PushButtonDP*>(m_pProperties->m_pDataProvider);
    112   CFX_DIBitmap* pPicture = NULL;
    113   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    114   if (HasBorder()) {
    115     DrawBorder(pGraphics, FWL_PART_PSB_Border, m_pProperties->m_pThemeProvider,
    116                pMatrix);
    117   }
    118   if (HasEdge()) {
    119     DrawEdge(pGraphics, FWL_PART_PSB_Edge, m_pProperties->m_pThemeProvider,
    120              pMatrix);
    121   }
    122   DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix);
    123   CFX_Matrix matrix;
    124   matrix.Concat(*pMatrix);
    125   FX_FLOAT iPicwidth = 0;
    126   FX_FLOAT ipicheight = 0;
    127   CFX_WideString wsCaption;
    128   if (pData) {
    129     pData->GetCaption(m_pInterface, wsCaption);
    130   }
    131   CFX_RectF rtText;
    132   rtText.Set(0, 0, 0, 0);
    133   if (!wsCaption.IsEmpty()) {
    134     CalcTextRect(wsCaption, pTheme, 0, m_iTTOAlign, rtText);
    135   }
    136   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_PSB_ModeMask) {
    137     case FWL_STYLEEXT_PSB_TextOnly:
    138       DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix);
    139       break;
    140     case FWL_STYLEEXT_PSB_IconOnly:
    141       if (pData) {
    142         pPicture = pData->GetPicture(m_pInterface);
    143       }
    144       if (pPicture) {
    145         CFX_PointF point;
    146         switch (m_iTTOAlign) {
    147           case 0: {
    148             point.x = m_rtClient.left;
    149             point.y = m_rtClient.top;
    150             break;
    151           }
    152           case 1: {
    153             point.x = m_rtClient.left +
    154                       (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
    155             point.y = m_rtClient.top;
    156             break;
    157           }
    158           case 2:
    159             point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
    160             point.y = m_rtClient.top;
    161             break;
    162           case 4:
    163             point.x = m_rtClient.left;
    164             point.y = m_rtClient.top + m_rtClient.height / 2 -
    165                       pPicture->GetHeight() / 2;
    166             break;
    167           case 5:
    168             point.x = m_rtClient.left +
    169                       (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
    170             point.y = m_rtClient.top + m_rtClient.height / 2 -
    171                       pPicture->GetHeight() / 2;
    172             break;
    173           case 6:
    174             point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
    175             point.y = m_rtClient.top + m_rtClient.height / 2 -
    176                       pPicture->GetHeight() / 2;
    177             break;
    178           case 8:
    179             point.x = m_rtClient.left;
    180             point.y =
    181                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    182             break;
    183           case 9:
    184             point.x = m_rtClient.left +
    185                       (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
    186             point.y =
    187                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    188             break;
    189           case 10:
    190             point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
    191             point.y =
    192                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    193             break;
    194         }
    195         pGraphics->DrawImage(pPicture, point, &matrix);
    196       }
    197       break;
    198     case FWL_STYLEEXT_PSB_TextIcon:
    199       if (pPicture) {
    200         CFX_PointF point;
    201         switch (m_iTTOAlign) {
    202           case 0: {
    203             point.x = m_rtClient.left;
    204             point.y = m_rtClient.top;
    205             iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7);
    206             ipicheight =
    207                 pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
    208             break;
    209           }
    210           case 1: {
    211             point.x =
    212                 m_rtClient.left + (m_rtClient.width / 2 -
    213                                    (pPicture->GetWidth() + rtText.width) / 2);
    214             point.y = m_rtClient.top;
    215             iPicwidth = pPicture->GetWidth() -
    216                         ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
    217                         rtText.width / 2 - 7;
    218             ipicheight =
    219                 pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
    220             break;
    221           }
    222           case 2:
    223             point.x = m_rtClient.left + m_rtClient.width -
    224                       pPicture->GetWidth() - rtText.width;
    225             point.y = m_rtClient.top;
    226             iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
    227                         pPicture->GetWidth() - rtText.width + 7;
    228             ipicheight =
    229                 pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
    230             break;
    231           case 4:
    232             point.x = m_rtClient.left;
    233             point.y = m_rtClient.top + m_rtClient.height / 2 -
    234                       pPicture->GetHeight() / 2;
    235             iPicwidth = m_rtClient.left + pPicture->GetWidth() - 7;
    236             break;
    237           case 5:
    238             point.x =
    239                 m_rtClient.left + (m_rtClient.width / 2 -
    240                                    (pPicture->GetWidth() + rtText.width) / 2);
    241             point.y = m_rtClient.top + m_rtClient.height / 2 -
    242                       pPicture->GetHeight() / 2;
    243             iPicwidth = pPicture->GetWidth() -
    244                         ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
    245                         rtText.width / 2 - 7;
    246             break;
    247           case 6:
    248             point.x = m_rtClient.left + m_rtClient.width -
    249                       pPicture->GetWidth() - rtText.width;
    250             point.y = m_rtClient.top + m_rtClient.height / 2 -
    251                       pPicture->GetHeight() / 2;
    252             iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
    253                         pPicture->GetWidth() - rtText.width + 7;
    254             break;
    255           case 8:
    256             point.x = m_rtClient.left;
    257             point.y =
    258                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    259             iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7);
    260             ipicheight -= rtText.height / 2;
    261             break;
    262           case 9:
    263             point.x =
    264                 m_rtClient.left + (m_rtClient.width / 2 -
    265                                    (pPicture->GetWidth() + rtText.width) / 2);
    266             point.y =
    267                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    268             iPicwidth = pPicture->GetWidth() -
    269                         ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
    270                         rtText.width / 2 - 7;
    271             ipicheight -= rtText.height / 2;
    272             break;
    273           case 10:
    274             point.x = m_rtClient.left + m_rtClient.width -
    275                       pPicture->GetWidth() - rtText.width;
    276             point.y =
    277                 m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
    278             iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
    279                         pPicture->GetWidth() - rtText.width + 7;
    280             ipicheight -= rtText.height / 2;
    281             break;
    282         }
    283         pGraphics->DrawImage(pPicture, point, &matrix);
    284       }
    285       matrix.e += m_rtClient.left + iPicwidth;
    286       matrix.f += m_rtClient.top + ipicheight;
    287       DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix);
    288       break;
    289   }
    290   return FWL_ERR_Succeeded;
    291 }
    292 void CFWL_PushButtonImp::DrawBkground(CFX_Graphics* pGraphics,
    293                                       IFWL_ThemeProvider* pTheme,
    294                                       const CFX_Matrix* pMatrix) {
    295   CFWL_ThemeBackground param;
    296   param.m_pWidget = m_pInterface;
    297   param.m_iPart = FWL_PART_PSB_Background;
    298   param.m_dwStates = GetPartStates();
    299   param.m_pGraphics = pGraphics;
    300   if (pMatrix) {
    301     param.m_matrix.Concat(*pMatrix);
    302   }
    303   param.m_rtPart = m_rtClient;
    304   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
    305     param.m_pData = &m_rtCaption;
    306   }
    307   pTheme->DrawBackground(&param);
    308 }
    309 void CFWL_PushButtonImp::DrawText(CFX_Graphics* pGraphics,
    310                                   IFWL_ThemeProvider* pTheme,
    311                                   const CFX_Matrix* pMatrix) {
    312   if (!m_pProperties->m_pDataProvider)
    313     return;
    314   CFX_WideString wsCaption;
    315   m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption);
    316   if (wsCaption.IsEmpty()) {
    317     return;
    318   }
    319   CFWL_ThemeText param;
    320   param.m_pWidget = m_pInterface;
    321   param.m_iPart = FWL_PART_PSB_Caption;
    322   param.m_dwStates = GetPartStates();
    323   param.m_pGraphics = pGraphics;
    324   if (pMatrix) {
    325     param.m_matrix.Concat(*pMatrix);
    326   }
    327   param.m_rtPart = m_rtCaption;
    328   param.m_wsText = wsCaption;
    329   param.m_dwTTOStyles = m_dwTTOStyles;
    330   param.m_iTTOAlign = m_iTTOAlign;
    331   pTheme->DrawText(&param);
    332 }
    333 FX_DWORD CFWL_PushButtonImp::GetPartStates() {
    334   FX_DWORD dwStates = FWL_PARTSTATE_PSB_Normal;
    335   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
    336     dwStates |= FWL_PARTSTATE_PSB_Focused;
    337   }
    338   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
    339     dwStates = FWL_PARTSTATE_PSB_Disabled;
    340   } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
    341     dwStates |= FWL_PARTSTATE_PSB_Pressed;
    342   } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
    343     dwStates |= FWL_PARTSTATE_PSB_Hovered;
    344   } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Default) {
    345     dwStates |= FWL_PARTSTATE_PSB_Default;
    346   }
    347   return dwStates;
    348 }
    349 void CFWL_PushButtonImp::UpdateTextOutStyles() {
    350   m_iTTOAlign = FDE_TTOALIGNMENT_Center;
    351   switch (m_pProperties->m_dwStyleExes &
    352           (FWL_STYLEEXT_PSB_HLayoutMask | FWL_STYLEEXT_PSB_VLayoutMask)) {
    353     case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Top: {
    354       m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
    355       break;
    356     }
    357     case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Top: {
    358       m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;
    359       break;
    360     }
    361     case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Top: {
    362       m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;
    363       break;
    364     }
    365     case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_VCenter: {
    366       m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
    367       break;
    368     }
    369     case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_VCenter: {
    370       m_iTTOAlign = FDE_TTOALIGNMENT_Center;
    371       break;
    372     }
    373     case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_VCenter: {
    374       m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;
    375       break;
    376     }
    377     case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Bottom: {
    378       m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;
    379       break;
    380     }
    381     case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Bottom: {
    382       m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;
    383       break;
    384     }
    385     case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Bottom: {
    386       m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;
    387       break;
    388     }
    389     default: {}
    390   }
    391   m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
    392   if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) {
    393     m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
    394   }
    395 }
    396 CFWL_PushButtonImpDelegate::CFWL_PushButtonImpDelegate(
    397     CFWL_PushButtonImp* pOwner)
    398     : m_pOwner(pOwner) {}
    399 int32_t CFWL_PushButtonImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
    400   if (!pMessage)
    401     return 0;
    402   if (!m_pOwner->IsEnabled()) {
    403     return 1;
    404   }
    405   int32_t iRet = 1;
    406   FX_DWORD dwMsgCode = pMessage->GetClassID();
    407   switch (dwMsgCode) {
    408     case FWL_MSGHASH_SetFocus:
    409     case FWL_MSGHASH_KillFocus: {
    410       OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
    411       break;
    412     }
    413     case FWL_MSGHASH_Mouse: {
    414       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
    415       FX_DWORD dwCmd = pMsg->m_dwCmd;
    416       switch (dwCmd) {
    417         case FWL_MSGMOUSECMD_LButtonDown: {
    418           OnLButtonDown(pMsg);
    419           break;
    420         }
    421         case FWL_MSGMOUSECMD_LButtonUp: {
    422           OnLButtonUp(pMsg);
    423           break;
    424         }
    425         case FWL_MSGMOUSECMD_MouseMove: {
    426           OnMouseMove(pMsg);
    427           break;
    428         }
    429         case FWL_MSGMOUSECMD_MouseLeave: {
    430           OnMouseLeave(pMsg);
    431           break;
    432         }
    433         default: {}
    434       }
    435       break;
    436     }
    437     case FWL_MSGHASH_Key: {
    438       CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
    439       if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {
    440         OnKeyDown(pKey);
    441       }
    442       break;
    443     }
    444     default: {
    445       iRet = 0;
    446       break;
    447     }
    448   }
    449   CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
    450   return iRet;
    451 }
    452 FWL_ERR CFWL_PushButtonImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
    453   return FWL_ERR_Succeeded;
    454 }
    455 FWL_ERR CFWL_PushButtonImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
    456                                                  const CFX_Matrix* pMatrix) {
    457   return m_pOwner->DrawWidget(pGraphics, pMatrix);
    458 }
    459 void CFWL_PushButtonImpDelegate::OnFocusChanged(CFWL_Message* pMsg,
    460                                                 FX_BOOL bSet) {
    461   if (bSet) {
    462     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
    463   } else {
    464     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    465   }
    466   m_pOwner->Repaint(&m_pOwner->m_rtClient);
    467 }
    468 void CFWL_PushButtonImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
    469   if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
    470     m_pOwner->SetFocus(TRUE);
    471   }
    472   m_pOwner->m_bBtnDown = TRUE;
    473   m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
    474   m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
    475   m_pOwner->Repaint(&m_pOwner->m_rtClient);
    476 }
    477 void CFWL_PushButtonImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
    478   m_pOwner->m_bBtnDown = FALSE;
    479   if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    480     m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
    481     m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
    482   } else {
    483     m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
    484     m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
    485   }
    486   if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    487     CFWL_EvtClick wmClick;
    488     wmClick.m_pSrcTarget = m_pOwner->m_pInterface;
    489     m_pOwner->DispatchEvent(&wmClick);
    490   }
    491   m_pOwner->Repaint(&m_pOwner->m_rtClient);
    492 }
    493 void CFWL_PushButtonImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
    494   FX_BOOL bRepaint = FALSE;
    495   if (m_pOwner->m_bBtnDown) {
    496     if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    497       if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
    498         m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
    499         bRepaint = TRUE;
    500       }
    501       if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
    502         m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
    503         bRepaint = TRUE;
    504       }
    505     } else {
    506       if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
    507         m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
    508         bRepaint = TRUE;
    509       }
    510       if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
    511         m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
    512         bRepaint = TRUE;
    513       }
    514     }
    515   } else {
    516     if (!m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    517       return;
    518     }
    519     if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
    520       m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
    521       bRepaint = TRUE;
    522     }
    523   }
    524   if (bRepaint) {
    525     m_pOwner->Repaint(&m_pOwner->m_rtClient);
    526   }
    527 }
    528 void CFWL_PushButtonImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) {
    529   m_pOwner->m_bBtnDown = FALSE;
    530   m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
    531   m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
    532   m_pOwner->Repaint(&m_pOwner->m_rtClient);
    533 }
    534 void CFWL_PushButtonImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) {
    535   if (pMsg->m_dwKeyCode == FWL_VKEY_Return) {
    536     CFWL_EvtMouse wmMouse;
    537     wmMouse.m_pSrcTarget = m_pOwner->m_pInterface;
    538     wmMouse.m_dwCmd = FWL_MSGMOUSECMD_LButtonUp;
    539     m_pOwner->DispatchEvent(&wmMouse);
    540     CFWL_EvtClick wmClick;
    541     wmClick.m_pSrcTarget = m_pOwner->m_pInterface;
    542     m_pOwner->DispatchEvent(&wmClick);
    543     return;
    544   }
    545   if (pMsg->m_dwKeyCode != FWL_VKEY_Tab) {
    546     return;
    547   }
    548   m_pOwner->DispatchKeyEvent(pMsg);
    549 }
    550