Home | History | Annotate | Download | only in core
      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_threadimp.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_panelimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_formimp.h"
     14 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
     15 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
     16 #include "xfa/src/fwl/src/basewidget/include/fwl_formproxyimp.h"
     17 
     18 #define FWL_SYSBTNSIZE 21
     19 #define FWL_SYSBTNMARGIN 5
     20 #define FWL_SYSBTNSPAN 2
     21 #define FWL_CornerEnlarge 10
     22 
     23 // static
     24 IFWL_Form* IFWL_Form::CreateFormProxy(CFWL_WidgetImpProperties& properties,
     25                                       CFX_WideString* classname,
     26                                       IFWL_Widget* pOuter) {
     27   IFWL_Form* pForm = new IFWL_Form;
     28   CFWL_FormProxyImp* pFormProxyImpl = new CFWL_FormProxyImp(properties, pOuter);
     29   pForm->SetImpl(pFormProxyImpl);
     30   pFormProxyImpl->SetInterface(pForm);
     31   return pForm;
     32 }
     33 IFWL_Form::IFWL_Form() {}
     34 FWL_FORMSIZE IFWL_Form::GetFormSize() {
     35   return static_cast<CFWL_FormImp*>(GetImpl())->GetFormSize();
     36 }
     37 FWL_ERR IFWL_Form::SetFormSize(FWL_FORMSIZE eFormSize) {
     38   return static_cast<CFWL_FormImp*>(GetImpl())->SetFormSize(eFormSize);
     39 }
     40 IFWL_Widget* IFWL_Form::DoModal() {
     41   return static_cast<CFWL_FormImp*>(GetImpl())->DoModal();
     42 }
     43 IFWL_Widget* IFWL_Form::DoModal(FX_DWORD& dwCommandID) {
     44   return static_cast<CFWL_FormImp*>(GetImpl())->DoModal(dwCommandID);
     45 }
     46 FWL_ERR IFWL_Form::EndDoModal() {
     47   return static_cast<CFWL_FormImp*>(GetImpl())->EndDoModal();
     48 }
     49 FWL_ERR IFWL_Form::SetBorderRegion(CFX_Path* pPath) {
     50   return static_cast<CFWL_FormImp*>(GetImpl())->SetBorderRegion(pPath);
     51 }
     52 
     53 CFWL_FormImp::CFWL_FormImp(const CFWL_WidgetImpProperties& properties,
     54                            IFWL_Widget* pOuter)
     55     : CFWL_PanelImp(properties, pOuter),
     56       m_pCloseBox(NULL),
     57       m_pMinBox(NULL),
     58       m_pMaxBox(NULL),
     59       m_pCaptionBox(NULL),
     60       m_pNoteLoop(NULL),
     61       m_pSubFocus(NULL),
     62       m_fCXBorder(0),
     63       m_fCYBorder(0),
     64       m_iCaptureBtn(-1),
     65       m_iSysBox(0),
     66       m_eResizeType(FORM_RESIZETYPE_None),
     67       m_bLButtonDown(FALSE),
     68       m_bMaximized(FALSE),
     69       m_bSetMaximize(FALSE),
     70       m_bCustomizeLayout(FALSE),
     71       m_eFormSize(FWL_FORMSIZE_Manual),
     72       m_bDoModalFlag(FALSE),
     73       m_pBigIcon(NULL),
     74       m_pSmallIcon(NULL),
     75       m_bMouseIn(FALSE) {
     76   m_rtRelative.Reset();
     77   m_rtCaption.Reset();
     78   m_rtRestore.Reset();
     79   m_rtCaptionText.Reset();
     80   m_rtIcon.Reset();
     81   m_InfoStart.m_ptStart.Reset();
     82   m_InfoStart.m_szStart.Reset();
     83 }
     84 CFWL_FormImp::~CFWL_FormImp() {
     85   RemoveSysButtons();
     86   if (m_pNoteLoop) {
     87     delete m_pNoteLoop;
     88     m_pNoteLoop = NULL;
     89   }
     90 }
     91 FWL_ERR CFWL_FormImp::GetClassName(CFX_WideString& wsClass) const {
     92   wsClass = FWL_CLASS_Form;
     93   return FWL_ERR_Succeeded;
     94 }
     95 FX_DWORD CFWL_FormImp::GetClassID() const {
     96   return FWL_CLASSHASH_Form;
     97 }
     98 FX_BOOL CFWL_FormImp::IsInstance(const CFX_WideStringC& wsClass) const {
     99   if (wsClass == CFX_WideStringC(FWL_CLASS_Form)) {
    100     return TRUE;
    101   }
    102   return CFWL_PanelImp::IsInstance(wsClass);
    103 }
    104 FWL_ERR CFWL_FormImp::Initialize() {
    105   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
    106     return FWL_ERR_Indefinite;
    107   RegisterForm();
    108   RegisterEventTarget();
    109   m_pDelegate = new CFWL_FormImpDelegate(this);
    110   return FWL_ERR_Succeeded;
    111 }
    112 FWL_ERR CFWL_FormImp::Finalize() {
    113   delete m_pDelegate;
    114   m_pDelegate = nullptr;
    115   UnregisterEventTarget();
    116   UnRegisterForm();
    117   return CFWL_WidgetImp::Finalize();
    118 }
    119 FWL_ERR CFWL_FormImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
    120   if (bAutoSize) {
    121     rect.Reset();
    122     FX_FLOAT fCapHeight = GetCaptionHeight();
    123     FX_FLOAT fCXBorder = GetBorderSize(TRUE);
    124     FX_FLOAT fCYBorder = GetBorderSize(FALSE);
    125     FX_FLOAT fEdge = GetEdgeWidth();
    126     if (m_pContent) {
    127       m_pContent->GetWidgetRect(rect, TRUE);
    128     }
    129     rect.height += fCapHeight + fCYBorder + fEdge + fEdge;
    130     rect.width += fCXBorder + fCXBorder + fEdge + fEdge;
    131   } else {
    132     rect = m_pProperties->m_rtWidget;
    133   }
    134   return FWL_ERR_Succeeded;
    135 }
    136 FWL_ERR CFWL_FormImp::GetClientRect(CFX_RectF& rect) {
    137   if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_Caption) == 0) {
    138     rect = m_pProperties->m_rtWidget;
    139     rect.Offset(-rect.left, -rect.top);
    140     return FWL_ERR_Succeeded;
    141   }
    142 #ifdef FWL_UseMacSystemBorder
    143   rect = m_rtRelative;
    144   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    145   if (!pWidgetMgr)
    146     return FWL_ERR_Indefinite;
    147   IFWL_AdapterWidgetMgr* adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();
    148   FX_FLOAT l, t, r, b;
    149   l = t = r = b = 0;
    150   adapterWidgetMgr->GetSystemBorder(l, t, r, b);
    151   rect.Deflate(l, t, r, b);
    152   rect.left = rect.top = 0;
    153   return FWL_ERR_Succeeded;
    154 #else
    155   FX_FLOAT x = 0;
    156   FX_FLOAT y = 0;
    157   FX_FLOAT t = 0;
    158   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    159   if (pTheme) {
    160     CFWL_ThemePart part;
    161     part.m_pWidget = m_pInterface;
    162     x = *static_cast<FX_FLOAT*>(
    163         pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CXBorder));
    164     y = *static_cast<FX_FLOAT*>(
    165         pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CYBorder));
    166     t = *static_cast<FX_FLOAT*>(
    167         pTheme->GetCapacity(&part, FWL_WGTCAPACITY_FRM_CYCaption));
    168   }
    169   rect = m_pProperties->m_rtWidget;
    170   rect.Offset(-rect.left, -rect.top);
    171   rect.Deflate(x, t, x, y);
    172   return FWL_ERR_Succeeded;
    173 #endif
    174 }
    175 FWL_ERR CFWL_FormImp::Update() {
    176   if (m_iLock > 0) {
    177     return FWL_ERR_Succeeded;
    178   }
    179   if (!m_pProperties->m_pThemeProvider) {
    180     m_pProperties->m_pThemeProvider = GetAvailableTheme();
    181   }
    182 #ifdef FWL_UseMacSystemBorder
    183 #else
    184   SetThemeData();
    185   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Icon) {
    186     UpdateIcon();
    187   }
    188 #endif
    189   UpdateCaption();
    190   Layout();
    191   return FWL_ERR_Succeeded;
    192 }
    193 FX_DWORD CFWL_FormImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
    194   (void)GetAvailableTheme();
    195   if (m_pCloseBox && m_pCloseBox->m_rtBtn.Contains(fx, fy)) {
    196     return FWL_WGTHITTEST_CloseBox;
    197   }
    198   if (m_pMaxBox && m_pMaxBox->m_rtBtn.Contains(fx, fy)) {
    199     return FWL_WGTHITTEST_MaxBox;
    200   }
    201   if (m_pMinBox && m_pMinBox->m_rtBtn.Contains(fx, fy)) {
    202     return FWL_WGTHITTEST_MinBox;
    203   }
    204   CFX_RectF rtCap;
    205   rtCap.Set(m_rtCaption.left + m_fCYBorder, m_rtCaption.top + m_fCXBorder,
    206             m_rtCaption.width - FWL_SYSBTNSIZE * m_iSysBox - 2 * m_fCYBorder,
    207             m_rtCaption.height - m_fCXBorder);
    208   if (rtCap.Contains(fx, fy)) {
    209     return FWL_WGTHITTEST_Titlebar;
    210   }
    211   if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) &&
    212       (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_Resize)) {
    213     FX_FLOAT fWidth =
    214         m_rtRelative.width - 2 * (m_fCYBorder + FWL_CornerEnlarge);
    215     FX_FLOAT fHeight =
    216         m_rtRelative.height - 2 * (m_fCXBorder + FWL_CornerEnlarge);
    217     CFX_RectF rt;
    218     rt.Set(0, m_fCXBorder + FWL_CornerEnlarge, m_fCYBorder, fHeight);
    219     if (rt.Contains(fx, fy)) {
    220       return FWL_WGTHITTEST_Left;
    221     }
    222     rt.Set(m_rtRelative.width - m_fCYBorder, m_fCXBorder + FWL_CornerEnlarge,
    223            m_fCYBorder, fHeight);
    224     if (rt.Contains(fx, fy)) {
    225       return FWL_WGTHITTEST_Right;
    226     }
    227     rt.Set(m_fCYBorder + FWL_CornerEnlarge, 0, fWidth, m_fCXBorder);
    228     if (rt.Contains(fx, fy)) {
    229       return FWL_WGTHITTEST_Top;
    230     }
    231     rt.Set(m_fCYBorder + FWL_CornerEnlarge, m_rtRelative.height - m_fCXBorder,
    232            fWidth, m_fCXBorder);
    233     if (rt.Contains(fx, fy)) {
    234       return FWL_WGTHITTEST_Bottom;
    235     }
    236     rt.Set(0, 0, m_fCYBorder + FWL_CornerEnlarge,
    237            m_fCXBorder + FWL_CornerEnlarge);
    238     if (rt.Contains(fx, fy)) {
    239       return FWL_WGTHITTEST_LeftTop;
    240     }
    241     rt.Set(0, m_rtRelative.height - m_fCXBorder - FWL_CornerEnlarge,
    242            m_fCYBorder + FWL_CornerEnlarge, m_fCXBorder + FWL_CornerEnlarge);
    243     if (rt.Contains(fx, fy)) {
    244       return FWL_WGTHITTEST_LeftBottom;
    245     }
    246     rt.Set(m_rtRelative.width - m_fCYBorder - FWL_CornerEnlarge, 0,
    247            m_fCYBorder + FWL_CornerEnlarge, m_fCXBorder + FWL_CornerEnlarge);
    248     if (rt.Contains(fx, fy)) {
    249       return FWL_WGTHITTEST_RightTop;
    250     }
    251     rt.Set(m_rtRelative.width - m_fCYBorder - FWL_CornerEnlarge,
    252            m_rtRelative.height - m_fCXBorder - FWL_CornerEnlarge,
    253            m_fCYBorder + FWL_CornerEnlarge, m_fCXBorder + FWL_CornerEnlarge);
    254     if (rt.Contains(fx, fy)) {
    255       return FWL_WGTHITTEST_RightBottom;
    256     }
    257   }
    258   return FWL_WGTHITTEST_Client;
    259 }
    260 FWL_ERR CFWL_FormImp::DrawWidget(CFX_Graphics* pGraphics,
    261                                  const CFX_Matrix* pMatrix) {
    262   if (!pGraphics)
    263     return FWL_ERR_Indefinite;
    264   if (!m_pProperties->m_pThemeProvider)
    265     return FWL_ERR_Indefinite;
    266   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    267   FX_BOOL bInactive = !IsActive();
    268   int32_t iState =
    269       bInactive ? FWL_PARTSTATE_FRM_Inactive : FWL_PARTSTATE_FRM_Normal;
    270   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_NoDrawClient) == 0) {
    271     DrawBackground(pGraphics, pTheme);
    272   }
    273 #ifdef FWL_UseMacSystemBorder
    274   return FWL_ERR_Succeeded;
    275 #endif
    276   CFWL_ThemeBackground param;
    277   param.m_pWidget = m_pInterface;
    278   param.m_dwStates = iState;
    279   param.m_pGraphics = pGraphics;
    280   param.m_rtPart = m_rtRelative;
    281   if (pMatrix) {
    282     param.m_matrix.Concat(*pMatrix);
    283   }
    284   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) {
    285     param.m_iPart = FWL_PART_FRM_Border;
    286     pTheme->DrawBackground(&param);
    287   }
    288   if ((m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_EdgeMask) !=
    289       FWL_WGTSTYLE_EdgeNone) {
    290     CFX_RectF rtEdge;
    291     GetEdgeRect(rtEdge);
    292     param.m_iPart = FWL_PART_FRM_Edge;
    293     param.m_rtPart = rtEdge;
    294     param.m_dwStates = iState;
    295     pTheme->DrawBackground(&param);
    296   }
    297   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Caption) {
    298     param.m_iPart = FWL_PART_FRM_Caption;
    299     param.m_dwStates = iState;
    300     param.m_rtPart = m_rtCaption;
    301     pTheme->DrawBackground(&param);
    302     DrawCaptionText(pGraphics, pTheme, pMatrix);
    303   } else if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_NarrowCaption) {
    304     param.m_iPart = FWL_PART_FRM_NarrowCaption;
    305     param.m_dwStates = iState;
    306     param.m_rtPart = m_rtCaption;
    307     pTheme->DrawBackground(&param);
    308     DrawCaptionText(pGraphics, pTheme, pMatrix);
    309   }
    310   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Icon) {
    311     param.m_iPart = FWL_PART_FRM_Icon;
    312     if (HasIcon()) {
    313       DrawIconImage(pGraphics, pTheme, pMatrix);
    314     }
    315   }
    316 #if (_FX_OS_ == _FX_MACOSX_)
    317   {
    318     if (m_pCloseBox) {
    319       param.m_iPart = FWL_PART_FRM_CloseBox;
    320       param.m_dwStates = m_pCloseBox->GetPartState();
    321       if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) {
    322         param.m_dwStates = FWL_PARTSTATE_FRM_Disabled;
    323       } else if (FWL_PARTSTATE_FRM_Normal == param.m_dwStates && m_bMouseIn) {
    324         param.m_dwStates = FWL_PARTSTATE_FRM_Hover;
    325       }
    326       param.m_rtPart = m_pCloseBox->m_rtBtn;
    327       pTheme->DrawBackground(&param);
    328     }
    329     if (m_pMaxBox) {
    330       param.m_iPart = FWL_PART_FRM_MaximizeBox;
    331       param.m_dwStates = m_pMaxBox->GetPartState();
    332       if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) {
    333         param.m_dwStates = FWL_PARTSTATE_FRM_Disabled;
    334       } else if (FWL_PARTSTATE_FRM_Normal == param.m_dwStates && m_bMouseIn) {
    335         param.m_dwStates = FWL_PARTSTATE_FRM_Hover;
    336       }
    337       param.m_rtPart = m_pMaxBox->m_rtBtn;
    338       param.m_dwData = m_bMaximized;
    339       pTheme->DrawBackground(&param);
    340     }
    341     if (m_pMinBox) {
    342       param.m_iPart = FWL_PART_FRM_MinimizeBox;
    343       param.m_dwStates = m_pMinBox->GetPartState();
    344       if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) {
    345         param.m_dwStates = FWL_PARTSTATE_FRM_Disabled;
    346       } else if (FWL_PARTSTATE_FRM_Normal == param.m_dwStates && m_bMouseIn) {
    347         param.m_dwStates = FWL_PARTSTATE_FRM_Hover;
    348       }
    349       param.m_rtPart = m_pMinBox->m_rtBtn;
    350       pTheme->DrawBackground(&param);
    351     }
    352     m_bMouseIn = FALSE;
    353   }
    354 #else
    355   {
    356     if (m_pCloseBox) {
    357       param.m_iPart = FWL_PART_FRM_CloseBox;
    358       param.m_dwStates = m_pCloseBox->GetPartState();
    359       param.m_rtPart = m_pCloseBox->m_rtBtn;
    360       pTheme->DrawBackground(&param);
    361     }
    362     if (m_pMaxBox) {
    363       param.m_iPart = FWL_PART_FRM_MaximizeBox;
    364       param.m_dwStates = m_pMaxBox->GetPartState();
    365       param.m_rtPart = m_pMaxBox->m_rtBtn;
    366       param.m_dwData = m_bMaximized;
    367       pTheme->DrawBackground(&param);
    368     }
    369     if (m_pMinBox) {
    370       param.m_iPart = FWL_PART_FRM_MinimizeBox;
    371       param.m_dwStates = m_pMinBox->GetPartState();
    372       param.m_rtPart = m_pMinBox->m_rtBtn;
    373       pTheme->DrawBackground(&param);
    374     }
    375   }
    376 #endif
    377   return FWL_ERR_Succeeded;
    378 }
    379 FWL_FORMSIZE CFWL_FormImp::GetFormSize() {
    380   return m_eFormSize;
    381 }
    382 FWL_ERR CFWL_FormImp::SetFormSize(FWL_FORMSIZE eFormSize) {
    383   m_eFormSize = eFormSize;
    384   return FWL_ERR_Succeeded;
    385 }
    386 IFWL_Widget* CFWL_FormImp::DoModal() {
    387   IFWL_NoteThread* pThread = GetOwnerThread();
    388   if (!pThread)
    389     return NULL;
    390   IFWL_NoteDriver* pDriver = pThread->GetNoteDriver();
    391   if (!pDriver)
    392     return NULL;
    393   m_pNoteLoop = new CFWL_NoteLoop(this);
    394   pDriver->PushNoteLoop(m_pNoteLoop);
    395   m_bDoModalFlag = TRUE;
    396   SetStates(FWL_WGTSTATE_Invisible, FALSE);
    397   pDriver->Run();
    398 #if (_FX_OS_ == _FX_MACOSX_)
    399 #else
    400   pDriver->PopNoteLoop();
    401 #endif
    402   delete m_pNoteLoop;
    403   m_pNoteLoop = NULL;
    404   return NULL;
    405 }
    406 IFWL_Widget* CFWL_FormImp::DoModal(FX_DWORD& dwCommandID) {
    407   return DoModal();
    408 }
    409 FWL_ERR CFWL_FormImp::EndDoModal() {
    410   if (!m_pNoteLoop)
    411     return FWL_ERR_Indefinite;
    412   m_bDoModalFlag = FALSE;
    413 #if (_FX_OS_ == _FX_MACOSX_)
    414   m_pNoteLoop->EndModalLoop();
    415   IFWL_NoteThread* pThread = GetOwnerThread();
    416   if (!pThread)
    417     return NULL;
    418   CFWL_NoteDriver* pDriver =
    419       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    420   if (!pDriver)
    421     return NULL;
    422   pDriver->PopNoteLoop();
    423   SetStates(FWL_WGTSTATE_Invisible, TRUE);
    424   return FWL_ERR_Succeeded;
    425 #else
    426   SetStates(FWL_WGTSTATE_Invisible, TRUE);
    427   return m_pNoteLoop->EndModalLoop();
    428 #endif
    429 }
    430 FWL_ERR CFWL_FormImp::SetBorderRegion(CFX_Path* pPath) {
    431   return FWL_ERR_Succeeded;
    432 }
    433 void CFWL_FormImp::DrawBackground(CFX_Graphics* pGraphics,
    434                                   IFWL_ThemeProvider* pTheme) {
    435   CFWL_ThemeBackground param;
    436   param.m_pWidget = m_pInterface;
    437   param.m_iPart = FWL_PART_FRM_Background;
    438   param.m_pGraphics = pGraphics;
    439   param.m_rtPart = m_rtRelative;
    440   param.m_rtPart.Deflate(m_fCYBorder, m_rtCaption.height, m_fCYBorder,
    441                          m_fCXBorder);
    442   pTheme->DrawBackground(&param);
    443 }
    444 CFWL_WidgetImp* CFWL_FormImp::GetSubFocus() {
    445   return m_pSubFocus;
    446 }
    447 void CFWL_FormImp::SetSubFocus(CFWL_WidgetImp* pWidget) {
    448   m_pSubFocus = pWidget;
    449 }
    450 CFX_MapAccelerators& CFWL_FormImp::GetAccelerator() {
    451   return m_mapAccelerators;
    452 }
    453 void CFWL_FormImp::SetAccelerator(CFX_MapAccelerators* pAccelerators) {
    454   if (!pAccelerators)
    455     return;
    456   m_mapAccelerators.RemoveAll();
    457   FX_DWORD vrKey, rValue;
    458   FX_POSITION pos = pAccelerators->GetStartPosition();
    459   while (pos) {
    460     pAccelerators->GetNextAssoc(pos, vrKey, rValue);
    461     m_mapAccelerators.SetAt(vrKey, rValue);
    462   }
    463 }
    464 void CFWL_FormImp::ShowChildWidget(IFWL_Widget* pParent) {
    465   IFWL_App* pApp = FWL_GetApp();
    466   if (!pApp)
    467     return;
    468   CFWL_WidgetMgr* pWidgetMgr =
    469       static_cast<CFWL_WidgetMgr*>(pApp->GetWidgetMgr());
    470   if (!pWidgetMgr)
    471     return;
    472   IFWL_Widget* pChild =
    473       pWidgetMgr->GetWidget(pParent, FWL_WGTRELATION_FirstChild);
    474   while (pChild) {
    475     pWidgetMgr->ShowWidget_Native(pChild);
    476     ShowChildWidget(pChild);
    477     pChild = pWidgetMgr->GetWidget(pChild, FWL_WGTRELATION_NextSibling);
    478   }
    479 }
    480 void CFWL_FormImp::RemoveSysButtons() {
    481   m_rtCaption.Reset();
    482   if (m_pCloseBox) {
    483     delete m_pCloseBox;
    484     m_pCloseBox = NULL;
    485   }
    486   if (m_pMinBox) {
    487     delete m_pMinBox;
    488     m_pMinBox = NULL;
    489   }
    490   if (m_pMaxBox) {
    491     delete m_pMaxBox;
    492     m_pMaxBox = NULL;
    493   }
    494   if (m_pCaptionBox) {
    495     delete m_pCaptionBox;
    496     m_pCaptionBox = NULL;
    497   }
    498 }
    499 void CFWL_FormImp::CalcContentRect(CFX_RectF& rtContent) {
    500 #ifdef FWL_UseMacSystemBorder
    501   rtContent = m_rtRelative;
    502 #else
    503   GetEdgeRect(rtContent);
    504   if (HasEdge()) {
    505     FX_FLOAT fEdge = GetEdgeWidth();
    506     rtContent.Deflate(fEdge, fEdge);
    507   }
    508 #endif
    509 }
    510 CFWL_SysBtn* CFWL_FormImp::GetSysBtnAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
    511   if (m_pCloseBox && m_pCloseBox->m_rtBtn.Contains(fx, fy)) {
    512     return m_pCloseBox;
    513   }
    514   if (m_pMaxBox && m_pMaxBox->m_rtBtn.Contains(fx, fy)) {
    515     return m_pMaxBox;
    516   }
    517   if (m_pMinBox && m_pMinBox->m_rtBtn.Contains(fx, fy)) {
    518     return m_pMinBox;
    519   }
    520   if (m_pCaptionBox && m_pCaptionBox->m_rtBtn.Contains(fx, fy)) {
    521     return m_pCaptionBox;
    522   }
    523   return NULL;
    524 }
    525 CFWL_SysBtn* CFWL_FormImp::GetSysBtnByState(FX_DWORD dwState) {
    526   if (m_pCloseBox && (m_pCloseBox->m_dwState & dwState)) {
    527     return m_pCloseBox;
    528   }
    529   if (m_pMaxBox && (m_pMaxBox->m_dwState & dwState)) {
    530     return m_pMaxBox;
    531   }
    532   if (m_pMinBox && (m_pMinBox->m_dwState & dwState)) {
    533     return m_pMinBox;
    534   }
    535   if (m_pCaptionBox && (m_pCaptionBox->m_dwState & dwState)) {
    536     return m_pCaptionBox;
    537   }
    538   return NULL;
    539 }
    540 CFWL_SysBtn* CFWL_FormImp::GetSysBtnByIndex(int32_t nIndex) {
    541   if (nIndex < 0) {
    542     return NULL;
    543   }
    544   CFX_PtrArray arrBtn;
    545   if (m_pMinBox) {
    546     arrBtn.Add(m_pMinBox);
    547   }
    548   if (m_pMaxBox) {
    549     arrBtn.Add(m_pMaxBox);
    550   }
    551   if (m_pCloseBox) {
    552     arrBtn.Add(m_pCloseBox);
    553   }
    554   return static_cast<CFWL_SysBtn*>(arrBtn[nIndex]);
    555 }
    556 int32_t CFWL_FormImp::GetSysBtnIndex(CFWL_SysBtn* pBtn) {
    557   CFX_PtrArray arrBtn;
    558   if (m_pMinBox) {
    559     arrBtn.Add(m_pMinBox);
    560   }
    561   if (m_pMaxBox) {
    562     arrBtn.Add(m_pMaxBox);
    563   }
    564   if (m_pCloseBox) {
    565     arrBtn.Add(m_pCloseBox);
    566   }
    567   return arrBtn.Find(pBtn);
    568 }
    569 FX_FLOAT CFWL_FormImp::GetCaptionHeight() {
    570   FX_DWORD dwCapacity = 0;
    571   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Caption) {
    572     dwCapacity = FWL_WGTCAPACITY_FRM_CYCaption;
    573   } else if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_NarrowCaption) {
    574     dwCapacity = FWL_WGTCAPACITY_FRM_CYNarrowCaption;
    575   }
    576   if (dwCapacity > 0) {
    577     FX_FLOAT* pfCapHeight =
    578         static_cast<FX_FLOAT*>(GetThemeCapacity(dwCapacity));
    579     return pfCapHeight ? *pfCapHeight : 0;
    580   }
    581   return 0;
    582 }
    583 void CFWL_FormImp::DrawCaptionText(CFX_Graphics* pGs,
    584                                    IFWL_ThemeProvider* pTheme,
    585                                    const CFX_Matrix* pMatrix) {
    586   CFX_WideString wsText;
    587   IFWL_DataProvider* pData = m_pProperties->m_pDataProvider;
    588   pData->GetCaption(m_pInterface, wsText);
    589   if (wsText.IsEmpty()) {
    590     return;
    591   }
    592   CFWL_ThemeText textParam;
    593   textParam.m_pWidget = m_pInterface;
    594   textParam.m_iPart = FWL_PART_FRM_Caption;
    595   textParam.m_dwStates = FWL_PARTSTATE_FRM_Normal;
    596   textParam.m_pGraphics = pGs;
    597   if (pMatrix) {
    598     textParam.m_matrix.Concat(*pMatrix);
    599   }
    600   CFX_RectF rtText;
    601   if (m_bCustomizeLayout) {
    602     rtText = m_rtCaptionText;
    603     rtText.top -= 5;
    604   } else {
    605     rtText = m_rtCaption;
    606     FX_FLOAT fpos;
    607     fpos = HasIcon() ? 29.0f : 13.0f;
    608     rtText.left += fpos;
    609   }
    610   textParam.m_rtPart = rtText;
    611   textParam.m_wsText = wsText;
    612   textParam.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine | FDE_TTOSTYLE_Ellipsis;
    613   textParam.m_iTTOAlign = m_bCustomizeLayout ? FDE_TTOALIGNMENT_Center
    614                                              : FDE_TTOALIGNMENT_CenterLeft;
    615   pTheme->DrawText(&textParam);
    616 }
    617 void CFWL_FormImp::DrawIconImage(CFX_Graphics* pGs,
    618                                  IFWL_ThemeProvider* pTheme,
    619                                  const CFX_Matrix* pMatrix) {
    620   IFWL_FormDP* pData =
    621       static_cast<IFWL_FormDP*>(m_pProperties->m_pDataProvider);
    622   CFWL_ThemeBackground param;
    623   param.m_pWidget = m_pInterface;
    624   param.m_iPart = FWL_PART_FRM_Icon;
    625   param.m_pGraphics = pGs;
    626   param.m_pImage = pData->GetIcon(m_pInterface, FALSE);
    627   param.m_rtPart = m_rtIcon;
    628   if (pMatrix) {
    629     param.m_matrix.Concat(*pMatrix);
    630   }
    631   pTheme->DrawBackground(&param);
    632 }
    633 void CFWL_FormImp::GetEdgeRect(CFX_RectF& rtEdge) {
    634   rtEdge = m_rtRelative;
    635   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) {
    636     FX_FLOAT fCX = GetBorderSize();
    637     FX_FLOAT fCY = GetBorderSize(FALSE);
    638     rtEdge.Deflate(fCX, m_rtCaption.Height(), fCX, fCY);
    639   }
    640 }
    641 void CFWL_FormImp::SetWorkAreaRect() {
    642   m_rtRestore = m_pProperties->m_rtWidget;
    643   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    644   if (!pWidgetMgr)
    645     return;
    646   m_bSetMaximize = TRUE;
    647   pWidgetMgr->SetMaximize_Native(m_pInterface);
    648   Repaint(&m_rtRelative);
    649 }
    650 void CFWL_FormImp::SetCursor(FX_FLOAT fx, FX_FLOAT fy) {
    651   IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
    652   IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr();
    653   if (!pCursorMgr)
    654     return;
    655   FX_DWORD dwHitTest = HitTest(fx, fy);
    656   switch (dwHitTest) {
    657     case FWL_WGTHITTEST_Right: {
    658       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeWE);
    659       pCursorMgr->SetCursor(hCursor);
    660       pCursorMgr->ShowCursor(TRUE);
    661       m_eResizeType = FORM_RESIZETYPE_Right;
    662       break;
    663     }
    664     case FWL_WGTHITTEST_Bottom: {
    665       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);
    666       pCursorMgr->SetCursor(hCursor);
    667       pCursorMgr->ShowCursor(TRUE);
    668       m_eResizeType = FORM_RESIZETYPE_Bottom;
    669       break;
    670     }
    671     case FWL_WGTHITTEST_Left: {
    672       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeWE);
    673       pCursorMgr->SetCursor(hCursor);
    674       pCursorMgr->ShowCursor(TRUE);
    675       m_eResizeType = FORM_RESIZETYPE_Left;
    676       break;
    677     }
    678     case FWL_WGTHITTEST_Top: {
    679       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);
    680       pCursorMgr->SetCursor(hCursor);
    681       pCursorMgr->ShowCursor(TRUE);
    682       m_eResizeType = FORM_RESIZETYPE_Top;
    683       break;
    684     }
    685     case FWL_WGTHITTEST_LeftTop: {
    686       FWL_HCURSOR hCursor =
    687           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNWSE);
    688       pCursorMgr->SetCursor(hCursor);
    689       pCursorMgr->ShowCursor(TRUE);
    690       m_eResizeType = FORM_RESIZETYPE_LeftTop;
    691       break;
    692     }
    693     case FWL_WGTHITTEST_LeftBottom: {
    694       FWL_HCURSOR hCursor =
    695           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNESW);
    696       pCursorMgr->SetCursor(hCursor);
    697       pCursorMgr->ShowCursor(TRUE);
    698       m_eResizeType = FORM_RESIZETYPE_LeftBottom;
    699       break;
    700     }
    701     case FWL_WGTHITTEST_RightTop: {
    702       FWL_HCURSOR hCursor =
    703           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNESW);
    704       pCursorMgr->SetCursor(hCursor);
    705       pCursorMgr->ShowCursor(TRUE);
    706       m_eResizeType = FORM_RESIZETYPE_RightTop;
    707       break;
    708     }
    709     case FWL_WGTHITTEST_RightBottom: {
    710       FWL_HCURSOR hCursor =
    711           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNWSE);
    712       pCursorMgr->SetCursor(hCursor);
    713       pCursorMgr->ShowCursor(TRUE);
    714       m_eResizeType = FORM_RESIZETYPE_RightBottom;
    715       break;
    716     }
    717     default: {
    718       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_Arrow);
    719       pCursorMgr->SetCursor(hCursor);
    720       pCursorMgr->ShowCursor(TRUE);
    721     }
    722   }
    723 }
    724 void CFWL_FormImp::Layout() {
    725   GetRelativeRect(m_rtRelative);
    726 #ifndef FWL_UseMacSystemBorder
    727   ReSetSysBtn();
    728 #endif
    729   if (m_pContent) {
    730     CFX_RectF rtClient;
    731     GetClientRect(rtClient);
    732     m_pContent->SetWidgetRect(rtClient);
    733     m_pContent->Update();
    734   }
    735 }
    736 void CFWL_FormImp::ReSetSysBtn() {
    737   m_fCXBorder =
    738       *static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_CXBorder));
    739   m_fCYBorder =
    740       *static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_CYBorder));
    741   RemoveSysButtons();
    742   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    743   m_bCustomizeLayout = pTheme->IsCustomizedLayout(m_pInterface);
    744   FX_FLOAT fCapHeight = GetCaptionHeight();
    745   if (fCapHeight > 0) {
    746     m_rtCaption = m_rtRelative;
    747     m_rtCaption.height = fCapHeight;
    748   }
    749   m_iSysBox = 0;
    750   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_CloseBox) {
    751     m_pCloseBox = new CFWL_SysBtn;
    752     if (m_bCustomizeLayout) {
    753       CFWL_ThemeBackground param;
    754       param.m_pWidget = m_pInterface;
    755       param.m_iPart = FWL_PART_FRM_CloseBox;
    756       pTheme->GetPartRect(&param, m_pCloseBox->m_rtBtn);
    757     } else {
    758       m_pCloseBox->m_rtBtn.Set(
    759           m_rtRelative.right() - FWL_SYSBTNMARGIN - FWL_SYSBTNSIZE,
    760           FWL_SYSBTNMARGIN, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    761     }
    762     m_iSysBox++;
    763   }
    764   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_MaximizeBox) {
    765     m_pMaxBox = new CFWL_SysBtn;
    766     if (m_bCustomizeLayout) {
    767       CFWL_ThemeBackground param;
    768       param.m_pWidget = m_pInterface;
    769       param.m_iPart = FWL_PART_FRM_MaximizeBox;
    770       pTheme->GetPartRect(&param, m_pMaxBox->m_rtBtn);
    771     } else {
    772       if (m_pCloseBox) {
    773         m_pMaxBox->m_rtBtn.Set(
    774             m_pCloseBox->m_rtBtn.left - FWL_SYSBTNSPAN - FWL_SYSBTNSIZE,
    775             m_pCloseBox->m_rtBtn.top, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    776       } else {
    777         m_pMaxBox->m_rtBtn.Set(
    778             m_rtRelative.right() - FWL_SYSBTNMARGIN - FWL_SYSBTNSIZE,
    779             FWL_SYSBTNMARGIN, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    780       }
    781     }
    782     m_iSysBox++;
    783   }
    784   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_MinimizeBox) {
    785     m_pMinBox = new CFWL_SysBtn;
    786     if (m_bCustomizeLayout) {
    787       CFWL_ThemeBackground param;
    788       param.m_pWidget = m_pInterface;
    789       param.m_iPart = FWL_PART_FRM_MinimizeBox;
    790       pTheme->GetPartRect(&param, m_pMinBox->m_rtBtn);
    791     } else {
    792       if (m_pMaxBox) {
    793         m_pMinBox->m_rtBtn.Set(
    794             m_pMaxBox->m_rtBtn.left - FWL_SYSBTNSPAN - FWL_SYSBTNSIZE,
    795             m_pMaxBox->m_rtBtn.top, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    796       } else if (m_pCloseBox) {
    797         m_pMinBox->m_rtBtn.Set(
    798             m_pCloseBox->m_rtBtn.left - FWL_SYSBTNSPAN - FWL_SYSBTNSIZE,
    799             m_pCloseBox->m_rtBtn.top, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    800       } else {
    801         m_pMinBox->m_rtBtn.Set(
    802             m_rtRelative.right() - FWL_SYSBTNMARGIN - FWL_SYSBTNSIZE,
    803             FWL_SYSBTNMARGIN, FWL_SYSBTNSIZE, FWL_SYSBTNSIZE);
    804       }
    805     }
    806     m_iSysBox++;
    807   }
    808   IFWL_FormDP* pData =
    809       static_cast<IFWL_FormDP*>(m_pProperties->m_pDataProvider);
    810   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Icon &&
    811       pData->GetIcon(m_pInterface, FALSE)) {
    812     if (m_bCustomizeLayout) {
    813       CFWL_ThemeBackground param;
    814       param.m_pWidget = m_pInterface;
    815       param.m_iPart = FWL_PART_FRM_Icon;
    816       CFX_WideString wsText;
    817       m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsText);
    818       param.m_pData = &wsText;
    819       pTheme->GetPartRect(&param, m_rtIcon);
    820     } else {
    821       m_rtIcon.Set(5, (m_rtCaption.height - m_fSmallIconSz) / 2, m_fSmallIconSz,
    822                    m_fSmallIconSz);
    823     }
    824   }
    825   if (m_bCustomizeLayout) {
    826     CFWL_ThemeText parma;
    827     parma.m_pWidget = m_pInterface;
    828     parma.m_iPart = FWL_PART_FRM_HeadText;
    829     m_pProperties->m_pDataProvider->GetCaption(m_pInterface, parma.m_wsText);
    830     pTheme->GetPartRect(&parma, m_rtCaptionText);
    831   }
    832 }
    833 void CFWL_FormImp::RegisterForm() {
    834   IFWL_NoteThread* pThread = GetOwnerThread();
    835   if (!pThread)
    836     return;
    837   CFWL_NoteDriver* pDriver =
    838       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    839   if (!pDriver)
    840     return;
    841   pDriver->RegisterForm(this);
    842 }
    843 void CFWL_FormImp::UnRegisterForm() {
    844   IFWL_NoteThread* pThread = GetOwnerThread();
    845   if (!pThread)
    846     return;
    847   CFWL_NoteDriver* pDriver =
    848       static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    849   if (!pDriver)
    850     return;
    851   pDriver->UnRegisterForm(this);
    852 }
    853 FX_BOOL CFWL_FormImp::IsDoModal() {
    854   return m_bDoModalFlag;
    855 }
    856 void CFWL_FormImp::SetThemeData() {
    857   m_fSmallIconSz =
    858       *static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FRM_SmallIcon));
    859   m_fBigIconSz =
    860       *static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FRM_BigIcon));
    861 }
    862 FX_BOOL CFWL_FormImp::HasIcon() {
    863   IFWL_FormDP* pData =
    864       static_cast<IFWL_FormDP*>(m_pProperties->m_pDataProvider);
    865   return !!pData->GetIcon(m_pInterface, FALSE);
    866 }
    867 void CFWL_FormImp::UpdateIcon() {
    868   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    869   if (!pWidgetMgr)
    870     return;
    871   IFWL_FormDP* pData =
    872       static_cast<IFWL_FormDP*>(m_pProperties->m_pDataProvider);
    873   CFX_DIBitmap* pBigIcon = pData->GetIcon(m_pInterface, TRUE);
    874   CFX_DIBitmap* pSmallIcon = pData->GetIcon(m_pInterface, FALSE);
    875   if (pBigIcon && pBigIcon != m_pBigIcon) {
    876     m_pBigIcon = pBigIcon;
    877     pWidgetMgr->SetWidgetIcon_Native(m_pInterface, m_pBigIcon, TRUE);
    878   }
    879   if (pSmallIcon && pSmallIcon != m_pSmallIcon) {
    880     m_pSmallIcon = pSmallIcon;
    881     pWidgetMgr->SetWidgetIcon_Native(m_pInterface, m_pBigIcon, FALSE);
    882   }
    883 }
    884 void CFWL_FormImp::UpdateCaption() {
    885   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
    886   if (!pWidgetMgr)
    887     return;
    888   IFWL_FormDP* pData =
    889       static_cast<IFWL_FormDP*>(m_pProperties->m_pDataProvider);
    890   if (!pData)
    891     return;
    892   CFX_WideString text;
    893   pData->GetCaption(m_pInterface, text);
    894   pWidgetMgr->SetWidgetCaption_Native(m_pInterface, text);
    895 }
    896 void CFWL_FormImp::DoWidthLimit(FX_FLOAT& fLeft,
    897                                 FX_FLOAT& fWidth,
    898                                 FX_FLOAT fCurX,
    899                                 FX_FLOAT fSpace,
    900                                 FX_FLOAT fLimitMin,
    901                                 FX_FLOAT fLimitMax,
    902                                 FX_BOOL bLeft) {
    903   FX_FLOAT fx = fCurX;
    904   FX_FLOAT fy = 0;
    905   TransformTo(NULL, fx, fy);
    906   FX_FLOAT fTemp =
    907       bLeft ? (fWidth - fx + fLeft + fSpace) : (fx - fLeft + fSpace);
    908   if (fTemp >= fLimitMin && fTemp <= fLimitMax) {
    909     fWidth = fTemp;
    910     fLeft += bLeft ? (fx - fLeft - fSpace) : 0;
    911   } else {
    912     if (fTemp < fLimitMin && fWidth > fLimitMin) {
    913       fLeft += bLeft ? (fWidth - fLimitMin) : 0;
    914       fWidth = fLimitMin;
    915     } else if (fTemp > fLimitMax && fWidth < fLimitMax) {
    916       fLeft -= bLeft ? (fLimitMax - fWidth) : 0;
    917       fWidth = fLimitMax;
    918     }
    919   }
    920 }
    921 void CFWL_FormImp::DoHeightLimit(FX_FLOAT& fTop,
    922                                  FX_FLOAT& fHeight,
    923                                  FX_FLOAT fCurY,
    924                                  FX_FLOAT fSpace,
    925                                  FX_FLOAT fLimitMin,
    926                                  FX_FLOAT fLimitMax,
    927                                  FX_BOOL bTop) {
    928   FX_FLOAT fx = 0;
    929   FX_FLOAT fy = fCurY;
    930   TransformTo(NULL, fx, fy);
    931   FX_FLOAT fTemp = bTop ? (fHeight - fy + fTop + fSpace) : (fy - fTop + fSpace);
    932   if (fTemp >= fLimitMin && fTemp <= fLimitMax) {
    933     fHeight = fTemp;
    934     fTop += bTop ? (fy - fTop - fSpace) : 0;
    935   } else {
    936     if (fTemp < fLimitMin && fHeight > fLimitMin) {
    937       fTop += bTop ? (fHeight - fLimitMin) : 0;
    938       fHeight = fLimitMin;
    939     } else if (fTemp > fLimitMax && fHeight < fLimitMax) {
    940       fTop -= bTop ? (fLimitMax - fHeight) : 0;
    941       fHeight = fLimitMax;
    942     }
    943   }
    944 }
    945 CFWL_FormImpDelegate::CFWL_FormImpDelegate(CFWL_FormImp* pOwner)
    946     : m_pOwner(pOwner) {
    947 }
    948 int32_t CFWL_FormImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
    949 #ifdef FWL_UseMacSystemBorder
    950   if (!pMessage)
    951     return 0;
    952   FX_DWORD dwMsgCode = pMessage->GetClassID();
    953   int32_t iRet = 1;
    954   switch (dwMsgCode) {
    955     case FWL_MSGHASH_Activate: {
    956       m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Deactivated;
    957       m_pOwner->Repaint(&m_pOwner->m_rtRelative);
    958       break;
    959     }
    960     case FWL_MSGHASH_Deactivate: {
    961       m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Deactivated;
    962       m_pOwner->Repaint(&m_pOwner->m_rtRelative);
    963       break;
    964     }
    965   }
    966   return FWL_ERR_Succeeded;
    967 #else
    968   if (!pMessage)
    969     return 0;
    970   FX_DWORD dwMsgCode = pMessage->GetClassID();
    971   int32_t iRet = 1;
    972   switch (dwMsgCode) {
    973     case FWL_MSGHASH_Activate: {
    974       m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Deactivated;
    975       IFWL_NoteThread* pThread = m_pOwner->GetOwnerThread();
    976       CFWL_NoteDriver* pDriver =
    977           static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    978       CFWL_WidgetImp* pSubFocusImp = m_pOwner->GetSubFocus();
    979       IFWL_Widget* pSubFocus =
    980           pSubFocusImp ? pSubFocusImp->GetInterface() : NULL;
    981       if (pSubFocus && pSubFocus != pDriver->GetFocus()) {
    982         pDriver->SetFocus(pSubFocus);
    983       }
    984       m_pOwner->Repaint(&m_pOwner->m_rtRelative);
    985       break;
    986     }
    987     case FWL_MSGHASH_Deactivate: {
    988       m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Deactivated;
    989       IFWL_NoteThread* pThread = m_pOwner->GetOwnerThread();
    990       CFWL_NoteDriver* pDriver =
    991           static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
    992       CFWL_WidgetImp* pSubFocusImp = m_pOwner->GetSubFocus();
    993       IFWL_Widget* pSubFocus =
    994           pSubFocusImp ? pSubFocusImp->GetInterface() : NULL;
    995       if (pSubFocus) {
    996         if (pSubFocus == pDriver->GetFocus()) {
    997           pDriver->SetFocus(NULL);
    998         } else if (pSubFocus->GetStates() & FWL_WGTSTATE_Focused) {
    999           CFWL_MsgKillFocus ms;
   1000           IFWL_WidgetDelegate* pDelegate = pSubFocus->SetDelegate(NULL);
   1001           if (pDelegate) {
   1002             pDelegate->OnProcessMessage(&ms);
   1003           }
   1004         }
   1005       }
   1006       m_pOwner->Repaint(&m_pOwner->m_rtRelative);
   1007       break;
   1008     }
   1009     case FWL_MSGHASH_Mouse: {
   1010       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1011       switch (pMsg->m_dwCmd) {
   1012         case FWL_MSGMOUSECMD_LButtonDown: {
   1013           OnLButtonDown(pMsg);
   1014           break;
   1015         }
   1016         case FWL_MSGMOUSECMD_LButtonUp: {
   1017           OnLButtonUp(pMsg);
   1018           break;
   1019         }
   1020         case FWL_MSGMOUSECMD_MouseMove: {
   1021           OnMouseMove(pMsg);
   1022           break;
   1023         }
   1024         case FWL_MSGMOUSECMD_MouseHover: {
   1025           OnMouseHover(pMsg);
   1026           break;
   1027         }
   1028         case FWL_MSGMOUSECMD_MouseLeave: {
   1029           OnMouseLeave(pMsg);
   1030           break;
   1031         }
   1032         case FWL_MSGMOUSECMD_LButtonDblClk: {
   1033           OnLButtonDblClk(pMsg);
   1034           break;
   1035         }
   1036       }
   1037       break;
   1038     }
   1039     case FWL_MSGHASH_Size: {
   1040       CFWL_WidgetMgr* pWidgetMgr =
   1041           static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
   1042       if (!pWidgetMgr)
   1043         return 0;
   1044       pWidgetMgr->AddRedrawCounts(m_pOwner->m_pInterface);
   1045       if (!m_pOwner->m_bSetMaximize) {
   1046         break;
   1047       }
   1048       m_pOwner->m_bSetMaximize = FALSE;
   1049       CFWL_MsgSize* pMsg = static_cast<CFWL_MsgSize*>(pMessage);
   1050       CFX_RectF rt;
   1051       pWidgetMgr->GetWidgetRect_Native(m_pOwner->m_pInterface, rt);
   1052       m_pOwner->m_pProperties->m_rtWidget.left = rt.left;
   1053       m_pOwner->m_pProperties->m_rtWidget.top = rt.top;
   1054       m_pOwner->m_pProperties->m_rtWidget.width = (FX_FLOAT)pMsg->m_iWidth;
   1055       m_pOwner->m_pProperties->m_rtWidget.height = (FX_FLOAT)pMsg->m_iHeight;
   1056       m_pOwner->Update();
   1057       break;
   1058     }
   1059     case FWL_MSGHASH_WindowMove: {
   1060       OnWindowMove(static_cast<CFWL_MsgWindowMove*>(pMessage));
   1061       break;
   1062     }
   1063     case FWL_MSGHASH_Close: {
   1064       OnClose(static_cast<CFWL_MsgClose*>(pMessage));
   1065       break;
   1066     }
   1067     default: { iRet = 0; }
   1068   }
   1069   return iRet;
   1070 #endif
   1071 }
   1072 FWL_ERR CFWL_FormImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
   1073   if (!pEvent)
   1074     return FWL_ERR_Indefinite;
   1075   if (pEvent->GetClassID() == FWL_EVTHASH_Close &&
   1076       pEvent->m_pSrcTarget == m_pOwner->m_pInterface) {
   1077   }
   1078   return FWL_ERR_Succeeded;
   1079 }
   1080 FWL_ERR CFWL_FormImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1081                                            const CFX_Matrix* pMatrix) {
   1082   return m_pOwner->DrawWidget(pGraphics, pMatrix);
   1083 }
   1084 void CFWL_FormImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
   1085   m_pOwner->SetGrab(TRUE);
   1086   m_pOwner->m_bLButtonDown = TRUE;
   1087   m_pOwner->m_eResizeType = FORM_RESIZETYPE_None;
   1088   CFWL_SysBtn* pPressBtn = m_pOwner->GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy);
   1089   m_pOwner->m_iCaptureBtn = m_pOwner->GetSysBtnIndex(pPressBtn);
   1090   CFX_RectF rtCap;
   1091   rtCap.Set(m_pOwner->m_rtCaption.left + m_pOwner->m_fCYBorder,
   1092             m_pOwner->m_rtCaption.top + m_pOwner->m_fCXBorder,
   1093             m_pOwner->m_rtCaption.width - FWL_SYSBTNSIZE * m_pOwner->m_iSysBox -
   1094                 2 * m_pOwner->m_fCYBorder,
   1095             m_pOwner->m_rtCaption.height - m_pOwner->m_fCXBorder);
   1096   if (pPressBtn) {
   1097     pPressBtn->SetPressed();
   1098     m_pOwner->Repaint(&pPressBtn->m_rtBtn);
   1099   } else if (rtCap.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1100     m_pOwner->m_eResizeType = FORM_RESIZETYPE_Cap;
   1101   } else if ((m_pOwner->m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) &&
   1102              (m_pOwner->m_pProperties->m_dwStyleExes &
   1103               FWL_STYLEEXT_FRM_Resize) &&
   1104              !m_pOwner->m_bMaximized) {
   1105     m_pOwner->SetCursor(pMsg->m_fx, pMsg->m_fy);
   1106   }
   1107   m_pOwner->m_InfoStart.m_ptStart.Set(pMsg->m_fx, pMsg->m_fy);
   1108   m_pOwner->m_InfoStart.m_szStart.Set(
   1109       m_pOwner->m_pProperties->m_rtWidget.width,
   1110       m_pOwner->m_pProperties->m_rtWidget.height);
   1111 }
   1112 void CFWL_FormImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
   1113   m_pOwner->SetGrab(FALSE);
   1114   m_pOwner->m_bLButtonDown = FALSE;
   1115   CFWL_SysBtn* pPointBtn = m_pOwner->GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy);
   1116   CFWL_SysBtn* pPressedBtn =
   1117       m_pOwner->GetSysBtnByIndex(m_pOwner->m_iCaptureBtn);
   1118   if (!pPressedBtn || pPointBtn != pPressedBtn) {
   1119     return;
   1120   }
   1121   if (pPressedBtn == m_pOwner->GetSysBtnByState(FWL_SYSBUTTONSTATE_Pressed)) {
   1122     pPressedBtn->SetNormal();
   1123   }
   1124   if (pPressedBtn == m_pOwner->m_pMaxBox) {
   1125     if (m_pOwner->m_bMaximized) {
   1126       m_pOwner->SetWidgetRect(m_pOwner->m_rtRestore);
   1127       m_pOwner->Update();
   1128       m_pOwner->Repaint();
   1129     } else {
   1130       m_pOwner->SetWorkAreaRect();
   1131       m_pOwner->Update();
   1132     }
   1133     m_pOwner->m_bMaximized = !m_pOwner->m_bMaximized;
   1134   } else if (pPressedBtn == m_pOwner->m_pMinBox) {
   1135     CFWL_WidgetMgr* pWidgetMgr =
   1136         static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
   1137     if (!pWidgetMgr)
   1138       return;
   1139     pWidgetMgr->SetMinimize_Native(m_pOwner->m_pInterface);
   1140   } else {
   1141     CFWL_EvtClose eClose;
   1142     eClose.m_pSrcTarget = m_pOwner->m_pInterface;
   1143     m_pOwner->DispatchEvent(&eClose);
   1144   }
   1145 }
   1146 void CFWL_FormImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
   1147   CFWL_WidgetMgr* pWidgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr());
   1148   if (m_pOwner->m_bLButtonDown) {
   1149     IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
   1150     IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr();
   1151     if (!pCursorMgr)
   1152       return;
   1153     CFWL_SysBtn* pPressedBtn =
   1154         m_pOwner->GetSysBtnByIndex(m_pOwner->m_iCaptureBtn);
   1155     FX_FLOAT fTop, fLeft, fWidth, fHeight;
   1156     fTop = m_pOwner->m_pProperties->m_rtWidget.top;
   1157     fLeft = m_pOwner->m_pProperties->m_rtWidget.left;
   1158     fWidth = m_pOwner->m_pProperties->m_rtWidget.width;
   1159     fHeight = m_pOwner->m_pProperties->m_rtWidget.height;
   1160     FX_FLOAT fWidthMax, fWidthMin, fHeightMax, fHeightMin;
   1161     if (m_pOwner->m_pContent) {
   1162       m_pOwner->GetContent()->GetMaxSize(fWidthMax, fHeightMax);
   1163       m_pOwner->GetContent()->GetMinSize(fWidthMin, fHeightMin);
   1164     } else {
   1165       fWidthMax = fHeightMax = 1024 * 4;
   1166       fWidthMin = fHeightMin = 0;
   1167     }
   1168     FX_BOOL bWidthlimit = (fWidthMin != 0 || fWidthMax != 0);
   1169     FX_BOOL bHeightlimit = (fHeightMin != 0 || fHeightMax != 0);
   1170     FX_BOOL bSizelimit = bWidthlimit || bHeightlimit;
   1171     if (fWidthMax != 0 || fHeightMax != 0 || fWidthMin != 0 ||
   1172         fHeightMin != 0) {
   1173       bSizelimit = TRUE;
   1174     }
   1175     if (pPressedBtn) {
   1176       if (!pPressedBtn->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1177         pPressedBtn->SetNormal();
   1178       } else {
   1179         pPressedBtn->SetPressed();
   1180       }
   1181       m_pOwner->Repaint(&pPressedBtn->m_rtBtn);
   1182       return;
   1183     } else if (m_pOwner->m_bMaximized) {
   1184       return;
   1185     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_Cap) {
   1186       m_pOwner->m_pProperties->m_rtWidget.Offset(
   1187           pMsg->m_fx - m_pOwner->m_InfoStart.m_ptStart.x,
   1188           pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y);
   1189       pWidgetMgr->SetWidgetPosition_Native(
   1190           m_pOwner->m_pInterface, m_pOwner->m_pProperties->m_rtWidget.left,
   1191           m_pOwner->m_pProperties->m_rtWidget.top);
   1192       return;
   1193     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_Right) {
   1194       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeWE);
   1195       pCursorMgr->SetCursor(hCursor);
   1196       pCursorMgr->ShowCursor(TRUE);
   1197       if (!bWidthlimit) {
   1198         fWidth += pMsg->m_fx - m_pOwner->m_InfoStart.m_ptStart.x;
   1199         m_pOwner->m_InfoStart.m_ptStart.x = pMsg->m_fx;
   1200       } else {
   1201         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1202                                m_pOwner->m_InfoStart.m_szStart.x -
   1203                                    m_pOwner->m_InfoStart.m_ptStart.x,
   1204                                fWidthMin, fWidthMax, FALSE);
   1205       }
   1206     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_Left) {
   1207       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeWE);
   1208       pCursorMgr->SetCursor(hCursor);
   1209       pCursorMgr->ShowCursor(TRUE);
   1210       if (!bWidthlimit) {
   1211         fLeft -= m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1212         fWidth += m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1213       } else {
   1214         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1215                                m_pOwner->m_InfoStart.m_ptStart.x, fWidthMin,
   1216                                fWidthMax, TRUE);
   1217       }
   1218     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_Bottom) {
   1219       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);
   1220       pCursorMgr->SetCursor(hCursor);
   1221       pCursorMgr->ShowCursor(TRUE);
   1222       if (!bHeightlimit) {
   1223         fHeight += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1224         m_pOwner->m_InfoStart.m_ptStart.y = pMsg->m_fy;
   1225       } else {
   1226         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1227                                 m_pOwner->m_InfoStart.m_szStart.y -
   1228                                     m_pOwner->m_InfoStart.m_ptStart.y,
   1229                                 fHeightMin, fHeightMax, FALSE);
   1230       }
   1231     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_Top) {
   1232       FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS);
   1233       pCursorMgr->SetCursor(hCursor);
   1234       pCursorMgr->ShowCursor(TRUE);
   1235       if (!bHeightlimit) {
   1236         fTop += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1237         fHeight -= pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1238       } else {
   1239         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1240                                 m_pOwner->m_InfoStart.m_ptStart.y, fHeightMin,
   1241                                 fHeightMax, TRUE);
   1242       }
   1243     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_LeftTop) {
   1244       FWL_HCURSOR hCursor =
   1245           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNWSE);
   1246       pCursorMgr->SetCursor(hCursor);
   1247       pCursorMgr->ShowCursor(TRUE);
   1248       if (!bSizelimit) {
   1249         fLeft -= m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1250         fTop += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1251         fWidth += m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1252         fHeight -= pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1253         m_pOwner->m_InfoStart.m_ptStart.x = pMsg->m_fx;
   1254         m_pOwner->m_InfoStart.m_ptStart.y = pMsg->m_fy;
   1255       } else {
   1256         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1257                                m_pOwner->m_InfoStart.m_ptStart.x, fWidthMin,
   1258                                fWidthMax, TRUE);
   1259         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1260                                 m_pOwner->m_InfoStart.m_ptStart.y, fHeightMin,
   1261                                 fHeightMax, TRUE);
   1262       }
   1263     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_LeftBottom) {
   1264       FWL_HCURSOR hCursor =
   1265           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNESW);
   1266       pCursorMgr->SetCursor(hCursor);
   1267       pCursorMgr->ShowCursor(TRUE);
   1268       if (!bSizelimit) {
   1269         fLeft -= m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1270         fWidth += m_pOwner->m_InfoStart.m_ptStart.x - pMsg->m_fx;
   1271         fHeight += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1272         m_pOwner->m_InfoStart.m_ptStart.x = pMsg->m_fx;
   1273         m_pOwner->m_InfoStart.m_ptStart.y = pMsg->m_fy;
   1274       } else {
   1275         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1276                                m_pOwner->m_InfoStart.m_ptStart.x, fWidthMin,
   1277                                fWidthMax, TRUE);
   1278         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1279                                 m_pOwner->m_InfoStart.m_szStart.y -
   1280                                     m_pOwner->m_InfoStart.m_ptStart.y,
   1281                                 fHeightMin, fHeightMax, FALSE);
   1282       }
   1283     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_RightTop) {
   1284       FWL_HCURSOR hCursor =
   1285           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNESW);
   1286       pCursorMgr->SetCursor(hCursor);
   1287       pCursorMgr->ShowCursor(TRUE);
   1288       if (!bSizelimit) {
   1289         fTop += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1290         fWidth += pMsg->m_fx - m_pOwner->m_InfoStart.m_ptStart.x;
   1291         fHeight -= pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1292         m_pOwner->m_InfoStart.m_ptStart.x = pMsg->m_fx;
   1293         m_pOwner->m_InfoStart.m_ptStart.y = pMsg->m_fy;
   1294       } else {
   1295         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1296                                m_pOwner->m_InfoStart.m_szStart.x -
   1297                                    m_pOwner->m_InfoStart.m_ptStart.x,
   1298                                fWidthMin, fWidthMax, FALSE);
   1299         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1300                                 m_pOwner->m_InfoStart.m_ptStart.y, fHeightMin,
   1301                                 fHeightMax, TRUE);
   1302       }
   1303     } else if (m_pOwner->m_eResizeType == FORM_RESIZETYPE_RightBottom) {
   1304       FWL_HCURSOR hCursor =
   1305           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNWSE);
   1306       pCursorMgr->SetCursor(hCursor);
   1307       pCursorMgr->ShowCursor(TRUE);
   1308       if (!bSizelimit) {
   1309         fWidth += pMsg->m_fx - m_pOwner->m_InfoStart.m_ptStart.x;
   1310         fHeight += pMsg->m_fy - m_pOwner->m_InfoStart.m_ptStart.y;
   1311         m_pOwner->m_InfoStart.m_ptStart.x = pMsg->m_fx;
   1312         m_pOwner->m_InfoStart.m_ptStart.y = pMsg->m_fy;
   1313       } else {
   1314         m_pOwner->DoWidthLimit(fLeft, fWidth, pMsg->m_fx,
   1315                                m_pOwner->m_InfoStart.m_szStart.x -
   1316                                    m_pOwner->m_InfoStart.m_ptStart.x,
   1317                                fWidthMin, fWidthMax, FALSE);
   1318         m_pOwner->DoHeightLimit(fTop, fHeight, pMsg->m_fy,
   1319                                 m_pOwner->m_InfoStart.m_szStart.y -
   1320                                     m_pOwner->m_InfoStart.m_ptStart.y,
   1321                                 fHeightMin, fHeightMax, FALSE);
   1322       }
   1323     }
   1324     if (m_pOwner->m_pContent) {
   1325     }
   1326     CFX_RectF rtForm;
   1327     rtForm.Set(fLeft, fTop, fWidth, fHeight);
   1328 #if (_FX_OS_ == _FX_MACOSX_)
   1329     m_pOwner->m_pProperties->m_rtWidget = rtForm;
   1330     m_pOwner->Update();
   1331     m_pOwner->SetWidgetRect(rtForm);
   1332 #else
   1333     m_pOwner->SetWidgetRect(rtForm);
   1334     m_pOwner->Update();
   1335 #endif
   1336     return;
   1337   }
   1338   if ((m_pOwner->m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) &&
   1339       (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_Resize) &&
   1340       !m_pOwner->m_bMaximized) {
   1341     m_pOwner->SetCursor(pMsg->m_fx, pMsg->m_fy);
   1342   }
   1343   CFX_RectF rtInvalidate;
   1344   rtInvalidate.Reset();
   1345   CFWL_SysBtn* pPointBtn = m_pOwner->GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy);
   1346   CFWL_SysBtn* pOldHover = m_pOwner->GetSysBtnByState(FWL_SYSBUTTONSTATE_Hover);
   1347 #if (_FX_OS_ == _FX_MACOSX_)
   1348   {
   1349     if (pOldHover && pPointBtn != pOldHover) {
   1350       pOldHover->SetNormal();
   1351     }
   1352     if (pPointBtn && pPointBtn != pOldHover) {
   1353       pPointBtn->SetHover();
   1354     }
   1355     if (m_pOwner->m_pCloseBox) {
   1356       rtInvalidate = m_pOwner->m_pCloseBox->m_rtBtn;
   1357     }
   1358     if (m_pOwner->m_pMaxBox) {
   1359       if (rtInvalidate.IsEmpty()) {
   1360         rtInvalidate = m_pOwner->m_pMaxBox->m_rtBtn;
   1361       } else {
   1362         rtInvalidate.Union(m_pOwner->m_pMaxBox->m_rtBtn);
   1363       }
   1364     }
   1365     if (m_pOwner->m_pMinBox) {
   1366       if (rtInvalidate.IsEmpty()) {
   1367         rtInvalidate = m_pOwner->m_pMinBox->m_rtBtn;
   1368       } else {
   1369         rtInvalidate.Union(m_pOwner->m_pMinBox->m_rtBtn);
   1370       }
   1371     }
   1372     if (!rtInvalidate.IsEmpty() &&
   1373         rtInvalidate.Contains(pMsg->m_fx, pMsg->m_fy)) {
   1374       m_pOwner->m_bMouseIn = TRUE;
   1375     }
   1376   }
   1377 #else
   1378   {
   1379     if (pOldHover && pPointBtn != pOldHover) {
   1380       pOldHover->SetNormal();
   1381       rtInvalidate = pOldHover->m_rtBtn;
   1382     }
   1383     if (pPointBtn && pPointBtn != pOldHover) {
   1384       pPointBtn->SetHover();
   1385       if (rtInvalidate.IsEmpty()) {
   1386         rtInvalidate = pPointBtn->m_rtBtn;
   1387       } else {
   1388         rtInvalidate.Union(pPointBtn->m_rtBtn);
   1389       }
   1390     }
   1391   }
   1392 #endif
   1393   if (!rtInvalidate.IsEmpty()) {
   1394     m_pOwner->Repaint(&rtInvalidate);
   1395   }
   1396 }
   1397 void CFWL_FormImpDelegate::OnMouseHover(CFWL_MsgMouse* pMsg) {
   1398   m_pOwner->SetCursor(pMsg->m_fx, pMsg->m_fy);
   1399 }
   1400 void CFWL_FormImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) {
   1401   CFWL_SysBtn* pHover = m_pOwner->GetSysBtnByState(FWL_SYSBUTTONSTATE_Hover);
   1402   if (pHover) {
   1403     pHover->SetNormal();
   1404     m_pOwner->Repaint(&pHover->m_rtBtn);
   1405   }
   1406   if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseLeave &&
   1407       !m_pOwner->m_bLButtonDown) {
   1408     m_pOwner->SetCursor(pMsg->m_fx, pMsg->m_fy);
   1409   }
   1410 }
   1411 void CFWL_FormImpDelegate::OnLButtonDblClk(CFWL_MsgMouse* pMsg) {
   1412   if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_Resize) &&
   1413       m_pOwner->HitTest(pMsg->m_fx, pMsg->m_fy) == FWL_WGTHITTEST_Titlebar) {
   1414     if (m_pOwner->m_bMaximized) {
   1415       m_pOwner->SetWidgetRect(m_pOwner->m_rtRestore);
   1416     } else {
   1417       m_pOwner->SetWorkAreaRect();
   1418     }
   1419     m_pOwner->Update();
   1420     m_pOwner->m_bMaximized = !m_pOwner->m_bMaximized;
   1421   }
   1422 }
   1423 void CFWL_FormImpDelegate::OnWindowMove(CFWL_MsgWindowMove* pMsg) {
   1424   m_pOwner->m_pProperties->m_rtWidget.left = pMsg->m_fx;
   1425   m_pOwner->m_pProperties->m_rtWidget.top = pMsg->m_fy;
   1426 }
   1427 void CFWL_FormImpDelegate::OnClose(CFWL_MsgClose* pMsg) {
   1428   CFWL_EvtClose eClose;
   1429   eClose.m_pSrcTarget = m_pOwner->m_pInterface;
   1430   m_pOwner->DispatchEvent(&eClose);
   1431 }
   1432 FWL_ERR FWL_Accelerator_SetForm(IFWL_Form* pFrom,
   1433                                 CFX_MapAccelerators* pMapAccel) {
   1434   CFWL_FormImp* pImp = static_cast<CFWL_FormImp*>(pFrom->GetImpl());
   1435   if (!pImp)
   1436     return FWL_ERR_Indefinite;
   1437   return FWL_ERR_Succeeded;
   1438 }
   1439