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_threadimp.h"
      9 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_panelimp.h"
     14 #include "xfa/src/fwl/src/core/include/fwl_formimp.h"
     15 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
     16 #include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h"
     17 #include "xfa/src/fwl/src/basewidget/include/fwl_editimp.h"
     18 #include "xfa/src/fwl/src/basewidget/include/fwl_listboximp.h"
     19 #include "xfa/src/fwl/src/basewidget/include/fwl_formproxyimp.h"
     20 #include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h"
     21 
     22 // static
     23 IFWL_ComboBox* IFWL_ComboBox::Create(
     24     const CFWL_WidgetImpProperties& properties) {
     25   IFWL_ComboBox* pComboBox = new IFWL_ComboBox;
     26   CFWL_ComboBoxImp* pComboBoxImpl = new CFWL_ComboBoxImp(properties, nullptr);
     27   pComboBox->SetImpl(pComboBoxImpl);
     28   pComboBoxImpl->SetInterface(pComboBox);
     29   return pComboBox;
     30 }
     31 IFWL_ComboBox::IFWL_ComboBox() {}
     32 int32_t IFWL_ComboBox::GetCurSel() {
     33   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetCurSel();
     34 }
     35 FWL_ERR IFWL_ComboBox::SetCurSel(int32_t iSel) {
     36   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetCurSel(iSel);
     37 }
     38 FWL_ERR IFWL_ComboBox::SetEditText(const CFX_WideString& wsText) {
     39   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditText(wsText);
     40 }
     41 int32_t IFWL_ComboBox::GetEditTextLength() const {
     42   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditTextLength();
     43 }
     44 FWL_ERR IFWL_ComboBox::GetEditText(CFX_WideString& wsText,
     45                                    int32_t nStart,
     46                                    int32_t nCount) const {
     47   return static_cast<CFWL_ComboBoxImp*>(GetImpl())
     48       ->GetEditText(wsText, nStart, nCount);
     49 }
     50 FWL_ERR IFWL_ComboBox::SetEditSelRange(int32_t nStart, int32_t nCount) {
     51   return static_cast<CFWL_ComboBoxImp*>(GetImpl())
     52       ->SetEditSelRange(nStart, nCount);
     53 }
     54 int32_t IFWL_ComboBox::GetEditSelRange(int32_t nIndex, int32_t& nStart) {
     55   return static_cast<CFWL_ComboBoxImp*>(GetImpl())
     56       ->GetEditSelRange(nIndex, nStart);
     57 }
     58 int32_t IFWL_ComboBox::GetEditLimit() {
     59   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditLimit();
     60 }
     61 FWL_ERR IFWL_ComboBox::SetEditLimit(int32_t nLimit) {
     62   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditLimit(nLimit);
     63 }
     64 FWL_ERR IFWL_ComboBox::EditDoClipboard(int32_t iCmd) {
     65   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDoClipboard(iCmd);
     66 }
     67 FX_BOOL IFWL_ComboBox::EditRedo(const CFX_ByteStringC& bsRecord) {
     68   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(bsRecord);
     69 }
     70 FX_BOOL IFWL_ComboBox::EditUndo(const CFX_ByteStringC& bsRecord) {
     71   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(bsRecord);
     72 }
     73 IFWL_ListBox* IFWL_ComboBox::GetListBoxt() {
     74   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetListBoxt();
     75 }
     76 FX_BOOL IFWL_ComboBox::AfterFocusShowDropList() {
     77   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->AfterFocusShowDropList();
     78 }
     79 FX_ERR IFWL_ComboBox::OpenDropDownList(FX_BOOL bActivate) {
     80   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->OpenDropDownList(bActivate);
     81 }
     82 FX_BOOL IFWL_ComboBox::EditCanUndo() {
     83   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanUndo();
     84 }
     85 FX_BOOL IFWL_ComboBox::EditCanRedo() {
     86   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanRedo();
     87 }
     88 FX_BOOL IFWL_ComboBox::EditUndo() {
     89   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo();
     90 }
     91 FX_BOOL IFWL_ComboBox::EditRedo() {
     92   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo();
     93 }
     94 FX_BOOL IFWL_ComboBox::EditCanCopy() {
     95   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCopy();
     96 }
     97 FX_BOOL IFWL_ComboBox::EditCanCut() {
     98   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCut();
     99 }
    100 FX_BOOL IFWL_ComboBox::EditCanSelectAll() {
    101   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanSelectAll();
    102 }
    103 FX_BOOL IFWL_ComboBox::EditCopy(CFX_WideString& wsCopy) {
    104   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCopy(wsCopy);
    105 }
    106 FX_BOOL IFWL_ComboBox::EditCut(CFX_WideString& wsCut) {
    107   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCut(wsCut);
    108 }
    109 FX_BOOL IFWL_ComboBox::EditPaste(const CFX_WideString& wsPaste) {
    110   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditPaste(wsPaste);
    111 }
    112 FX_BOOL IFWL_ComboBox::EditSelectAll() {
    113   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditSelectAll();
    114 }
    115 FX_BOOL IFWL_ComboBox::EditDelete() {
    116   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDelete();
    117 }
    118 FX_BOOL IFWL_ComboBox::EditDeSelect() {
    119   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDeSelect();
    120 }
    121 FWL_ERR IFWL_ComboBox::GetBBox(CFX_RectF& rect) {
    122   return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetBBox(rect);
    123 }
    124 FWL_ERR IFWL_ComboBox::EditModifyStylesEx(FX_DWORD dwStylesExAdded,
    125                                           FX_DWORD dwStylesExRemoved) {
    126   return static_cast<CFWL_ComboBoxImp*>(GetImpl())
    127       ->EditModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
    128 }
    129 
    130 CFWL_ComboEditImp::CFWL_ComboEditImp(const CFWL_WidgetImpProperties& properties,
    131                                      IFWL_Widget* pOuter)
    132     : CFWL_EditImp(properties, pOuter) {
    133   m_pOuter = static_cast<CFWL_ComboBoxImp*>(pOuter->GetImpl());
    134 }
    135 
    136 CFWL_ComboEditImpDelegate::CFWL_ComboEditImpDelegate(CFWL_ComboEditImp* pOwner)
    137     : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {
    138 }
    139 int32_t CFWL_ComboEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
    140   if (!pMessage)
    141     return 0;
    142   FX_DWORD dwMsgCode = pMessage->GetClassID();
    143   FX_BOOL backDefault = TRUE;
    144   switch (dwMsgCode) {
    145     case FWL_MSGHASH_SetFocus:
    146     case FWL_MSGHASH_KillFocus: {
    147       if (dwMsgCode == FWL_MSGHASH_SetFocus) {
    148         m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
    149       } else {
    150         m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    151       }
    152       backDefault = FALSE;
    153       break;
    154     }
    155     case FWL_MSGHASH_Mouse: {
    156       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
    157       if ((pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) &&
    158           ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)) {
    159         m_pOwner->SetSelected();
    160         m_pOwner->SetComboBoxFocus(TRUE);
    161       }
    162       break;
    163     }
    164     default: {}
    165   }
    166   if (!backDefault) {
    167     return 1;
    168   }
    169   return CFWL_EditImpDelegate::OnProcessMessage(pMessage);
    170 }
    171 void CFWL_ComboEditImp::ClearSelected() {
    172   ClearSelections();
    173   Repaint(&m_rtClient);
    174 }
    175 void CFWL_ComboEditImp::SetSelected() {
    176   FlagFocus(TRUE);
    177   EndCaret();
    178   AddSelRange(0);
    179 }
    180 void CFWL_ComboEditImp::EndCaret() {
    181   m_pEdtEngine->MoveCaretPos(MC_End);
    182 }
    183 void CFWL_ComboEditImp::FlagFocus(FX_BOOL bSet) {
    184   if (bSet) {
    185     m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
    186   } else {
    187     m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    188     ShowCaret(FALSE);
    189   }
    190 };
    191 void CFWL_ComboEditImp::SetComboBoxFocus(FX_BOOL bSet) {
    192   m_pOuter->SetFocus(bSet);
    193 }
    194 CFWL_ComboListImp::CFWL_ComboListImp(const CFWL_WidgetImpProperties& properties,
    195                                      IFWL_Widget* pOuter)
    196     : CFWL_ListBoxImp(properties, pOuter), m_bNotifyOwner(TRUE) {
    197   FXSYS_assert(pOuter != NULL);
    198 }
    199 FWL_ERR CFWL_ComboListImp::Initialize() {
    200   if (CFWL_ListBoxImp::Initialize() != FWL_ERR_Succeeded)
    201     return FWL_ERR_Indefinite;
    202   delete m_pDelegate;
    203   m_pDelegate = new CFWL_ComboListImpDelegate(this);
    204   return FWL_ERR_Succeeded;
    205 }
    206 FWL_ERR CFWL_ComboListImp::Finalize() {
    207   delete m_pDelegate;
    208   m_pDelegate = nullptr;
    209   return CFWL_ListBoxImp::Finalize();
    210 }
    211 int32_t CFWL_ComboListImp::MatchItem(const CFX_WideString& wsMatch) {
    212   if (wsMatch.IsEmpty()) {
    213     return -1;
    214   }
    215   if (!m_pProperties->m_pDataProvider)
    216     return -1;
    217   IFWL_ListBoxDP* pData =
    218       static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
    219   int32_t iCount = pData->CountItems(m_pInterface);
    220   for (int32_t i = 0; i < iCount; i++) {
    221     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
    222     CFX_WideString wsText;
    223     pData->GetItemText(m_pInterface, hItem, wsText);
    224     FX_STRSIZE pos = wsText.Find(wsMatch.c_str());
    225     if (!pos) {
    226       return i;
    227     }
    228   }
    229   return -1;
    230 }
    231 void CFWL_ComboListImp::ChangeSelected(int32_t iSel) {
    232   if (!m_pProperties->m_pDataProvider)
    233     return;
    234   IFWL_ListBoxDP* pData =
    235       static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
    236   FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);
    237   CFX_RectF rtInvalidate;
    238   rtInvalidate.Reset();
    239   FWL_HLISTITEM hOld = GetSelItem(0);
    240   int32_t iOld = pData->GetItemIndex(m_pInterface, hOld);
    241   if (iOld == iSel) {
    242     return;
    243   } else if (iOld > -1) {
    244     GetItemRect(iOld, rtInvalidate);
    245     SetSelItem(hOld, FALSE);
    246   }
    247   if (hItem) {
    248     CFX_RectF rect;
    249     GetItemRect(iSel, rect);
    250     rtInvalidate.Union(rect);
    251     FWL_HLISTITEM hSel = pData->GetItem(m_pInterface, iSel);
    252     SetSelItem(hSel, TRUE);
    253   }
    254   if (!rtInvalidate.IsEmpty()) {
    255     Repaint(&rtInvalidate);
    256   }
    257 }
    258 int32_t CFWL_ComboListImp::CountItems() {
    259   IFWL_ListBoxDP* pData =
    260       static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
    261   return pData ? pData->CountItems(m_pInterface) : 0;
    262 }
    263 void CFWL_ComboListImp::GetItemRect(int32_t nIndex, CFX_RectF& rtItem) {
    264   IFWL_ListBoxDP* pData =
    265       static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
    266   FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, nIndex);
    267   pData->GetItemRect(m_pInterface, hItem, rtItem);
    268 }
    269 void CFWL_ComboListImp::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) {
    270   fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top;
    271   IFWL_Widget* pOwner = GetOwner();
    272   if (!pOwner)
    273     return;
    274   pOwner->TransformTo(m_pOuter, fx, fy);
    275 }
    276 void CFWL_ComboListImp::SetFocus(FX_BOOL bSet) {
    277   CFWL_WidgetImp::SetFocus(bSet);
    278 }
    279 CFWL_ComboListImpDelegate::CFWL_ComboListImpDelegate(CFWL_ComboListImp* pOwner)
    280     : CFWL_ListBoxImpDelegate(pOwner), m_pOwner(pOwner) {
    281 }
    282 int32_t CFWL_ComboListImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
    283   if (!pMessage)
    284     return 0;
    285   FX_DWORD dwHashCode = pMessage->GetClassID();
    286   FX_BOOL backDefault = TRUE;
    287   if (dwHashCode == FWL_MSGHASH_SetFocus ||
    288       dwHashCode == FWL_MSGHASH_KillFocus) {
    289     OnDropListFocusChanged(pMessage, dwHashCode == FWL_MSGHASH_SetFocus);
    290   } else if (dwHashCode == FWL_MSGHASH_Mouse) {
    291     CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
    292     if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
    293       CFX_RectF rect;
    294       m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
    295       if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
    296         pMsg->m_fx -= rect.left;
    297         pMsg->m_fy -= rect.top;
    298         IFWL_WidgetDelegate* pDelegate =
    299             m_pOwner->m_pVertScrollBar->SetDelegate(NULL);
    300         return pDelegate->OnProcessMessage(pMsg);
    301       }
    302     }
    303     FX_DWORD dwCmd = pMsg->m_dwCmd;
    304     switch (dwCmd) {
    305       case FWL_MSGMOUSECMD_MouseMove: {
    306         backDefault = FALSE;
    307         OnDropListMouseMove(pMsg);
    308         break;
    309       }
    310       case FWL_MSGMOUSECMD_LButtonDown: {
    311         backDefault = FALSE;
    312         OnDropListLButtonDown(pMsg);
    313         break;
    314       }
    315       case FWL_MSGMOUSECMD_LButtonUp: {
    316         backDefault = FALSE;
    317         OnDropListLButtonUp(pMsg);
    318         break;
    319       }
    320       default: {}
    321     }
    322   } else if (dwHashCode == FWL_MSGHASH_Key) {
    323     backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage));
    324   }
    325   if (!backDefault) {
    326     return 1;
    327   }
    328   return CFWL_ListBoxImpDelegate::OnProcessMessage(pMessage);
    329 }
    330 void CFWL_ComboListImpDelegate::OnDropListFocusChanged(CFWL_Message* pMsg,
    331                                                        FX_BOOL bSet) {
    332   if (!bSet) {
    333     CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg);
    334     CFWL_ComboBoxImp* pOuter =
    335         static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    336     if (pKill->m_pSetFocus == m_pOwner->m_pOuter ||
    337         pKill->m_pSetFocus == pOuter->m_pEdit.get()) {
    338       pOuter->ShowDropList(FALSE);
    339     }
    340   }
    341 }
    342 int32_t CFWL_ComboListImpDelegate::OnDropListMouseMove(CFWL_MsgMouse* pMsg) {
    343   if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    344     if (m_pOwner->m_bNotifyOwner) {
    345       m_pOwner->m_bNotifyOwner = FALSE;
    346     }
    347     if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
    348       CFX_RectF rect;
    349       m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
    350       if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
    351         return 1;
    352       }
    353     }
    354     FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
    355     if (hItem) {
    356       if (!m_pOwner->m_pProperties->m_pDataProvider)
    357         return 0;
    358       IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
    359           m_pOwner->m_pProperties->m_pDataProvider);
    360       int32_t iSel = pData->GetItemIndex(m_pOwner->m_pInterface, hItem);
    361       CFWL_EvtCmbHoverChanged event;
    362       event.m_pSrcTarget = m_pOwner->m_pOuter;
    363       event.m_iCurHover = iSel;
    364       m_pOwner->DispatchEvent(&event);
    365       m_pOwner->ChangeSelected(iSel);
    366     }
    367   } else if (m_pOwner->m_bNotifyOwner) {
    368     m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);
    369     CFWL_ComboBoxImp* pOuter =
    370         static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    371     pOuter->m_pDelegate->OnProcessMessage(pMsg);
    372   }
    373   return 1;
    374 }
    375 int32_t CFWL_ComboListImpDelegate::OnDropListLButtonDown(CFWL_MsgMouse* pMsg) {
    376   if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    377     return 0;
    378   }
    379   CFWL_ComboBoxImp* pOuter =
    380       static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    381   pOuter->ShowDropList(FALSE);
    382   return 1;
    383 }
    384 int32_t CFWL_ComboListImpDelegate::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) {
    385   CFWL_ComboBoxImp* pOuter =
    386       static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    387   if (m_pOwner->m_bNotifyOwner) {
    388     m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);
    389     pOuter->m_pDelegate->OnProcessMessage(pMsg);
    390   } else {
    391     if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
    392       CFX_RectF rect;
    393       m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
    394       if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
    395         return 1;
    396       }
    397     }
    398     pOuter->ShowDropList(FALSE);
    399     FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
    400     if (hItem) {
    401       pOuter->ProcessSelChanged(TRUE);
    402     }
    403   }
    404   return 1;
    405 }
    406 int32_t CFWL_ComboListImpDelegate::OnDropListKey(CFWL_MsgKey* pKey) {
    407   CFWL_ComboBoxImp* pOuter =
    408       static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    409   FX_BOOL bPropagate = FALSE;
    410   if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {
    411     FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
    412     switch (dwKeyCode) {
    413       case FWL_VKEY_Return:
    414       case FWL_VKEY_Escape: {
    415         pOuter->ShowDropList(FALSE);
    416         return 1;
    417       }
    418       case FWL_VKEY_Up:
    419       case FWL_VKEY_Down: {
    420         OnDropListKeyDown(pKey);
    421         pOuter->SetDelegate(nullptr);
    422         pOuter->ProcessSelChanged(FALSE);
    423         return 1;
    424       }
    425       default: { bPropagate = TRUE; }
    426     }
    427   } else if (pKey->m_dwCmd == FWL_MSGKEYCMD_Char) {
    428     bPropagate = TRUE;
    429   }
    430   if (bPropagate) {
    431     pKey->m_pDstTarget = m_pOwner->m_pOuter;
    432     pOuter->m_pDelegate->OnProcessMessage(pKey);
    433     return 1;
    434   }
    435   return 0;
    436 }
    437 void CFWL_ComboListImpDelegate::OnDropListKeyDown(CFWL_MsgKey* pKey) {
    438   FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
    439   switch (dwKeyCode) {
    440     case FWL_VKEY_Up:
    441     case FWL_VKEY_Down:
    442     case FWL_VKEY_Home:
    443     case FWL_VKEY_End: {
    444       CFWL_ComboBoxImp* pOuter =
    445           static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    446       IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
    447           m_pOwner->m_pProperties->m_pDataProvider);
    448       FWL_HLISTITEM hItem =
    449           pData->GetItem(m_pOwner->m_pInterface, pOuter->m_iCurSel);
    450       hItem = m_pOwner->GetItem(hItem, dwKeyCode);
    451       if (!hItem) {
    452         break;
    453       }
    454       m_pOwner->SetSelection(hItem, hItem, TRUE);
    455       m_pOwner->ScrollToVisible(hItem);
    456       CFX_RectF rtInvalidate;
    457       rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width,
    458                        m_pOwner->m_pProperties->m_rtWidget.height);
    459       m_pOwner->Repaint(&rtInvalidate);
    460       break;
    461     }
    462     default: {}
    463   }
    464 }
    465 CFWL_ComboBoxImp::CFWL_ComboBoxImp(const CFWL_WidgetImpProperties& properties,
    466                                    IFWL_Widget* pOuter)
    467     : CFWL_WidgetImp(properties, pOuter),
    468       m_pForm(NULL),
    469       m_bLButtonDown(FALSE),
    470       m_iCurSel(-1),
    471       m_iBtnState(FWL_PARTSTATE_CMB_Normal),
    472       m_fComboFormHandler(0),
    473       m_bNeedShowList(FALSE) {
    474   m_rtClient.Reset();
    475   m_rtBtn.Reset();
    476   m_rtHandler.Reset();
    477 }
    478 CFWL_ComboBoxImp::~CFWL_ComboBoxImp() {
    479 }
    480 FWL_ERR CFWL_ComboBoxImp::GetClassName(CFX_WideString& wsClass) const {
    481   wsClass = FWL_CLASS_ComboBox;
    482   return FWL_ERR_Succeeded;
    483 }
    484 FX_DWORD CFWL_ComboBoxImp::GetClassID() const {
    485   return FWL_CLASSHASH_ComboBox;
    486 }
    487 FWL_ERR CFWL_ComboBoxImp::Initialize() {
    488   if (m_pWidgetMgr->IsFormDisabled()) {
    489     return DisForm_Initialize();
    490   }
    491   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
    492     return FWL_WGTSTATE_Invisible;  // Probably a bug; not a FWL_ERR_ value.
    493   m_pDelegate = new CFWL_ComboBoxImpDelegate(this);
    494   CFWL_WidgetImpProperties prop;
    495   prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
    496   prop.m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
    497   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) {
    498     prop.m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon;
    499   }
    500   prop.m_pDataProvider = m_pProperties->m_pDataProvider;
    501   m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface));
    502   m_pListBox->Initialize();
    503   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) {
    504     CFWL_WidgetImpProperties prop2;
    505     m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop2, m_pInterface));
    506     m_pEdit->Initialize();
    507     static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
    508   }
    509   if (m_pEdit) {
    510     m_pEdit->SetParent(m_pInterface);
    511   }
    512   SetStates(m_pProperties->m_dwStates);
    513   return FWL_ERR_Succeeded;
    514 }
    515 FWL_ERR CFWL_ComboBoxImp::Finalize() {
    516   if (m_pEdit) {
    517     m_pEdit->Finalize();
    518   }
    519   m_pListBox->Finalize();
    520   delete m_pDelegate;
    521   m_pDelegate = nullptr;
    522   return CFWL_WidgetImp::Finalize();
    523 }
    524 FWL_ERR CFWL_ComboBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
    525   if (bAutoSize) {
    526     rect.Reset();
    527     FX_BOOL bIsDropDown = IsDropDownStyle();
    528     if (bIsDropDown && m_pEdit) {
    529       m_pEdit->GetWidgetRect(rect, TRUE);
    530     } else {
    531       rect.width = 100;
    532       rect.height = 16;
    533     }
    534     if (!m_pProperties->m_pThemeProvider) {
    535       ReSetTheme();
    536     }
    537     FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
    538         GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
    539     if (!pFWidth)
    540       return FWL_ERR_Indefinite;
    541     rect.Inflate(0, 0, *pFWidth, 0);
    542     CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
    543   } else {
    544     rect = m_pProperties->m_rtWidget;
    545   }
    546   return FWL_ERR_Succeeded;
    547 }
    548 FWL_ERR CFWL_ComboBoxImp::ModifyStylesEx(FX_DWORD dwStylesExAdded,
    549                                          FX_DWORD dwStylesExRemoved) {
    550   if (m_pWidgetMgr->IsFormDisabled()) {
    551     return DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
    552   }
    553   FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;
    554   FX_BOOL bRemoveDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;
    555   if (bAddDropDown && !m_pEdit) {
    556     CFWL_WidgetImpProperties prop;
    557     m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, nullptr));
    558     m_pEdit->Initialize();
    559     static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
    560     m_pEdit->SetParent(m_pInterface);
    561   } else if (bRemoveDropDown && m_pEdit) {
    562     m_pEdit->SetStates(FWL_WGTSTATE_Invisible, TRUE);
    563   }
    564   return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
    565 }
    566 FWL_ERR CFWL_ComboBoxImp::Update() {
    567   if (m_pWidgetMgr->IsFormDisabled()) {
    568     return DisForm_Update();
    569   }
    570   if (IsLocked()) {
    571     return FWL_ERR_Indefinite;
    572   }
    573   ReSetTheme();
    574   FX_BOOL bDropDown = IsDropDownStyle();
    575   if (bDropDown && m_pEdit) {
    576     ReSetEditAlignment();
    577   }
    578   if (m_pProperties->m_pThemeProvider == NULL) {
    579     m_pProperties->m_pThemeProvider = GetAvailableTheme();
    580   }
    581   Layout();
    582   CFWL_ThemePart part;
    583   part.m_pWidget = m_pInterface;
    584   m_fComboFormHandler =
    585       *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity(
    586           &part, FWL_WGTCAPACITY_CMB_ComboFormHandler));
    587   return FWL_ERR_Succeeded;
    588 }
    589 FX_DWORD CFWL_ComboBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
    590   if (m_pWidgetMgr->IsFormDisabled()) {
    591     return DisForm_HitTest(fx, fy);
    592   }
    593   return CFWL_WidgetImp::HitTest(fx, fy);
    594 }
    595 FWL_ERR CFWL_ComboBoxImp::DrawWidget(CFX_Graphics* pGraphics,
    596                                      const CFX_Matrix* pMatrix) {
    597   if (m_pWidgetMgr->IsFormDisabled()) {
    598     return DisForm_DrawWidget(pGraphics, pMatrix);
    599   }
    600   if (!pGraphics)
    601     return FWL_ERR_Indefinite;
    602   if (!m_pProperties->m_pThemeProvider)
    603     return FWL_ERR_Indefinite;
    604   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    605   FX_BOOL bIsDropDown = IsDropDownStyle();
    606   if (HasBorder()) {
    607     DrawBorder(pGraphics, FWL_PART_CMB_Border, pTheme, pMatrix);
    608   }
    609   if (HasEdge()) {
    610     DrawEdge(pGraphics, FWL_PART_CMB_Edge, pTheme, pMatrix);
    611   }
    612   if (!bIsDropDown) {
    613     CFX_RectF rtTextBk(m_rtClient);
    614     rtTextBk.width -= m_rtBtn.width;
    615     CFWL_ThemeBackground param;
    616     param.m_pWidget = m_pInterface;
    617     param.m_iPart = FWL_PART_CMB_Background;
    618     param.m_pGraphics = pGraphics;
    619     if (pMatrix) {
    620       param.m_matrix.Concat(*pMatrix);
    621     }
    622     param.m_rtPart = rtTextBk;
    623     if (m_iCurSel >= 0) {
    624       IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
    625           static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    626               ->m_pProperties->m_pDataProvider);
    627       void* p = pData->GetItemData(m_pListBox.get(),
    628                                    pData->GetItem(m_pListBox.get(), m_iCurSel));
    629       if (p != NULL) {
    630         param.m_pData = p;
    631       }
    632     }
    633     if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
    634       param.m_dwStates = FWL_PARTSTATE_CMB_Disabled;
    635     } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
    636                (m_iCurSel >= 0)) {
    637       param.m_dwStates = FWL_PARTSTATE_CMB_Selected;
    638     } else {
    639       param.m_dwStates = FWL_PARTSTATE_CMB_Normal;
    640     }
    641     pTheme->DrawBackground(&param);
    642     if (m_iCurSel >= 0) {
    643       if (!m_pListBox)
    644         return FWL_ERR_Indefinite;
    645       CFX_WideString wsText;
    646       IFWL_ComboBoxDP* pData =
    647           static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    648       FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
    649       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    650           ->GetItemText(hItem, wsText);
    651       CFWL_ThemeText param;
    652       param.m_pWidget = m_pInterface;
    653       param.m_iPart = FWL_PART_CMB_Caption;
    654       param.m_dwStates = m_iBtnState;
    655       param.m_pGraphics = pGraphics;
    656       param.m_matrix.Concat(*pMatrix);
    657       param.m_rtPart = rtTextBk;
    658       param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
    659                              ? FWL_PARTSTATE_CMB_Selected
    660                              : FWL_PARTSTATE_CMB_Normal;
    661       param.m_wsText = wsText;
    662       param.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
    663       param.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
    664       pTheme->DrawText(&param);
    665     }
    666   }
    667   {
    668     CFWL_ThemeBackground param;
    669     param.m_pWidget = m_pInterface;
    670     param.m_iPart = FWL_PART_CMB_DropDownButton;
    671     param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
    672                            ? FWL_PARTSTATE_CMB_Disabled
    673                            : m_iBtnState;
    674     param.m_pGraphics = pGraphics;
    675     param.m_matrix.Concat(*pMatrix);
    676     param.m_rtPart = m_rtBtn;
    677     pTheme->DrawBackground(&param);
    678   }
    679   return FWL_ERR_Succeeded;
    680 }
    681 FWL_ERR CFWL_ComboBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
    682   if (!pThemeProvider)
    683     return FWL_ERR_Indefinite;
    684   m_pProperties->m_pThemeProvider = pThemeProvider;
    685   if (m_pListBox && pThemeProvider->IsValidWidget(m_pListBox.get())) {
    686     m_pListBox->SetThemeProvider(pThemeProvider);
    687   }
    688   if (m_pEdit && pThemeProvider->IsValidWidget(m_pEdit.get())) {
    689     m_pEdit->SetThemeProvider(pThemeProvider);
    690   }
    691   return FWL_ERR_Succeeded;
    692 }
    693 int32_t CFWL_ComboBoxImp::GetCurSel() {
    694   return m_iCurSel;
    695 }
    696 FWL_ERR CFWL_ComboBoxImp::SetCurSel(int32_t iSel) {
    697   int32_t iCount =
    698       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->CountItems();
    699   FX_BOOL bClearSel = iSel < 0 || iSel >= iCount;
    700   FX_BOOL bDropDown = IsDropDownStyle();
    701   if (bDropDown && m_pEdit) {
    702     if (bClearSel) {
    703       m_pEdit->SetText(CFX_WideString());
    704     } else {
    705       CFX_WideString wsText;
    706       IFWL_ComboBoxDP* pData =
    707           static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    708       FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);
    709       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    710           ->GetItemText(hItem, wsText);
    711       m_pEdit->SetText(wsText);
    712     }
    713     m_pEdit->Update();
    714   }
    715   m_iCurSel = bClearSel ? -1 : iSel;
    716   return FWL_ERR_Succeeded;
    717 }
    718 FWL_ERR CFWL_ComboBoxImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
    719   FX_BOOL bIsDropDown = IsDropDownStyle();
    720   if (bIsDropDown && m_pEdit) {
    721     m_pEdit->SetStates(dwStates, bSet);
    722   }
    723   if (m_pListBox) {
    724     m_pListBox->SetStates(dwStates, bSet);
    725   }
    726   return CFWL_WidgetImp::SetStates(dwStates, bSet);
    727 }
    728 FWL_ERR CFWL_ComboBoxImp::SetEditText(const CFX_WideString& wsText) {
    729   if (!m_pEdit)
    730     return FWL_ERR_Indefinite;
    731   m_pEdit->SetText(wsText);
    732   return m_pEdit->Update();
    733 }
    734 int32_t CFWL_ComboBoxImp::GetEditTextLength() const {
    735   if (!m_pEdit)
    736     return -1;
    737   return m_pEdit->GetTextLength();
    738 }
    739 FWL_ERR CFWL_ComboBoxImp::GetEditText(CFX_WideString& wsText,
    740                                       int32_t nStart,
    741                                       int32_t nCount) const {
    742   if (m_pEdit) {
    743     return m_pEdit->GetText(wsText, nStart, nCount);
    744   } else if (m_pListBox) {
    745     IFWL_ComboBoxDP* pData =
    746         static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    747     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
    748     return m_pListBox->GetItemText(hItem, wsText);
    749   }
    750   return FWL_ERR_Indefinite;
    751 }
    752 FWL_ERR CFWL_ComboBoxImp::SetEditSelRange(int32_t nStart, int32_t nCount) {
    753   if (!m_pEdit)
    754     return FWL_ERR_Indefinite;
    755   static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->ClearSelected();
    756   m_pEdit->AddSelRange(nStart, nCount);
    757   return FWL_ERR_Succeeded;
    758 }
    759 int32_t CFWL_ComboBoxImp::GetEditSelRange(int32_t nIndex, int32_t& nStart) {
    760   if (!m_pEdit)
    761     return -1;
    762   return m_pEdit->GetSelRange(nIndex, nStart);
    763 }
    764 int32_t CFWL_ComboBoxImp::GetEditLimit() {
    765   if (!m_pEdit)
    766     return -1;
    767   return m_pEdit->GetLimit();
    768 }
    769 FWL_ERR CFWL_ComboBoxImp::SetEditLimit(int32_t nLimit) {
    770   if (!m_pEdit)
    771     return FWL_ERR_Indefinite;
    772   return m_pEdit->SetLimit(nLimit);
    773 }
    774 FWL_ERR CFWL_ComboBoxImp::EditDoClipboard(int32_t iCmd) {
    775   if (!m_pEdit)
    776     return FWL_ERR_Indefinite;
    777   return m_pEdit->DoClipboard(iCmd);
    778 }
    779 FX_BOOL CFWL_ComboBoxImp::EditRedo(const CFX_ByteStringC& bsRecord) {
    780   if (!m_pEdit)
    781     return FALSE;
    782   return m_pEdit->Redo(bsRecord);
    783 }
    784 FX_BOOL CFWL_ComboBoxImp::EditUndo(const CFX_ByteStringC& bsRecord) {
    785   if (!m_pEdit)
    786     return FALSE;
    787   return m_pEdit->Undo(bsRecord);
    788 }
    789 IFWL_ListBox* CFWL_ComboBoxImp::GetListBoxt() {
    790   return m_pListBox.get();
    791 }
    792 FX_BOOL CFWL_ComboBoxImp::AfterFocusShowDropList() {
    793   if (!m_bNeedShowList) {
    794     return FALSE;
    795   }
    796   if (m_pEdit) {
    797     MatchEditText();
    798   }
    799   ShowDropList(TRUE);
    800   m_bNeedShowList = FALSE;
    801   return TRUE;
    802 }
    803 FX_ERR CFWL_ComboBoxImp::OpenDropDownList(FX_BOOL bActivate) {
    804   ShowDropList(bActivate);
    805   return FWL_ERR_Succeeded;
    806 }
    807 FX_BOOL CFWL_ComboBoxImp::EditCanUndo() {
    808   return m_pEdit->CanUndo();
    809 }
    810 FX_BOOL CFWL_ComboBoxImp::EditCanRedo() {
    811   return m_pEdit->CanRedo();
    812 }
    813 FX_BOOL CFWL_ComboBoxImp::EditUndo() {
    814   return m_pEdit->Undo();
    815 }
    816 FX_BOOL CFWL_ComboBoxImp::EditRedo() {
    817   return m_pEdit->Redo();
    818 }
    819 FX_BOOL CFWL_ComboBoxImp::EditCanCopy() {
    820   return m_pEdit->CountSelRanges() > 0;
    821 }
    822 FX_BOOL CFWL_ComboBoxImp::EditCanCut() {
    823   if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) {
    824     return FALSE;
    825   }
    826   return m_pEdit->CountSelRanges() > 0;
    827 }
    828 FX_BOOL CFWL_ComboBoxImp::EditCanSelectAll() {
    829   return m_pEdit->GetTextLength() > 0;
    830 }
    831 FX_BOOL CFWL_ComboBoxImp::EditCopy(CFX_WideString& wsCopy) {
    832   return m_pEdit->Copy(wsCopy);
    833 }
    834 FX_BOOL CFWL_ComboBoxImp::EditCut(CFX_WideString& wsCut) {
    835   return m_pEdit->Cut(wsCut);
    836 }
    837 FX_BOOL CFWL_ComboBoxImp::EditPaste(const CFX_WideString& wsPaste) {
    838   return m_pEdit->Paste(wsPaste);
    839 }
    840 FX_BOOL CFWL_ComboBoxImp::EditSelectAll() {
    841   return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded;
    842 }
    843 FX_BOOL CFWL_ComboBoxImp::EditDelete() {
    844   return m_pEdit->ClearText() == FWL_ERR_Succeeded;
    845 }
    846 FX_BOOL CFWL_ComboBoxImp::EditDeSelect() {
    847   return m_pEdit->ClearSelections() == FWL_ERR_Succeeded;
    848 }
    849 FWL_ERR CFWL_ComboBoxImp::GetBBox(CFX_RectF& rect) {
    850   if (m_pWidgetMgr->IsFormDisabled()) {
    851     return DisForm_GetBBox(rect);
    852   }
    853   rect = m_pProperties->m_rtWidget;
    854   if (m_pListBox && IsDropListShowed()) {
    855     CFX_RectF rtList;
    856     m_pListBox->GetWidgetRect(rtList);
    857     rtList.Offset(rect.left, rect.top);
    858     rect.Union(rtList);
    859   }
    860   return FWL_ERR_Succeeded;
    861 }
    862 FWL_ERR CFWL_ComboBoxImp::EditModifyStylesEx(FX_DWORD dwStylesExAdded,
    863                                              FX_DWORD dwStylesExRemoved) {
    864   if (m_pEdit != NULL) {
    865     return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
    866   } else {
    867     return FWL_ERR_Parameter_Invalid;
    868   }
    869 }
    870 FX_FLOAT CFWL_ComboBoxImp::GetListHeight() {
    871   return static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider)
    872       ->GetListHeight(m_pInterface);
    873 }
    874 void CFWL_ComboBoxImp::DrawStretchHandler(CFX_Graphics* pGraphics,
    875                                           const CFX_Matrix* pMatrix) {
    876   CFWL_ThemeBackground param;
    877   param.m_pGraphics = pGraphics;
    878   param.m_iPart = FWL_PART_CMB_StretcgHandler;
    879   param.m_dwStates = FWL_PARTSTATE_CMB_Normal;
    880   param.m_pWidget = m_pInterface;
    881   if (pMatrix) {
    882     param.m_matrix.Concat(*pMatrix);
    883   }
    884   param.m_rtPart = m_rtHandler;
    885   m_pProperties->m_pThemeProvider->DrawBackground(&param);
    886 }
    887 void CFWL_ComboBoxImp::ShowDropList(FX_BOOL bActivate) {
    888   if (m_pWidgetMgr->IsFormDisabled()) {
    889     return DisForm_ShowDropList(bActivate);
    890   }
    891   FX_BOOL bDropList = IsDropListShowed();
    892   if (bDropList == bActivate) {
    893     return;
    894   }
    895   if (!m_pForm) {
    896     InitProxyForm();
    897   }
    898   m_pListProxyDelegate->Reset();
    899   if (bActivate) {
    900     static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    901         ->ChangeSelected(m_iCurSel);
    902     ReSetListItemAlignment();
    903     FX_DWORD dwStyleAdd = m_pProperties->m_dwStyleExes &
    904                           (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw);
    905     m_pListBox->ModifyStylesEx(dwStyleAdd, 0);
    906     m_pListBox->GetWidgetRect(m_rtList, TRUE);
    907     FX_FLOAT fHeight = GetListHeight();
    908     if (fHeight > 0) {
    909       if (m_rtList.height > GetListHeight()) {
    910         m_rtList.height = GetListHeight();
    911         m_pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll, 0);
    912       }
    913     }
    914     CFX_RectF rtAnchor;
    915     rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
    916                  m_pProperties->m_rtWidget.height);
    917     FX_FLOAT fMinHeight = 0;
    918     if (m_rtList.width < m_rtClient.width) {
    919       m_rtList.width = m_rtClient.width;
    920     }
    921     m_rtProxy = m_rtList;
    922     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
    923       m_rtProxy.height += m_fComboFormHandler;
    924     }
    925     GetPopupPos(fMinHeight, m_rtProxy.height, rtAnchor, m_rtProxy);
    926     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
    927       FX_FLOAT fx = 0;
    928       FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2;
    929       TransformTo(NULL, fx, fy);
    930       m_bUpFormHandler = fy > m_rtProxy.top;
    931       if (m_bUpFormHandler) {
    932         m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler);
    933         m_rtList.top = m_fComboFormHandler;
    934       } else {
    935         m_rtHandler.Set(0, m_rtList.height, m_rtList.width,
    936                         m_fComboFormHandler);
    937       }
    938     }
    939     m_pForm->SetWidgetRect(m_rtProxy);
    940     m_pForm->Update();
    941     m_pListBox->SetWidgetRect(m_rtList);
    942     m_pListBox->Update();
    943     CFWL_EvtCmbPreDropDown ev;
    944     ev.m_pSrcTarget = m_pInterface;
    945     DispatchEvent(&ev);
    946     m_fItemHeight =
    947         static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_fItemHeight;
    948     static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(TRUE);
    949     m_pForm->DoModal();
    950     static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(FALSE);
    951   } else {
    952     m_pForm->EndDoModal();
    953     CFWL_EvtCmbCloseUp ev;
    954     ev.m_pSrcTarget = m_pInterface;
    955     DispatchEvent(&ev);
    956     m_bLButtonDown = FALSE;
    957     static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_bNotifyOwner =
    958         TRUE;
    959     SetFocus(TRUE);
    960   }
    961 }
    962 FX_BOOL CFWL_ComboBoxImp::IsDropListShowed() {
    963   return m_pForm && !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
    964 }
    965 FX_BOOL CFWL_ComboBoxImp::IsDropDownStyle() const {
    966   return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown;
    967 }
    968 void CFWL_ComboBoxImp::MatchEditText() {
    969   CFX_WideString wsText;
    970   m_pEdit->GetText(wsText);
    971   int32_t iMatch =
    972       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->MatchItem(wsText);
    973   if (iMatch != m_iCurSel) {
    974     static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    975         ->ChangeSelected(iMatch);
    976     if (iMatch >= 0) {
    977       SynchrEditText(iMatch);
    978     }
    979   } else if (iMatch >= 0) {
    980     static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
    981   }
    982   m_iCurSel = iMatch;
    983 }
    984 void CFWL_ComboBoxImp::SynchrEditText(int32_t iListItem) {
    985   CFX_WideString wsText;
    986   IFWL_ComboBoxDP* pData =
    987       static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    988   FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iListItem);
    989   static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
    990       ->GetItemText(hItem, wsText);
    991   m_pEdit->SetText(wsText);
    992   m_pEdit->Update();
    993   static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
    994 }
    995 void CFWL_ComboBoxImp::Layout() {
    996   if (m_pWidgetMgr->IsFormDisabled()) {
    997     return DisForm_Layout();
    998   }
    999   GetClientRect(m_rtClient);
   1000   FX_FLOAT* pFWidth =
   1001       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
   1002   if (!pFWidth)
   1003     return;
   1004   FX_FLOAT fBtn = *pFWidth;
   1005   m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn,
   1006               m_rtClient.height);
   1007   FX_BOOL bIsDropDown = IsDropDownStyle();
   1008   if (bIsDropDown && m_pEdit) {
   1009     CFX_RectF rtEdit;
   1010     rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
   1011                m_rtClient.height);
   1012     m_pEdit->SetWidgetRect(rtEdit);
   1013     if (m_iCurSel >= 0) {
   1014       CFX_WideString wsText;
   1015       IFWL_ComboBoxDP* pData =
   1016           static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
   1017       FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
   1018       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
   1019           ->GetItemText(hItem, wsText);
   1020       m_pEdit->LockUpdate();
   1021       m_pEdit->SetText(wsText);
   1022       m_pEdit->UnlockUpdate();
   1023     }
   1024     m_pEdit->Update();
   1025   }
   1026 }
   1027 void CFWL_ComboBoxImp::ReSetTheme() {
   1028   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
   1029   if (!pTheme) {
   1030     pTheme = GetAvailableTheme();
   1031     m_pProperties->m_pThemeProvider = pTheme;
   1032   }
   1033   if (m_pListBox) {
   1034     if (!m_pListBox->GetThemeProvider() &&
   1035         pTheme->IsValidWidget(m_pListBox.get())) {
   1036       m_pListBox->SetThemeProvider(pTheme);
   1037     }
   1038   }
   1039   if (m_pEdit) {
   1040     if (!m_pEdit->GetThemeProvider() && pTheme->IsValidWidget(m_pEdit.get())) {
   1041       m_pEdit->SetThemeProvider(pTheme);
   1042     }
   1043   }
   1044 }
   1045 void CFWL_ComboBoxImp::ReSetEditAlignment() {
   1046   if (!m_pEdit)
   1047     return;
   1048   FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;
   1049   FX_DWORD dwAdd = 0;
   1050   switch (dwStylExes & FWL_STYLEEXT_CMB_EditHAlignMask) {
   1051     case FWL_STYLEEXT_CMB_EditHCenter: {
   1052       dwAdd |= FWL_STYLEEXT_EDT_HCenter;
   1053       break;
   1054     }
   1055     case FWL_STYLEEXT_CMB_EditHFar: {
   1056       dwAdd |= FWL_STYLEEXT_EDT_HFar;
   1057       break;
   1058     }
   1059     default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; }
   1060   }
   1061   switch (dwStylExes & FWL_STYLEEXT_CMB_EditVAlignMask) {
   1062     case FWL_STYLEEXT_CMB_EditVCenter: {
   1063       dwAdd |= FWL_STYLEEXT_EDT_VCenter;
   1064       break;
   1065     }
   1066     case FWL_STYLEEXT_CMB_EditVFar: {
   1067       dwAdd |= FWL_STYLEEXT_EDT_VFar;
   1068       break;
   1069     }
   1070     default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; }
   1071   }
   1072   if (dwStylExes & FWL_STYLEEXT_CMB_EditJustified) {
   1073     dwAdd |= FWL_STYLEEXT_EDT_Justified;
   1074   }
   1075   if (dwStylExes & FWL_STYLEEXT_CMB_EditDistributed) {
   1076     dwAdd |= FWL_STYLEEXT_EDT_Distributed;
   1077   }
   1078   m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
   1079                                      FWL_STYLEEXT_EDT_HAlignModeMask |
   1080                                      FWL_STYLEEXT_EDT_VAlignMask);
   1081 }
   1082 void CFWL_ComboBoxImp::ReSetListItemAlignment() {
   1083   if (!m_pListBox)
   1084     return;
   1085   FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;
   1086   FX_DWORD dwAdd = 0;
   1087   switch (dwStylExes & FWL_STYLEEXT_CMB_ListItemAlignMask) {
   1088     case FWL_STYLEEXT_CMB_ListItemCenterAlign: {
   1089       dwAdd |= FWL_STYLEEXT_LTB_CenterAlign;
   1090     }
   1091     case FWL_STYLEEXT_CMB_ListItemRightAlign: {
   1092       dwAdd |= FWL_STYLEEXT_LTB_RightAlign;
   1093     }
   1094     default: { dwAdd |= FWL_STYLEEXT_LTB_LeftAlign; }
   1095   }
   1096   m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask);
   1097 }
   1098 void CFWL_ComboBoxImp::ProcessSelChanged(FX_BOOL bLButtonUp) {
   1099   IFWL_ComboBoxDP* pDatas =
   1100       static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
   1101   m_iCurSel = pDatas->GetItemIndex(m_pInterface, m_pListBox->GetSelItem(0));
   1102   FX_BOOL bDropDown = IsDropDownStyle();
   1103   if (bDropDown) {
   1104     IFWL_ComboBoxDP* pData =
   1105         static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
   1106     FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
   1107     if (hItem) {
   1108       CFX_WideString wsText;
   1109       pData->GetItemText(m_pInterface, hItem, wsText);
   1110       if (m_pEdit) {
   1111         m_pEdit->SetText(wsText);
   1112         m_pEdit->Update();
   1113         static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
   1114       }
   1115       CFWL_EvtCmbSelChanged ev;
   1116       ev.bLButtonUp = bLButtonUp;
   1117       ev.m_pSrcTarget = m_pInterface;
   1118       ev.iArraySels.Add(m_iCurSel);
   1119       DispatchEvent(&ev);
   1120     }
   1121   } else {
   1122     Repaint(&m_rtClient);
   1123   }
   1124 }
   1125 void CFWL_ComboBoxImp::InitProxyForm() {
   1126   if (m_pForm)
   1127     return;
   1128   if (!m_pListBox)
   1129     return;
   1130   CFWL_WidgetImpProperties propForm;
   1131   propForm.m_pOwner = m_pInterface;
   1132   propForm.m_dwStyles = FWL_WGTSTYLE_Popup;
   1133   propForm.m_dwStates = FWL_WGTSTATE_Invisible;
   1134   CFX_WideString className;
   1135   m_pForm = IFWL_Form::CreateFormProxy(propForm, &className, m_pListBox.get());
   1136   m_pForm->Initialize();
   1137   m_pProxy = static_cast<CFWL_FormProxyImp*>(m_pForm->GetImpl());
   1138   m_pListBox->SetParent(m_pForm);
   1139   m_pListProxyDelegate = new CFWL_ComboProxyImpDelegate(m_pForm, this);
   1140   m_pProxy->SetDelegate(m_pListProxyDelegate);
   1141 }
   1142 FWL_ERR CFWL_ComboBoxImp::DisForm_Initialize() {
   1143   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
   1144     return FWL_WGTSTATE_Invisible;  // Ditto.
   1145   m_pDelegate = new CFWL_ComboBoxImpDelegate(this);
   1146   DisForm_InitComboList();
   1147   DisForm_InitComboEdit();
   1148   return FWL_ERR_Succeeded;
   1149 }
   1150 void CFWL_ComboBoxImp::DisForm_InitComboList() {
   1151   if (m_pListBox) {
   1152     return;
   1153   }
   1154   CFWL_WidgetImpProperties prop;
   1155   prop.m_pParent = m_pInterface;
   1156   prop.m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
   1157   prop.m_dwStates = FWL_WGTSTATE_Invisible;
   1158   prop.m_pDataProvider = m_pProperties->m_pDataProvider;
   1159   prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
   1160   m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface));
   1161   m_pListBox->Initialize();
   1162 }
   1163 void CFWL_ComboBoxImp::DisForm_InitComboEdit() {
   1164   if (m_pEdit) {
   1165     return;
   1166   }
   1167   CFWL_WidgetImpProperties prop;
   1168   prop.m_pParent = m_pInterface;
   1169   prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
   1170   m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, m_pInterface));
   1171   m_pEdit->Initialize();
   1172   static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
   1173 }
   1174 void CFWL_ComboBoxImp::DisForm_ShowDropList(FX_BOOL bActivate) {
   1175   FX_BOOL bDropList = DisForm_IsDropListShowed();
   1176   if (bDropList == bActivate) {
   1177     return;
   1178   }
   1179   if (bActivate) {
   1180     CFWL_EvtCmbPreDropDown preEvent;
   1181     preEvent.m_pSrcTarget = m_pInterface;
   1182     DispatchEvent(&preEvent);
   1183     CFWL_ComboListImp* pComboList =
   1184         static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl());
   1185     int32_t iItems = pComboList->CountItems();
   1186     if (iItems < 1) {
   1187       return;
   1188     }
   1189     ReSetListItemAlignment();
   1190     pComboList->ChangeSelected(m_iCurSel);
   1191     FX_FLOAT fItemHeight = pComboList->GetItemHeigt();
   1192     FX_FLOAT fBorder = GetBorderSize();
   1193     FX_FLOAT fPopupMin = 0.0f;
   1194     if (iItems > 3) {
   1195       fPopupMin = fItemHeight * 3 + fBorder * 2;
   1196     }
   1197     FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2;
   1198     CFX_RectF rtList;
   1199     rtList.left = m_rtClient.left;
   1200     rtList.width = m_pProperties->m_rtWidget.width;
   1201     rtList.top = 0;
   1202     rtList.height = 0;
   1203     GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList);
   1204     m_pListBox->SetWidgetRect(rtList);
   1205     m_pListBox->Update();
   1206   } else {
   1207     SetFocus(TRUE);
   1208   }
   1209   m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
   1210   if (bActivate) {
   1211     CFWL_EvtCmbPostDropDown postEvent;
   1212     postEvent.m_pSrcTarget = m_pInterface;
   1213     DispatchEvent(&postEvent);
   1214   }
   1215   CFX_RectF rect;
   1216   m_pListBox->GetWidgetRect(rect);
   1217   rect.Inflate(2, 2);
   1218   Repaint(&rect);
   1219 }
   1220 FX_BOOL CFWL_ComboBoxImp::DisForm_IsDropListShowed() {
   1221   return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible);
   1222 }
   1223 FWL_ERR CFWL_ComboBoxImp::DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded,
   1224                                                  FX_DWORD dwStylesExRemoved) {
   1225   if (!m_pEdit) {
   1226     DisForm_InitComboEdit();
   1227   }
   1228   FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;
   1229   FX_BOOL bDelDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;
   1230   dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown;
   1231   m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown;
   1232   if (bAddDropDown) {
   1233     m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly);
   1234   } else if (bDelDropDown) {
   1235     m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0);
   1236   }
   1237   return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
   1238 }
   1239 FWL_ERR CFWL_ComboBoxImp::DisForm_Update() {
   1240   if (m_iLock) {
   1241     return FWL_ERR_Indefinite;
   1242   }
   1243   if (m_pEdit) {
   1244     ReSetEditAlignment();
   1245   }
   1246   ReSetTheme();
   1247   Layout();
   1248   return FWL_ERR_Succeeded;
   1249 }
   1250 FX_DWORD CFWL_ComboBoxImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) {
   1251   CFX_RectF rect;
   1252   rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width,
   1253            m_pProperties->m_rtWidget.height);
   1254   if (rect.Contains(fx, fy)) {
   1255     return FWL_WGTHITTEST_Edit;
   1256   }
   1257   if (m_rtBtn.Contains(fx, fy)) {
   1258     return FWL_WGTHITTEST_Client;
   1259   }
   1260   if (DisForm_IsDropListShowed()) {
   1261     m_pListBox->GetWidgetRect(rect);
   1262     if (rect.Contains(fx, fy)) {
   1263       return FWL_WGTHITTEST_Client;
   1264     }
   1265   }
   1266   return FWL_WGTHITTEST_Unknown;
   1267 }
   1268 FWL_ERR CFWL_ComboBoxImp::DisForm_DrawWidget(CFX_Graphics* pGraphics,
   1269                                              const CFX_Matrix* pMatrix) {
   1270   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
   1271   CFX_Matrix mtOrg;
   1272   mtOrg.Set(1, 0, 0, 1, 0, 0);
   1273   if (pMatrix) {
   1274     mtOrg = *pMatrix;
   1275   }
   1276   FX_BOOL bListShowed = m_pListBox && DisForm_IsDropListShowed();
   1277   pGraphics->SaveGraphState();
   1278   pGraphics->ConcatMatrix(&mtOrg);
   1279   if (!m_rtBtn.IsEmpty(0.1f)) {
   1280     CFWL_ThemeBackground param;
   1281     param.m_pWidget = m_pInterface;
   1282     param.m_iPart = FWL_PART_CMB_DropDownButton;
   1283     param.m_dwStates = m_iBtnState;
   1284     param.m_pGraphics = pGraphics;
   1285     param.m_rtPart = m_rtBtn;
   1286     pTheme->DrawBackground(&param);
   1287   }
   1288   pGraphics->RestoreGraphState();
   1289   if (m_pEdit) {
   1290     CFX_RectF rtEdit;
   1291     m_pEdit->GetWidgetRect(rtEdit);
   1292     CFX_Matrix mt;
   1293     mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
   1294     mt.Concat(mtOrg);
   1295     m_pEdit->DrawWidget(pGraphics, &mt);
   1296   }
   1297   if (bListShowed) {
   1298     CFX_RectF rtList;
   1299     m_pListBox->GetWidgetRect(rtList);
   1300     CFX_Matrix mt;
   1301     mt.Set(1, 0, 0, 1, rtList.left, rtList.top);
   1302     mt.Concat(mtOrg);
   1303     m_pListBox->DrawWidget(pGraphics, &mt);
   1304   }
   1305   return FWL_ERR_Succeeded;
   1306 }
   1307 FWL_ERR CFWL_ComboBoxImp::DisForm_GetBBox(CFX_RectF& rect) {
   1308   rect = m_pProperties->m_rtWidget;
   1309   if (m_pListBox && DisForm_IsDropListShowed()) {
   1310     CFX_RectF rtList;
   1311     m_pListBox->GetWidgetRect(rtList);
   1312     rtList.Offset(rect.left, rect.top);
   1313     rect.Union(rtList);
   1314   }
   1315   return FWL_ERR_Succeeded;
   1316 }
   1317 void CFWL_ComboBoxImp::DisForm_Layout() {
   1318   GetClientRect(m_rtClient);
   1319   m_rtContent = m_rtClient;
   1320   FX_FLOAT* pFWidth =
   1321       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
   1322   if (!pFWidth)
   1323     return;
   1324   FX_FLOAT borderWidth = 0;
   1325   { borderWidth = FWL_PART_CMB_Border; }
   1326   FX_FLOAT fBtn = *pFWidth;
   1327   if (!(this->GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) {
   1328     m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth,
   1329                 fBtn - borderWidth, m_rtClient.height - 2 * borderWidth);
   1330   }
   1331   CFX_RectF* pUIMargin =
   1332       static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin));
   1333   if (pUIMargin) {
   1334     m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
   1335                         pUIMargin->height);
   1336   }
   1337   FX_BOOL bIsDropDown = IsDropDownStyle();
   1338   if (bIsDropDown && m_pEdit) {
   1339     CFX_RectF rtEdit;
   1340     rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn,
   1341                m_rtContent.height);
   1342     m_pEdit->SetWidgetRect(rtEdit);
   1343     if (m_iCurSel >= 0) {
   1344       CFX_WideString wsText;
   1345       IFWL_ComboBoxDP* pData =
   1346           static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
   1347       FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
   1348       static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
   1349           ->GetItemText(hItem, wsText);
   1350       m_pEdit->LockUpdate();
   1351       m_pEdit->SetText(wsText);
   1352       m_pEdit->UnlockUpdate();
   1353     }
   1354     m_pEdit->Update();
   1355   }
   1356 }
   1357 CFWL_ComboBoxImpDelegate::CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp* pOwner)
   1358     : m_pOwner(pOwner) {}
   1359 int32_t CFWL_ComboBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
   1360   if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
   1361     return DisForm_OnProcessMessage(pMessage);
   1362   }
   1363   if (!pMessage)
   1364     return 0;
   1365   FX_DWORD dwMsgCode = pMessage->GetClassID();
   1366   FX_BOOL iRet = 1;
   1367   switch (dwMsgCode) {
   1368     case FWL_MSGHASH_SetFocus:
   1369     case FWL_MSGHASH_KillFocus: {
   1370       OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
   1371       break;
   1372     }
   1373     case FWL_MSGHASH_Mouse: {
   1374       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1375       FX_DWORD dwCmd = pMsg->m_dwCmd;
   1376       switch (dwCmd) {
   1377         case FWL_MSGMOUSECMD_LButtonDown: {
   1378           OnLButtonDown(pMsg);
   1379           break;
   1380         }
   1381         case FWL_MSGMOUSECMD_LButtonUp: {
   1382           OnLButtonUp(pMsg);
   1383           break;
   1384         }
   1385         case FWL_MSGMOUSECMD_MouseMove: {
   1386           OnMouseMove(pMsg);
   1387           break;
   1388         }
   1389         case FWL_MSGMOUSECMD_MouseLeave: {
   1390           OnMouseLeave(pMsg);
   1391           break;
   1392         }
   1393         default: {}
   1394       }
   1395       break;
   1396     }
   1397     case FWL_MSGHASH_Key: {
   1398       OnKey(static_cast<CFWL_MsgKey*>(pMessage));
   1399       break;
   1400     }
   1401     default: { iRet = 0; }
   1402   }
   1403   CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
   1404   return iRet;
   1405 }
   1406 FWL_ERR CFWL_ComboBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
   1407   FX_DWORD dwFlag = pEvent->GetClassID();
   1408   if (dwFlag == FWL_EVTHASH_LTB_DrawItem) {
   1409     CFWL_EvtLtbDrawItem* pDrawItemEvent =
   1410         static_cast<CFWL_EvtLtbDrawItem*>(pEvent);
   1411     CFWL_EvtCmbDrawItem pTemp;
   1412     pTemp.m_pSrcTarget = m_pOwner->m_pInterface;
   1413     pTemp.m_pGraphics = pDrawItemEvent->m_pGraphics;
   1414     pTemp.m_index = pDrawItemEvent->m_index;
   1415     pTemp.m_rtItem = pDrawItemEvent->m_rect;
   1416     m_pOwner->DispatchEvent(&pTemp);
   1417   } else if (dwFlag == FWL_EVTHASH_Scroll) {
   1418     CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
   1419     CFWL_EvtScroll pScrollEv;
   1420     pScrollEv.m_pSrcTarget = m_pOwner->m_pInterface;
   1421     pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode;
   1422     pScrollEv.m_fPos = pScrollEvent->m_fPos;
   1423     m_pOwner->DispatchEvent(&pScrollEv);
   1424   } else if (dwFlag == FWL_EVTHASH_EDT_TextChanged) {
   1425     CFWL_EvtEdtTextChanged* pTextChangedEvent =
   1426         static_cast<CFWL_EvtEdtTextChanged*>(pEvent);
   1427     CFWL_EvtCmbEditChanged pTemp;
   1428     pTemp.m_pSrcTarget = m_pOwner->m_pInterface;
   1429     pTemp.wsInsert = pTextChangedEvent->wsInsert;
   1430     pTemp.wsDelete = pTextChangedEvent->wsDelete;
   1431     pTemp.nChangeType = pTextChangedEvent->nChangeType;
   1432     m_pOwner->DispatchEvent(&pTemp);
   1433   }
   1434   return FWL_ERR_Succeeded;
   1435 }
   1436 FWL_ERR CFWL_ComboBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1437                                                const CFX_Matrix* pMatrix) {
   1438   return m_pOwner->DrawWidget(pGraphics, pMatrix);
   1439 }
   1440 void CFWL_ComboBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg,
   1441                                               FX_BOOL bSet) {
   1442   IFWL_Target* pDstTarget = pMsg->m_pDstTarget;
   1443   IFWL_Target* pSrcTarget = pMsg->m_pSrcTarget;
   1444   FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
   1445   if (bSet) {
   1446     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
   1447     if (bDropDown && pSrcTarget != m_pOwner->m_pListBox.get()) {
   1448       if (!m_pOwner->m_pEdit)
   1449         return;
   1450       static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
   1451           ->SetSelected();
   1452     } else {
   1453       m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1454     }
   1455   } else {
   1456     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
   1457     if (bDropDown && pDstTarget != m_pOwner->m_pListBox.get()) {
   1458       if (!m_pOwner->m_pEdit)
   1459         return;
   1460       static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
   1461           ->FlagFocus(FALSE);
   1462       static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
   1463           ->ClearSelected();
   1464     } else {
   1465       m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1466     }
   1467   }
   1468 }
   1469 void CFWL_ComboBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
   1470   if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
   1471     return;
   1472   }
   1473   FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
   1474   CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;
   1475   FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);
   1476   if (bClickBtn) {
   1477     if (bDropDown && m_pOwner->m_pEdit) {
   1478       m_pOwner->MatchEditText();
   1479     }
   1480     m_pOwner->m_bLButtonDown = TRUE;
   1481     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Pressed;
   1482     m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1483     m_pOwner->ShowDropList(TRUE);
   1484     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
   1485     m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1486   }
   1487 }
   1488 void CFWL_ComboBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
   1489   m_pOwner->m_bLButtonDown = FALSE;
   1490   if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1491     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Hovered;
   1492   } else {
   1493     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
   1494   }
   1495   m_pOwner->Repaint(&m_pOwner->m_rtBtn);
   1496 }
   1497 void CFWL_ComboBoxImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
   1498   int32_t iOldState = m_pOwner->m_iBtnState;
   1499   if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1500     m_pOwner->m_iBtnState = m_pOwner->m_bLButtonDown
   1501                                 ? FWL_PARTSTATE_CMB_Pressed
   1502                                 : FWL_PARTSTATE_CMB_Hovered;
   1503   } else {
   1504     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
   1505   }
   1506   if ((iOldState != m_pOwner->m_iBtnState) &&
   1507       !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
   1508         FWL_WGTSTATE_Disabled)) {
   1509     m_pOwner->Repaint(&m_pOwner->m_rtBtn);
   1510   }
   1511 }
   1512 void CFWL_ComboBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) {
   1513   if (!m_pOwner->IsDropListShowed() &&
   1514       !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
   1515         FWL_WGTSTATE_Disabled)) {
   1516     m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
   1517     m_pOwner->Repaint(&m_pOwner->m_rtBtn);
   1518   }
   1519 }
   1520 void CFWL_ComboBoxImpDelegate::OnKey(CFWL_MsgKey* pMsg) {
   1521   FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
   1522   if (dwKeyCode == FWL_VKEY_Tab) {
   1523     m_pOwner->DispatchKeyEvent(pMsg);
   1524     return;
   1525   }
   1526   FX_BOOL bSubCtrlKey = pMsg->m_pDstTarget == m_pOwner->m_pInterface;
   1527   if (bSubCtrlKey) {
   1528     DoSubCtrlKey(pMsg);
   1529   }
   1530 }
   1531 void CFWL_ComboBoxImpDelegate::DoSubCtrlKey(CFWL_MsgKey* pMsg) {
   1532   FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
   1533   FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up;
   1534   FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down;
   1535   if (bUp || bDown) {
   1536     int32_t iCount = static_cast<CFWL_ComboListImp*>(
   1537                          m_pOwner->m_pListBox->GetImpl())->CountItems();
   1538     if (iCount < 1) {
   1539       return;
   1540     }
   1541     FX_BOOL bMatchEqual = FALSE;
   1542     int32_t iCurSel = m_pOwner->m_iCurSel;
   1543     FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
   1544     if (bDropDown && m_pOwner->m_pEdit) {
   1545       CFX_WideString wsText;
   1546       m_pOwner->m_pEdit->GetText(wsText);
   1547       iCurSel = static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl())
   1548                     ->MatchItem(wsText);
   1549       if (iCurSel >= 0) {
   1550         CFX_WideString wsTemp;
   1551         IFWL_ComboBoxDP* pData = static_cast<IFWL_ComboBoxDP*>(
   1552             m_pOwner->m_pProperties->m_pDataProvider);
   1553         FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, iCurSel);
   1554         static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl())
   1555             ->GetItemText(hItem, wsTemp);
   1556         bMatchEqual = wsText.Equal(wsTemp);
   1557       }
   1558     }
   1559     if (iCurSel < 0) {
   1560       iCurSel = 0;
   1561     } else if (!bDropDown || bMatchEqual) {
   1562       if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {
   1563         return;
   1564       }
   1565       if (bUp) {
   1566         iCurSel--;
   1567       } else {
   1568         iCurSel++;
   1569       }
   1570     }
   1571     m_pOwner->m_iCurSel = iCurSel;
   1572     if (bDropDown && m_pOwner->m_pEdit) {
   1573       m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);
   1574     } else {
   1575       m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1576     }
   1577     return;
   1578   }
   1579   FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
   1580   if (bDropDown) {
   1581     IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
   1582     pDelegate->OnProcessMessage(pMsg);
   1583   }
   1584 }
   1585 int32_t CFWL_ComboBoxImpDelegate::DisForm_OnProcessMessage(
   1586     CFWL_Message* pMessage) {
   1587   if (!pMessage)
   1588     return 0;
   1589   FX_DWORD dwMsgCode = pMessage->GetClassID();
   1590   FX_BOOL backDefault = TRUE;
   1591   switch (dwMsgCode) {
   1592     case FWL_MSGHASH_SetFocus:
   1593     case FWL_MSGHASH_KillFocus: {
   1594       backDefault = FALSE;
   1595       DisForm_OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
   1596       break;
   1597     }
   1598     case FWL_MSGHASH_Mouse: {
   1599       backDefault = FALSE;
   1600       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1601       FX_DWORD dwCmd = pMsg->m_dwCmd;
   1602       switch (dwCmd) {
   1603         case FWL_MSGMOUSECMD_LButtonDown: {
   1604           DisForm_OnLButtonDown(pMsg);
   1605           break;
   1606         }
   1607         case FWL_MSGMOUSECMD_LButtonUp: {
   1608           OnLButtonUp(pMsg);
   1609           break;
   1610         }
   1611         default: {}
   1612       }
   1613       break;
   1614     }
   1615     case FWL_MSGHASH_Key: {
   1616       backDefault = FALSE;
   1617       CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
   1618       if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyUp) {
   1619         break;
   1620       }
   1621       if (m_pOwner->DisForm_IsDropListShowed() &&
   1622           pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {
   1623         FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
   1624         FX_BOOL bListKey =
   1625             dwKeyCode == FWL_VKEY_Up || dwKeyCode == FWL_VKEY_Down ||
   1626             dwKeyCode == FWL_VKEY_Return || dwKeyCode == FWL_VKEY_Escape;
   1627         if (bListKey) {
   1628           IFWL_WidgetDelegate* pDelegate =
   1629               m_pOwner->m_pListBox->SetDelegate(NULL);
   1630           pDelegate->OnProcessMessage(pMessage);
   1631           break;
   1632         }
   1633       }
   1634       DisForm_OnKey(pKey);
   1635       break;
   1636     }
   1637     default: {}
   1638   }
   1639   if (!backDefault) {
   1640     return 1;
   1641   }
   1642   return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
   1643 }
   1644 void CFWL_ComboBoxImpDelegate::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) {
   1645   FX_BOOL bDropDown = m_pOwner->DisForm_IsDropListShowed();
   1646   CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;
   1647   FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);
   1648   if (bClickBtn) {
   1649     if (m_pOwner->DisForm_IsDropListShowed()) {
   1650       m_pOwner->DisForm_ShowDropList(FALSE);
   1651       return;
   1652     }
   1653     {
   1654       if (m_pOwner->m_pEdit) {
   1655         m_pOwner->MatchEditText();
   1656       }
   1657       m_pOwner->DisForm_ShowDropList(TRUE);
   1658     }
   1659   }
   1660 }
   1661 void CFWL_ComboBoxImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg,
   1662                                                       FX_BOOL bSet) {
   1663   if (bSet) {
   1664     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
   1665     if ((m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) {
   1666       CFWL_MsgSetFocus msg;
   1667       msg.m_pDstTarget = m_pOwner->m_pEdit.get();
   1668       msg.m_pSrcTarget = NULL;
   1669       IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
   1670       pDelegate->OnProcessMessage(&msg);
   1671     }
   1672   } else {
   1673     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
   1674     m_pOwner->DisForm_ShowDropList(FALSE);
   1675     CFWL_MsgKillFocus msg;
   1676     msg.m_pDstTarget = NULL;
   1677     msg.m_pSrcTarget = m_pOwner->m_pEdit.get();
   1678     IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
   1679     pDelegate->OnProcessMessage(&msg);
   1680   }
   1681 }
   1682 void CFWL_ComboBoxImpDelegate::DisForm_OnKey(CFWL_MsgKey* pMsg) {
   1683   FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
   1684   FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up;
   1685   FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down;
   1686   if (bUp || bDown) {
   1687     CFWL_ComboListImp* pComboList =
   1688         static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl());
   1689     int32_t iCount = pComboList->CountItems();
   1690     if (iCount < 1) {
   1691       return;
   1692     }
   1693     FX_BOOL bMatchEqual = FALSE;
   1694     int32_t iCurSel = m_pOwner->m_iCurSel;
   1695     if (m_pOwner->m_pEdit) {
   1696       CFX_WideString wsText;
   1697       m_pOwner->m_pEdit->GetText(wsText);
   1698       iCurSel = pComboList->MatchItem(wsText);
   1699       if (iCurSel >= 0) {
   1700         CFX_WideString wsTemp;
   1701         FWL_HLISTITEM item = m_pOwner->m_pListBox->GetSelItem(iCurSel);
   1702         m_pOwner->m_pListBox->GetItemText(item, wsTemp);
   1703         bMatchEqual = wsText.Equal(wsTemp);
   1704       }
   1705     }
   1706     if (iCurSel < 0) {
   1707       iCurSel = 0;
   1708     } else if (bMatchEqual) {
   1709       if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {
   1710         return;
   1711       }
   1712       if (bUp) {
   1713         iCurSel--;
   1714       } else {
   1715         iCurSel++;
   1716       }
   1717     }
   1718     m_pOwner->m_iCurSel = iCurSel;
   1719     m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);
   1720     return;
   1721   }
   1722   if (m_pOwner->m_pEdit) {
   1723     IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
   1724     pDelegate->OnProcessMessage(pMsg);
   1725   }
   1726 }
   1727 CFWL_ComboProxyImpDelegate::CFWL_ComboProxyImpDelegate(
   1728     IFWL_Form* pForm,
   1729     CFWL_ComboBoxImp* pComboBox)
   1730     : m_bLButtonDown(FALSE),
   1731       m_bLButtonUpSelf(FALSE),
   1732       m_fStartPos(0),
   1733       m_pForm(pForm),
   1734       m_pComboBox(pComboBox) {
   1735 }
   1736 int32_t CFWL_ComboProxyImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
   1737   if (!pMessage)
   1738     return 0;
   1739   FX_DWORD dwMsgCode = pMessage->GetClassID();
   1740   if (dwMsgCode == FWL_MSGHASH_Mouse) {
   1741     CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1742     FX_DWORD dwCmd = pMsg->m_dwCmd;
   1743     switch (dwCmd) {
   1744       case FWL_MSGMOUSECMD_LButtonDown: {
   1745         OnLButtonDown(pMsg);
   1746         break;
   1747       }
   1748       case FWL_MSGMOUSECMD_LButtonUp: {
   1749         OnLButtonUp(pMsg);
   1750         break;
   1751       }
   1752       case FWL_MSGMOUSECMD_MouseMove: {
   1753         OnMouseMove(pMsg);
   1754         break;
   1755       }
   1756       default: {}
   1757     }
   1758   }
   1759   if (dwMsgCode == FWL_MSGHASH_Deactivate) {
   1760     OnDeactive(static_cast<CFWL_MsgDeactivate*>(pMessage));
   1761   }
   1762   if (dwMsgCode == FWL_MSGHASH_KillFocus || dwMsgCode == FWL_MSGHASH_SetFocus) {
   1763     OnFocusChanged(static_cast<CFWL_MsgKillFocus*>(pMessage),
   1764                    dwMsgCode == FWL_MSGHASH_SetFocus);
   1765   }
   1766   return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
   1767 }
   1768 FWL_ERR CFWL_ComboProxyImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1769                                                  const CFX_Matrix* pMatrix) {
   1770   m_pComboBox->DrawStretchHandler(pGraphics, pMatrix);
   1771   return FWL_ERR_Succeeded;
   1772 }
   1773 void CFWL_ComboProxyImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
   1774   IFWL_NoteThread* pThread = m_pForm->GetOwnerThread();
   1775   if (!pThread)
   1776     return;
   1777   CFWL_NoteDriver* pDriver =
   1778       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
   1779   CFX_RectF rtWidget;
   1780   m_pForm->GetWidgetRect(rtWidget);
   1781   rtWidget.left = rtWidget.top = 0;
   1782   if (rtWidget.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1783     m_bLButtonDown = TRUE;
   1784     pDriver->SetGrab(m_pForm, TRUE);
   1785   } else {
   1786     m_bLButtonDown = FALSE;
   1787     pDriver->SetGrab(m_pForm, FALSE);
   1788     m_pComboBox->ShowDropList(FALSE);
   1789     return;
   1790   }
   1791   IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
   1792   IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr();
   1793   FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);
   1794   pCursorMgr->SetCursor(hCursor);
   1795   pCursorMgr->ShowCursor(TRUE);
   1796   m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy);
   1797   m_fStartPos = pMsg->m_fy;
   1798 }
   1799 void CFWL_ComboProxyImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
   1800   m_bLButtonDown = FALSE;
   1801   IFWL_NoteThread* pThread = m_pForm->GetOwnerThread();
   1802   if (!pThread)
   1803     return;
   1804   CFWL_NoteDriver* pDriver =
   1805       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
   1806   pDriver->SetGrab(m_pForm, FALSE);
   1807   if (m_bLButtonUpSelf) {
   1808     CFX_RectF rect;
   1809     m_pForm->GetWidgetRect(rect);
   1810     rect.left = rect.top = 0;
   1811     if (!rect.Contains(pMsg->m_fx, pMsg->m_fy) &&
   1812         m_pComboBox->IsDropListShowed()) {
   1813       m_pComboBox->ShowDropList(FALSE);
   1814     }
   1815   } else {
   1816     m_bLButtonUpSelf = TRUE;
   1817   }
   1818 }
   1819 void CFWL_ComboProxyImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
   1820   IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
   1821   IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr();
   1822   FWL_CURSORTYPE cursorType = FWL_CURSORTYPE_Arrow;
   1823   if (m_pComboBox->m_rtHandler.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1824     cursorType = FWL_CURSORTYPE_SizeNS;
   1825   }
   1826   FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(cursorType);
   1827   pCursorMgr->SetCursor(hCursor);
   1828   pCursorMgr->ShowCursor(TRUE);
   1829   if (!m_bLButtonDown) {
   1830     return;
   1831   }
   1832   m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy);
   1833   FX_FLOAT fChanged = pMsg->m_fy - m_fStartPos;
   1834   if (m_pComboBox->m_bUpFormHandler) {
   1835     fChanged = m_fStartPos - pMsg->m_fy;
   1836   }
   1837   if (m_pComboBox->m_rtList.height + fChanged < m_pComboBox->m_fItemHeight) {
   1838     return;
   1839   }
   1840   m_pComboBox->m_rtList.height += fChanged;
   1841   m_pComboBox->m_rtProxy.height += fChanged;
   1842   if (m_pComboBox->m_bUpFormHandler) {
   1843     m_pComboBox->m_rtProxy.top -= fChanged;
   1844     m_pComboBox->m_rtHandler.Set(0, 0, m_pComboBox->m_rtList.width,
   1845                                  m_pComboBox->m_fComboFormHandler);
   1846   } else {
   1847     m_pComboBox->m_rtHandler.Set(0, m_pComboBox->m_rtList.height,
   1848                                  m_pComboBox->m_rtList.width,
   1849                                  m_pComboBox->m_fComboFormHandler);
   1850   }
   1851   m_pForm->SetWidgetRect(m_pComboBox->m_rtProxy);
   1852   m_pComboBox->m_pListBox->SetWidgetRect(m_pComboBox->m_rtList);
   1853   m_pComboBox->m_pListBox->Update();
   1854   m_fStartPos = pMsg->m_fy;
   1855 }
   1856 void CFWL_ComboProxyImpDelegate::OnDeactive(CFWL_MsgDeactivate* pMsg) {
   1857   m_pComboBox->ShowDropList(FALSE);
   1858 }
   1859 void CFWL_ComboProxyImpDelegate::OnFocusChanged(CFWL_MsgKillFocus* pMsg,
   1860                                                 FX_BOOL bSet) {
   1861   if (!bSet) {
   1862     if (pMsg->m_pSetFocus == NULL) {
   1863       m_pComboBox->ShowDropList(FALSE);
   1864     }
   1865   }
   1866 }
   1867