一个窗口及其控件缩放的类

#pragma once
#include "uxtheme.h"


#define ANCHOR_LEFT                   1
#define ANCHOR_TOP                    2
#define ANCHOR_RIGHT                  4
#define ANCHOR_BOTTOM                 8
#define ANCHOR_HORIZONTALLY_CENTERED  16
#define ANCHOR_VERTICALLY_CENTERED    32
#define ANCHOR_PRIORITY_RIGHT         64   // by defualt, left has higher priority
#define ANCHOR_PRIORITY_BOTTOM        128  // by defualt, top has higher priority
#define ANCHOR_VERTICALLY             (ANCHOR_TOP | ANCHOR_BOTTOM)
#define ANCHOR_HORIZONTALLY           (ANCHOR_LEFT | ANCHOR_RIGHT)
#define ANCHOR_ALL                    (ANCHOR_VERTICALLY | ANCHOR_HORIZONTALLY)

#define DOCK_NONE   0
#define DOCK_LEFT   1
#define DOCK_TOP    2
#define DOCK_RIGHT  3
#define DOCK_BOTTOM 4
#define DOCK_FILL   5


class CWndResizer 
{
public:
  CWndResizer(void);
  ~CWndResizer(void);
private:

  class CPanel;
  typedef CList<CPanel *, CPanel *> CPanelList;

  typedef enum tagSplitterOrientation 
  {
    // a horizontal splitter container panel
    SPLIT_CONTAINER_H = 1,
    // a vertical splitter contianer panel
    SPLIT_CONTAINER_V = 2, 

  } SplitterOrientation;


  typedef enum tagFlowDirection 
  {
    // left to right flow direction
    LEFT_TO_RIGHT = 3,
    // top to bottom flow direction
    TOP_TO_BOTTOM = 4, 

  } FlowDirection;

  class CPanel : public CRect
  {
  public:
    CPanel();
    CPanel(const CRect * prc);
    virtual ~CPanel();
    UINT Anchor;
    UINT Dock;
    CString Name;
    CPanel * Parent;
    CPanelList Children;
    int LeftOffset;
    int TopOffset;
    int RightOffset;
    int BottomOffset; 
    CSize MinSize;
    CSize MaxSize;
    virtual void OnResized();
    virtual BOOL AddChild(CPanel * prc);
    virtual BOOL RemoveChild(CPanel * prc);
    virtual BOOL SetAnchor(UINT anchor);
    virtual BOOL SetMinSize(CSize & size);
    virtual BOOL SetMaxSize(CSize & size);
    virtual CString ToString();
    virtual CString GetTypeName();
    virtual CWnd * GetHookedWnd();
  private:
    void Init();
  };

  class CRootPanel : public CPanel
  {
  public:
    CRootPanel();
    ~CRootPanel();
    virtual CWnd * GetHookedWnd();
    CWnd * m_pHookWnd;
    virtual CString GetTypeName();
  }; 

  class CUIPanel : public CPanel
  {
  public:
    CUIPanel(const CRect * prc, UINT uID);
    ~CUIPanel();
    UINT m_uID;   // could be a resource ID or a HWND
    BOOL m_bOle;  // TRUE= m_uID is an ID of an ActiveX or OLE control, FALSE=regular windows control
    virtual CString GetTypeName();
  };


  class CVisualPanel : public CPanel
  {
  public:
    CVisualPanel();
    CVisualPanel(const CRect * prc);
    ~CVisualPanel();
    virtual void Draw(CDC * pDC);
    BOOL m_bVisible;
    virtual CString GetTypeName();
    virtual void OnResized();
  private:
    CRect m_rcPrev;
  };

  class CGripperPanel : public CVisualPanel
  {
  public:
    CGripperPanel();
    CGripperPanel(const CRect * prc);
    ~CGripperPanel();
    virtual void Draw(CDC * pDC);
    virtual CString GetTypeName();
   private:
    HTHEME m_hTheme;
    int m_iPartId;
    int m_iStateId;
    CString m_sClassName;
  };

  class CSplitterGripperPanel : public CVisualPanel
  {
  public:
    CSplitterGripperPanel(CWndResizer::SplitterOrientation type);
    ~CSplitterGripperPanel();
    virtual void Draw(CDC * pDC);
    virtual CString GetTypeName();
  private:
    CWndResizer::SplitterOrientation m_OrienType;
  };

  class CSplitPanel : public CPanel
  {
  public:
    CSplitPanel(CPanel * pPanel);
    ~CSplitPanel();
    virtual BOOL SetAnchor(UINT anchor);
    virtual BOOL AddChild(CPanel * prc);
    virtual BOOL RemoveChild(CPanel * prc);
    virtual CString GetTypeName();
  private:
    CPanel * m_pOriginalPanel;
  };


  class CSpitterPanel : public CPanel
  {
  public:
    CSpitterPanel(CWndResizer::SplitterOrientation type);
    CSpitterPanel(const CRect * prc, CWndResizer::SplitterOrientation type);
    ~CSpitterPanel();
    virtual CString GetTypeName();
    CSplitterGripperPanel * m_pGrippePanel;
  private:
    CWndResizer::SplitterOrientation m_OrienType;
  };


  class CSplitContainer : public CPanel
  {
  public:
    CSplitContainer(CSplitPanel * pPanelA, CSplitPanel * pPanelB, CWndResizer::SplitterOrientation type);
    ~CSplitContainer();
    virtual void OnResized();
    virtual BOOL AddChild(CPanel * prc);
    virtual BOOL RemoveChild(CPanel * prc);
    virtual CString GetTypeName();
    void SetSplitterPosition(int leftOfSpliter /* or topOfSpliter if vertical */);
    int GetSplitterPosition();
    void SetFixedPanel(short nFixedPanel /* 1=left or top; 2=right or bototm; other=no fixed panel */);
    short GetFixedPanel();
    void SetIsSplitterFixed(BOOL bFixed);
    BOOL GetIsSplitterFixed();
    void SetShowSplitterGrip(BOOL bShow);
    BOOL GetShowSplitterGrip();

    static CWndResizer::CSplitContainer * Create(CPanel * pPanelA, CPanel * pPanelB);
    
    CWndResizer::SplitterOrientation m_Orientation;
  private:
    BOOL m_IsSplitterFixed;
    short m_FixedPanel; // 1=left or top panel; 2=right or bottom panel, otherwise no fixed panel

    double m_nRatio;
    int m_nSplitterSize; // for horizontal, it is the splitter width, otherwise it is the splitter height
    void GetSplitArea(CRect * pSplitterPanel);
    int GetSplitterSize(CPanel * pLeftPanel, CPanel * pRightPanel);
    void UpdateRatio();

    CSplitPanel * m_pPanelA;
    CSplitPanel * m_pPanelB;
    CSpitterPanel * m_pSplitter;
  };


  class CFlowLayoutPanel : public CPanel
  {
  public:
    CFlowLayoutPanel();
    CFlowLayoutPanel(const CRect * prc);
    ~CFlowLayoutPanel();
    virtual void OnResized();
    virtual CString GetTypeName();
    void SetFlowDirection(CWndResizer::FlowDirection direction);
    CWndResizer::FlowDirection GetFlowDirection();
    void SetItemSpacingX(int nSpace);
    int GetItemSpacingX();
    void SetItemSpacingY(int nSpace);
    int GetItemSpacingY();

  private:
    int m_nItemSpacingX;
    int m_nItemSpacingY;
    CWndResizer::FlowDirection m_nFlowDirection;
  };

public:
  BOOL SetAnchor(LPCTSTR panelName, UINT anchor);
  BOOL SetAnchor(UINT panelID, UINT anchor);
  BOOL GetAnchor(LPCTSTR panelName, UINT & anchor);
  BOOL GetAnchor(UINT panelID, UINT & anchor);


  BOOL SetDock(LPCTSTR panelName, UINT anchor);
  BOOL SetDock(UINT panelID, UINT anchor);
  BOOL GetDock(LPCTSTR panelName, UINT & anchor);
  BOOL GetDock(UINT panelID, UINT & anchor);

  BOOL SetFixedPanel(LPCTSTR splitContainerName, short panel);
  BOOL GetFixedPanel(LPCTSTR splitContainerName, short & panel);

  BOOL SetIsSplitterFixed(LPCTSTR splitContainerName, BOOL fixed);
  BOOL GetIsSplitterFixed(LPCTSTR splitContainerName, BOOL &fixed);

  BOOL SetFlowDirection(LPCTSTR flowPanelName, short direction);
  BOOL GetFlowDirection(LPCTSTR flowPanelName, short &direction);

  BOOL SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpacing);
  BOOL GetFlowItemSpacingX(LPCTSTR flowPanelName, int &nSpacing);

  BOOL SetFlowItemSpacingY(LPCTSTR flowPanelName, int nSpacing);
  BOOL GetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpacing);


  BOOL SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow);
  BOOL GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL & bShow);

  BOOL SetParent(LPCTSTR panelName, LPCTSTR parentName);
  BOOL SetParent(UINT panelID, LPCTSTR parentName);
  BOOL SetParent(LPCTSTR panelName, UINT parentID);
  BOOL SetParent(UINT panelID, UINT parentID);
  BOOL GetParent(LPCTSTR panelName, CString & parentName);
  BOOL GetParent(UINT panelID, CString & parentName);

  BOOL SetMinimumSize(LPCTSTR panelName, CSize & size);
  BOOL SetMinimumSize(UINT panelID, CSize & size);
  BOOL GetMinimumSize(LPCTSTR panelName, CSize & size) ;
  BOOL GetMinimumSize(UINT panelID, CSize & size) ;

  BOOL SetMaximumSize(LPCTSTR panelName, CSize & size);
  BOOL SetMaximumSize(UINT panelID, CSize & size);
  BOOL GetMaximumSize(LPCTSTR panelName, CSize & size) ;
  BOOL GetMaximumSize(UINT panelID, CSize & size) ;

  void SetShowResizeGrip(BOOL show = TRUE);
  BOOL GetShowResizeGrip();
  BOOL Hook(CWnd * pWnd);
  BOOL Hook(CWnd * pWnd, CSize & size);
  BOOL Unhook();
  
  BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CRect * prcPanel);
  BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE);

  BOOL CreatePanel(LPCTSTR panelName, const CRect * prcPanel);
  BOOL CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE);

  BOOL CreatePanel(UINT uID);

  BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, LPCTSTR panelNameB);    
  BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, UINT panelIDB);  
  BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, UINT panelIDB);  
  BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, LPCTSTR panelNameB); 

  // useful for persisting UI layout
  BOOL SetSplitterPosition(LPCTSTR splitContainerName, UINT position);  
  BOOL GetSplitterPosition(LPCTSTR splitContainerName, UINT & position);  

  BOOL InvokeOnResized();
  
  CString GetDebugInfo();
  
private:
  
  CWnd * m_pHookedWnd;
  CRootPanel root;
  CPanel * m_pCaptured;
  HCURSOR m_hOldCursor;
  int m_splitterOffset;  

  void OnPaint();
  void OnSize(UINT nType, int cx, int cy);
  void OnSizing(UINT fwSide, LPRECT pRect);
  void OnDestroy();
	void OnLButtonDown(UINT nFlags, CPoint point);
	void OnMouseMove(UINT nFlags, CPoint point);
	void OnLButtonUp(UINT nFlags, CPoint point);

  CWndResizer::CPanel * FindPanelByName(CWndResizer::CPanel * pRoot, LPCTSTR name);
  CWndResizer::CPanel * FindSplitterFromPoint(CWndResizer::CPanel * pRoot, CPoint point);
  void GetUIPanels(CWndResizer::CPanel * pRoot, CPanelList * pList, BOOL bOle);
  void GetVisualPanels(CWndResizer::CPanel * pRoot, CPanelList * pList);

  void ResizeUI(CWndResizer::CPanel * pRoot);

  CString IdToName(UINT uID);
  CWndResizer::CUIPanel * CreateUIPanel(UINT uID);
  CWndResizer::CUIPanel * GetUIPanel(UINT uID);

  void UpdateSplitterOffset(CPoint ptCurr);
  void GetDebugInfo(CPanel * pRoot, CString & info, CString  indent);

  WNDPROC m_pfnWndProc;
  static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


};
#include "StdAfx.h"
#include "WndResizer.h"



static CMap<HWND, HWND, CWndResizer *, CWndResizer *> WndResizerData;


/  CWndResizer
///
CWndResizer::CWndResizer(void)
{
  m_pHookedWnd = NULL;
  m_pfnWndProc = NULL;
  root.Name = _T("_root");
  m_pCaptured = NULL;
  m_hOldCursor = NULL;
  m_splitterOffset = 0;

}

CWndResizer::~CWndResizer(void)
{

}

void CWndResizer::OnSize(UINT nType, int cx, int cy)
{
  root.right = cx;
  root.bottom = cy;
  root.OnResized();
  ResizeUI(&root);
  
}

void CWndResizer::ResizeUI(CWndResizer::CPanel * pRoot)
{
  CPanelList panels;
  GetUIPanels(pRoot, &panels, FALSE);

  POSITION pos = NULL;

  if (panels.GetCount() > 0)
  {
    HDWP hDWP = ::BeginDeferWindowPos(panels.GetCount());
    ASSERT( hDWP != NULL);
    pos = panels.GetHeadPosition();
    while (pos != NULL)
    {
      CUIPanel * pPanel = (CUIPanel *) panels.GetNext(pos);

        ::DeferWindowPos(hDWP, m_pHookedWnd->GetDlgItem(pPanel->m_uID)->m_hWnd, NULL,
                      pPanel->left , pPanel->top , pPanel->Width(), pPanel->Height(),
                      SWP_NOACTIVATE | SWP_NOZORDER );

    }
    BOOL bOk = ::EndDeferWindowPos(hDWP);
    ASSERT( bOk == TRUE);
    m_pHookedWnd->InvalidateRect(pRoot, FALSE);
  }

  panels.RemoveAll();
  GetUIPanels(pRoot, &panels, TRUE);
  pos = panels.GetHeadPosition();
  while (pos != NULL)
  {
    CUIPanel * pPanel = (CUIPanel *) panels.GetNext(pos);
    m_pHookedWnd->GetDlgItem(pPanel->m_uID)->MoveWindow(pPanel);
  }
}


void CWndResizer::OnLButtonDown(UINT nFlags, CPoint point)
{
  UpdateSplitterOffset(point);
}
void CWndResizer::OnMouseMove(UINT nFlags, CPoint point)
{
  if (m_pCaptured != NULL )
  {
    if ((nFlags & MK_LBUTTON) <= 0)
    {
      CPoint ptScreen = point;
      m_pHookedWnd->ClientToScreen(&ptScreen);
      HWND hWndFromPoint = ::WindowFromPoint(ptScreen);
      if (m_pCaptured->PtInRect( point ) == FALSE || hWndFromPoint != m_pHookedWnd->m_hWnd)
      {
        ::ReleaseCapture();      
        m_pCaptured = NULL;
        HCURSOR hCur = ::SetCursor(m_hOldCursor);
        ::DestroyCursor( hCur );
        m_hOldCursor = NULL;
      }
    }
  }

  if (m_pCaptured == NULL )
  {
    m_pCaptured = FindSplitterFromPoint(&root, point);
    if (m_pCaptured != NULL)
    {
      m_pHookedWnd->SetCapture();
      LPCTSTR cursor = NULL;
      CSplitContainer * pSplitContainer = (CSplitContainer *)m_pCaptured->Parent;
      if (pSplitContainer->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
      {
        cursor = IDC_SIZEWE;
      }
      else
      {
        cursor = IDC_SIZENS;
      }
      HCURSOR hCur = AfxGetApp()->LoadStandardCursor(cursor);
      HCURSOR m_hOldCursor = ::SetCursor(hCur);
    }
  }

  if (m_pCaptured != NULL && (nFlags & MK_LBUTTON) > 0)
  {
    CSplitContainer * pSplitterContainer = (CSplitContainer *) m_pCaptured->Parent;
    
    if (pSplitterContainer->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
    {
      pSplitterContainer->SetSplitterPosition( point.x - m_splitterOffset);
    }
    else
    {
      pSplitterContainer->SetSplitterPosition( point.y - m_splitterOffset);
    }
    UpdateSplitterOffset(point);

    ResizeUI(pSplitterContainer);

  }
}
void CWndResizer::OnLButtonUp(UINT nFlags, CPoint point)
{
  OnMouseMove(nFlags, point);
}
void CWndResizer::UpdateSplitterOffset(CPoint ptCurr)
{
  if (m_pCaptured == NULL )
  {
    return;
  }
  if (((CSplitContainer *)m_pCaptured->Parent)->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
  {
    if ( ptCurr.x  < m_pCaptured->left)
    {
      m_splitterOffset = 0;
    }
    else if ( ptCurr.x > m_pCaptured->right)
    {
      m_splitterOffset = m_pCaptured->Width();
    }
    else
    {
      m_splitterOffset = ptCurr.x - m_pCaptured->left;
    }
  }
  else
  {
    if ( ptCurr.y  < m_pCaptured->top)
    {
      m_splitterOffset = 0;
    }
    else if ( ptCurr.y > m_pCaptured->bottom)
    {
      m_splitterOffset = m_pCaptured->Height();
    }
    else
    {
      m_splitterOffset = ptCurr.y - m_pCaptured->top;
    }    
  }
}
void CWndResizer::OnSizing(UINT fwSide, LPRECT pRect)
{

  CRect * prc = (CRect *) pRect;

  CRect rcMin(0, 0, root.MinSize.cx, root.MinSize.cy);
  CRect rcMax(0, 0, root.MaxSize.cx, root.MaxSize.cy);

  LONG_PTR style = GetWindowLongPtr(m_pHookedWnd->m_hWnd , GWL_STYLE);
  LONG_PTR styleEx = GetWindowLongPtr(m_pHookedWnd->m_hWnd, GWL_EXSTYLE);

  ::AdjustWindowRectEx(&rcMin, style, (m_pHookedWnd->GetMenu() != NULL), styleEx);
  ::AdjustWindowRectEx(&rcMax, style, (m_pHookedWnd->GetMenu() != NULL), styleEx);

  switch (fwSide)
  {
  case WMSZ_BOTTOM:
    if (prc->Height() < rcMin.Height() )
    {
      prc->bottom = prc->top + rcMin.Height();
    }
    if (prc->Height() > rcMax.Height() )
    {
      prc->bottom = prc->top + rcMax.Height();
    }    
    break;
  case WMSZ_BOTTOMLEFT:
    if (prc->Height() < rcMin.Height() )
    {
      prc->bottom = prc->top + rcMin.Height();
    }
    if (prc->Width() < rcMin.Width() )
    {
      prc->left = prc->right - rcMin.Width();
    }

    if (prc->Height() > rcMax.Height() )
    {
      prc->bottom = prc->top + rcMax.Height();
    }
    if (prc->Width() > rcMax.Width() )
    {
      prc->left = prc->right - rcMax.Width();
    }
    break;
  case WMSZ_BOTTOMRIGHT:
    if (prc->Height() < rcMin.Height() )
    {
      prc->bottom = prc->top + rcMin.Height();
    }
    if (prc->Width() < rcMin.Width() )
    {
      prc->right = prc->left + rcMin.Width();
    }

    if (prc->Height() > rcMax.Height() )
    {
      prc->bottom = prc->top + rcMax.Height();
    }
    if (prc->Width() > rcMax.Width() )
    {
      prc->right = prc->left + rcMax.Width();
    }

    break;
  case WMSZ_LEFT:
    if (prc->Width() < rcMin.Width() )
    {
      prc->left = prc->right - rcMin.Width();
    }

    if (prc->Width() > rcMax.Width() )
    {
      prc->left = prc->right - rcMax.Width();
    }
    break;
  case WMSZ_RIGHT:
    if (prc->Width() < rcMin.Width() )
    {
      prc->right = prc->left + rcMin.Width();
    }

    if (prc->Width() > rcMax.Width() )
    {
      prc->right = prc->left + rcMax.Width();
    }
    break;
  case WMSZ_TOP:
    if (prc->Height() < rcMin.Height() )
    {
      prc->top = prc->bottom - rcMin.Height();
    }

    if (prc->Height() > rcMax.Height() )
    {
      prc->top = prc->bottom - rcMax.Height();
    }
    break;
  case WMSZ_TOPLEFT:
    if (prc->Height() < rcMin.Height() )
    {
      prc->top = prc->bottom - rcMin.Height();
    }
    if (prc->Width() < rcMin.Width() )
    {
      prc->left = prc->right - rcMin.Width();
    }


    if (prc->Height() > rcMax.Height() )
    {
      prc->top = prc->bottom - rcMax.Height();
    }
    if (prc->Width() > rcMax.Width() )
    {
      prc->left = prc->right - rcMax.Width();
    }
    break;
  case WMSZ_TOPRIGHT:
    if (prc->Height() < rcMin.Height() )
    {
      prc->top = prc->bottom - rcMin.Height();
    }
    if (prc->Width() < rcMin.Width() )
    {
      prc->right = prc->left + rcMin.Width();
    }

    if (prc->Height() > rcMax.Height() )
    {
      prc->top = prc->bottom - rcMax.Height();
    }
    if (prc->Width() > rcMax.Width() )
    {
      prc->right = prc->left + rcMax.Width();
    }
    break;
  }

}

void CWndResizer::OnPaint()
{
  if (m_pHookedWnd == NULL)
  {
    return;
  }
  CPaintDC dc(m_pHookedWnd); // device context for painting

  CPanelList panelList;
  GetVisualPanels(&root, &panelList);
  POSITION pos = panelList.GetHeadPosition();
  while (pos != NULL)
  {
    CVisualPanel * pPanel = (CVisualPanel *) panelList.GetNext(pos);
    if (pPanel->m_bVisible)
    {
      pPanel->Draw(&dc);
    }
  }

}


BOOL CWndResizer::SetAnchor(LPCTSTR panelName, UINT uAnchor)
{
  // container must already exist
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  
  {
    return FALSE;
  }

  return pPanel->SetAnchor(uAnchor);
}

BOOL CWndResizer::SetAnchor(UINT uID, UINT uAnchor)
{
  ASSERT(m_pHookedWnd != NULL);

  CUIPanel * pPanel = GetUIPanel(uID);

  if (pPanel == NULL)
  {
    return FALSE;
  }
  pPanel->SetAnchor(uAnchor);  
  
  return TRUE;
}
BOOL CWndResizer::GetAnchor(LPCTSTR panelName, UINT & anchor)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  anchor = pPanel->Anchor;
  return TRUE;
}
BOOL CWndResizer::GetAnchor(UINT uID, UINT & anchor)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  anchor = pPanel->Anchor;
  return TRUE;
}
/

BOOL CWndResizer::SetDock(LPCTSTR panelName, UINT uDock)
{
  // container must already exist
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  
  {
    return FALSE;
  }

  pPanel->Dock = uDock ;
  return TRUE;
}

BOOL CWndResizer::SetDock(UINT uID, UINT uDock)
{
  ASSERT(m_pHookedWnd != NULL);

  CUIPanel * pPanel = GetUIPanel(uID);

  if (pPanel == NULL)
  {
    return FALSE;
  }
  pPanel->Dock = uDock;  
  
  return TRUE;
}
BOOL CWndResizer::GetDock(LPCTSTR panelName, UINT & uDock)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  uDock = pPanel->Dock;
  return TRUE;
}
BOOL CWndResizer::GetDock(UINT uID, UINT & uDock)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  uDock = pPanel->Dock;
  return TRUE;
}


//
BOOL CWndResizer::SetParent(LPCTSTR panelName, LPCTSTR parentName)
{
  ASSERT(m_pHookedWnd != NULL);


  // now make sure parentName is OK
  CPanel * pParent = NULL;
  if ( (pParent = FindPanelByName(&root, parentName)) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  // make sure panelName exist
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) == NULL)
  {
    return FALSE;
  }

  return pParent->AddChild(pPanel);
}
BOOL CWndResizer::SetParent(UINT uID, LPCTSTR parentName)
{
  ASSERT(m_pHookedWnd != NULL);

  // now make sure parentName is OK
  CPanel * pParent = NULL;
  if ( (pParent = FindPanelByName(&root, parentName)) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }
  CPanel * pPanel = NULL;

  // first see if it is already defined
  if ((pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
  {
    if ((pPanel = CreateUIPanel(uID)) == NULL)
    {
      return FALSE;
    }
  }

  return pParent->AddChild(pPanel);

}

BOOL CWndResizer::SetParent(LPCTSTR panelName, UINT uParentID)
{
  ASSERT(m_pHookedWnd != NULL);

  // now make sure parentName is OK
  CPanel * pParent = GetUIPanel(uParentID);
  if ( pParent == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  // make sure panelName exist
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) == NULL)
  {
    return FALSE;
  }

  return pParent->AddChild(pPanel);

}
BOOL CWndResizer::SetParent(UINT uID, UINT uParentID)
{
  CPanel * pParent = GetUIPanel(uParentID);
  if (pParent == NULL)
  {
    return FALSE;
  }
  CPanel * pPanel = GetUIPanel(uID);;
  if (pParent == NULL)
  {
    return FALSE;
  }

  return pParent->AddChild( pPanel );

}


BOOL CWndResizer::GetParent(LPCTSTR panelName, CString & parentName)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL) 
  {
    return FALSE;
  }

  parentName = pPanel->Parent->Name;
  return TRUE;
}
BOOL CWndResizer::GetParent(UINT uID, CString & parentName)
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)  // name of parent must already exist
  {
    return FALSE;
  }

  parentName = pPanel->Parent->Name;
  return TRUE;
}

BOOL CWndResizer::SetFixedPanel(LPCTSTR splitContainerName, short panel)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *>( pContainer );
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }

  pSplitContainer->SetFixedPanel(panel);
  return TRUE;
}
BOOL CWndResizer::GetFixedPanel(LPCTSTR splitContainerName, short & panel)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *> (pContainer);
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }
  panel = pSplitContainer->GetFixedPanel();
  return TRUE;

}

BOOL CWndResizer::SetIsSplitterFixed(LPCTSTR splitContainerName, BOOL fixed)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *> (pContainer);
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }
  pSplitContainer->SetIsSplitterFixed( fixed );
  return TRUE;
}
BOOL CWndResizer::GetIsSplitterFixed(LPCTSTR splitContainerName, BOOL &fixed)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *> (pContainer);
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }
  fixed = pSplitContainer->GetIsSplitterFixed();
  return TRUE;
}



BOOL CWndResizer::SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *> (pContainer);
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }
  pSplitContainer->SetShowSplitterGrip( bShow );
  return TRUE;
}
BOOL CWndResizer::GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL &bShow)
{
  CPanel * pContainer = FindPanelByName(&root, splitContainerName);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pSplitContainer =  dynamic_cast<CSplitContainer *> (pContainer);
  if (pSplitContainer == NULL)
  {
    return FALSE;
  }
  bShow = pSplitContainer->GetShowSplitterGrip();
  return TRUE;
}




/
BOOL CWndResizer::SetMinimumSize( LPCTSTR panelName, CSize & size)
{
  CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  
  {
    return FALSE;
  }
  return pPanel->SetMinSize( size );
}
BOOL CWndResizer::SetMinimumSize(UINT uID, CSize & size)
{
  CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL) 
  {
    if ((pPanel = CreateUIPanel(uID)) == NULL)
    {
      return FALSE;
    }
  }

  return pPanel->SetMinSize( size );
}

BOOL CWndResizer::GetMinimumSize(LPCTSTR panelName, CSize & size) 
{
  CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL) 
  {
    return FALSE;
  }

  size = pPanel->MinSize;
  return TRUE;
}
BOOL CWndResizer::GetMinimumSize(UINT uID, CSize & size) 
{
  const CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL) 
  {
    return FALSE;
  }

  size = pPanel->MinSize;
  return TRUE;
}
BOOL CWndResizer::SetMaximumSize(UINT uID, CSize & size)
{
  CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)  
  {
    return FALSE;
  }
  
  return pPanel->SetMaxSize(size);
}

BOOL CWndResizer::SetMaximumSize( LPCTSTR panelName, CSize & size)
{
  CPanel * pPanel = NULL;

  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL) 
  {
    return FALSE;
  }

  return pPanel->SetMaxSize(size);

}
BOOL CWndResizer::GetMaximumSize(  LPCTSTR panelName, CSize & size) 
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)  
  {
    return FALSE;
  }

  size = pPanel->MaxSize;
  return TRUE;
}
BOOL CWndResizer::GetMaximumSize(  UINT uID, CSize & size) 
{
  CPanel * pPanel = NULL;
  if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)  
  {
    return FALSE;
  }

  size = pPanel->MaxSize;
  return TRUE;
}
void CWndResizer::SetShowResizeGrip(BOOL show)
{  
  CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, _T("_resizeGrip"));
  ASSERT(pPanel != NULL);
  if ( pPanel->m_bVisible != show )
  {
    pPanel->m_bVisible = show;
    m_pHookedWnd->Invalidate(TRUE);
  }
}
BOOL CWndResizer::GetShowResizeGrip()
{
  CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, _T("_resizeGrip"));
  ASSERT(pPanel != NULL);
  return pPanel->m_bVisible ;

} 
void CWndResizer::OnDestroy()
{
  if (m_pHookedWnd != NULL)
  {
    Unhook();
  }
}
BOOL CWndResizer::Hook(CWnd * pParent)
{
  ASSERT( m_pHookedWnd == NULL );

  if (m_pHookedWnd != NULL )
  {
    return FALSE; //already hooked
  }

  CRect rc;
  pParent->GetClientRect( &rc );
  return Hook(pParent, rc.Size() );


}
BOOL CWndResizer::Hook(CWnd * pParent, CSize &  size)
{
  ASSERT( m_pHookedWnd == NULL );

  if (m_pHookedWnd != NULL )
  {
    return FALSE; //already hooked
  }
  m_pHookedWnd = pParent;
  m_pHookedWnd->GetClientRect( &root );
  root.right = size.cx;
  root.bottom = size.cy;
  root.m_pHookWnd = m_pHookedWnd;

  // create the resize gripper panel
  CRect rcResziGrip(&root);
  int cx = ::GetSystemMetrics(SM_CXHSCROLL);
  int cy = ::GetSystemMetrics(SM_CYVSCROLL);
  rcResziGrip.DeflateRect(root.Width() - cx, root.Height() - cy, 0, 0);
  CGripperPanel * pResizeGripper = new CGripperPanel(&rcResziGrip);
  pResizeGripper->SetAnchor( ANCHOR_RIGHT | ANCHOR_BOTTOM );
  pResizeGripper->Name = _T("_resizeGrip");
  root.AddChild( pResizeGripper );

  WndResizerData.SetAt(m_pHookedWnd->m_hWnd, this);

  m_pfnWndProc = (WNDPROC)::SetWindowLongPtr(m_pHookedWnd->m_hWnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);
  return TRUE;
}

BOOL CWndResizer::Unhook()
{
  ASSERT( m_pHookedWnd != NULL );
  if (m_pHookedWnd == NULL )
  {
    return FALSE; //hasent been hooked
  }

  WNDPROC pWndProc = (WNDPROC)::SetWindowLongPtr(m_pHookedWnd->m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnWndProc);
  WndResizerData.RemoveKey(m_pHookedWnd->m_hWnd); 
  root.m_pHookWnd = NULL;
  m_pHookedWnd = NULL;

  // destroy all chilldren
  while(root.Children.GetCount() > 0 )
  {
    CPanel * pChild = root.Children.RemoveHead();
    delete pChild;
  }
  return TRUE;
}


LRESULT CALLBACK CWndResizer::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  CWndResizer * pResizer = NULL;
  WndResizerData.Lookup(hWnd, pResizer);
  ASSERT( pResizer != NULL);

	int cx = 0;
	int cy = 0;

	switch (uMsg)
	{
		case WM_SIZE:
      cx = LOWORD(lParam);    
      cy = HIWORD(lParam);    
      pResizer->OnSize((UINT) wParam, cx, cy);
			break;
    case WM_SIZING:
      pResizer->OnSizing((UINT) wParam, (LPRECT)lParam);      
      break;
    case WM_DESTROY:
      pResizer->OnDestroy();
      break;
    case WM_MOUSEMOVE:
      pResizer->OnMouseMove((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
      break;
    case WM_LBUTTONDOWN:
      pResizer->OnLButtonDown((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
      break;
    case WM_LBUTTONUP:
      pResizer->OnLButtonUp((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
      break;
    case WM_PAINT:
      pResizer->OnPaint();     
      break;
    //case WM_ERASEBKGND:
    //  return FALSE;
    //  break;
		default:
			break;
	}

	return ::CallWindowProc(pResizer->m_pfnWndProc, hWnd, uMsg, wParam, lParam);


}



BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, LPCTSTR panelNameA, LPCTSTR panelNameB)
{
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanelA = NULL;
  if ((pPanelA = FindPanelByName(&root, panelNameA)) == NULL)  
  {
    return FALSE;
  }


  CPanel * pPanelB = NULL;
  if ((pPanelB = FindPanelByName(&root, panelNameB)) == NULL)  
  {
    return FALSE;
  }
  

  if (pPanelA == pPanelB) // two panel cannot be same
  {
    return FALSE;
  }


  CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
  if (pSplitterContainer == NULL)
  {
    return FALSE;
  }
  pSplitterContainer->Name = panelName;

  return root.AddChild(pSplitterContainer);
}



BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, LPCTSTR panelNameA, UINT panelIDB)
{
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanelA = NULL;
  if ((pPanelA = FindPanelByName(&root, panelNameA)) == NULL)  
  {
    return FALSE;
  }

  CPanel * pPanelB = GetUIPanel(panelIDB);
  if (pPanelB == NULL )
  {
    return FALSE;
  }
  

  if (pPanelA == pPanelB) // two panel cannot be same
  {
    return FALSE;
  }

  // first lets make sure the two CRect are properly set

  CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
  if (pSplitterContainer == NULL)
  {
    return FALSE;
  }
  pSplitterContainer->Name = panelName;

  return root.AddChild(pSplitterContainer);

}


BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, UINT panelIDA, LPCTSTR panelNameB)
{
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanelA = GetUIPanel(panelIDA);
  if (pPanelA == NULL )
  {
    return FALSE;
  }


  CPanel * pPanelB = NULL;
  if ((pPanelB = FindPanelByName(&root, panelNameB)) == NULL)  
  {
    return FALSE;
  }

  if (pPanelA == pPanelB) // two panel cannot be same
  {
    return FALSE;
  }
  
  CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
  if (pSplitterContainer == NULL)
  {
    return FALSE;
  }
  pSplitterContainer->Name.Append(panelName);

  return root.AddChild(pSplitterContainer);

}



BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, UINT panelIDA, UINT panelIDB)
{
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, panelName)) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanelA = GetUIPanel(panelIDA);
  if (pPanelA == NULL )
  {
    return FALSE;
  }


  CPanel * pPanelB = GetUIPanel(panelIDB);
  if (pPanelB == NULL )
  {
    return FALSE;
  }
  
  if (pPanelA == pPanelB) // two panel cannot be same
  {
    return FALSE;
  }
 
  CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
  if (pSplitterContainer == NULL)
  {
    return FALSE;
  }
  pSplitterContainer->Name = panelName;

  return root.AddChild(pSplitterContainer);

}

BOOL CWndResizer::SetSplitterPosition(LPCTSTR splitContainerName, UINT position)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, splitContainerName)) == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pContainer = dynamic_cast<CSplitContainer *> ( pPanel);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  pContainer->SetSplitterPosition( (int) position);
  ResizeUI( pContainer );
  return TRUE;
}
BOOL CWndResizer::GetSplitterPosition(LPCTSTR splitContainerName, UINT & position)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, splitContainerName)) == NULL)
  {
    return FALSE;
  }
  CSplitContainer * pContainer = dynamic_cast<CSplitContainer *> ( pPanel);
  if (pContainer == NULL)
  {
    return FALSE;
  }
  position = (UINT) pContainer->GetSplitterPosition();
  return TRUE;
}

BOOL CWndResizer::CreatePanel(UINT uID)
{
  ASSERT(m_pHookedWnd != NULL);
  if (FindPanelByName(&root, IdToName(uID)) != NULL)
  {
    return FALSE;
  }
  CUIPanel * pPanel = GetUIPanel(uID);
  ASSERT(pPanel != NULL);

  pPanel->m_bOle = TRUE;

  return TRUE;
}

BOOL CWndResizer::SetFlowDirection(LPCTSTR flowPanelName, short direction)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  pFlowLayout->SetFlowDirection( direction == 1 ? CWndResizer::LEFT_TO_RIGHT : CWndResizer::TOP_TO_BOTTOM);
  return TRUE;
}
BOOL CWndResizer::GetFlowDirection(LPCTSTR flowPanelName, short &direction)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  direction = (pFlowLayout->GetFlowDirection() == CWndResizer::LEFT_TO_RIGHT ? 1 : 2);
  return TRUE;
}

BOOL CWndResizer::SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpacing)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  pFlowLayout->SetItemSpacingX(nSpacing);
  return TRUE;
}
BOOL CWndResizer::GetFlowItemSpacingX(LPCTSTR flowPanelName, int &nSpacing)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  nSpacing = pFlowLayout->GetItemSpacingX();
  return TRUE;
}

BOOL CWndResizer::SetFlowItemSpacingY(LPCTSTR flowPanelName, int nSpacing)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  pFlowLayout->SetItemSpacingY(nSpacing);
  return TRUE;

}

BOOL CWndResizer::GetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpacing)
{
  ASSERT(m_pHookedWnd != NULL);
  CPanel * pPanel = NULL;
  if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
  {
    return FALSE;
  }
  CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
  if (pFlowLayout == NULL)
  {
    return FALSE;
  }
  nSpacing = pFlowLayout->GetItemSpacingY();
  return TRUE;

}


BOOL CWndResizer::CreateFlowLayoutPanel(LPCTSTR panelName, const CRect * prcPanel)
{
  if (FindPanelByName(&root, panelName) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanel = new CFlowLayoutPanel(prcPanel);
  pPanel->Name = panelName;
  return root.AddChild(pPanel);
 
}
BOOL CWndResizer::CreateFlowLayoutPanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren)
{
  ASSERT(m_pHookedWnd != NULL);

  CRect rcFinal;
  for(int i = 0; i < parrID->GetCount(); i++)
  {
    CRect rc;
    m_pHookedWnd->GetDlgItem(parrID->GetAt(i))->GetWindowRect(&rc);
    m_pHookedWnd->ScreenToClient(&rc);
    rcFinal.UnionRect(&rcFinal, &rc);
  }

  BOOL bOk = CreateFlowLayoutPanel(panelName, &rcFinal);
  if (bOk == FALSE)
  {
    return FALSE;
  }

  if ( setAsChildren )
  {
    CPanel * pPanel = FindPanelByName(&root, panelName);
    for(int i = 0; i < parrID->GetCount(); i++)
    {
      if (FindPanelByName(&root, IdToName(parrID->GetAt(i))) != NULL)  
      {
        bOk = root.RemoveChild(pPanel);
        ASSERT( bOk == TRUE);
        delete pPanel;
        return FALSE;
      }
      CUIPanel * pUIPanel = GetUIPanel(parrID->GetAt(i));
      ASSERT( pUIPanel != NULL);
      bOk = pPanel->AddChild( pUIPanel );
      ASSERT( bOk == TRUE);
    }
  }
  return TRUE;
}

BOOL CWndResizer::CreatePanel(LPCTSTR panelName, const CRect * prcPanel)
{
  if (FindPanelByName(&root, panelName) != NULL)  
  {
    return FALSE;
  }

  CPanel * pPanel = new CPanel(prcPanel);
  pPanel->Name = panelName;
  return root.AddChild(pPanel);
 
}
BOOL CWndResizer::CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren)
{
  ASSERT(m_pHookedWnd != NULL);

  CRect rcFinal;
  for(int i = 0; i < parrID->GetCount(); i++)
  {
    CRect rc;
    m_pHookedWnd->GetDlgItem(parrID->GetAt(i))->GetWindowRect(&rc);
    m_pHookedWnd->ScreenToClient(&rc);
    rcFinal.UnionRect(&rcFinal, &rc);
  }

  BOOL bOk = CreatePanel(panelName, &rcFinal);
  if (bOk == FALSE)
  {
    return FALSE;
  }

  if ( setAsChildren )
  {
    CPanel * pPanel = FindPanelByName(&root, panelName);
    for(int i = 0; i < parrID->GetCount(); i++)
    {
      if (FindPanelByName(&root, IdToName(parrID->GetAt(i))) != NULL)  
      {
        bOk = root.RemoveChild(pPanel);
        ASSERT( bOk == TRUE);
        delete pPanel;
        return FALSE;
      }
      CUIPanel * pUIPanel = GetUIPanel(parrID->GetAt(i));
      ASSERT( pUIPanel != NULL);
      bOk = pPanel->AddChild( pUIPanel );
      ASSERT( bOk == TRUE);
    }
  }
  return TRUE;
}

CWndResizer::CPanel * CWndResizer::FindPanelByName(CWndResizer::CPanel * pRoot, LPCTSTR name)
{
  if (CString(name).GetLength() == 0)
  {
    return NULL;
  }

  if (pRoot == NULL )
  {
    return NULL;
  }

  if (pRoot->Name.CompareNoCase(name) == 0 )
  {
    return pRoot;
  }
  else
  {
    POSITION pos = pRoot->Children.GetHeadPosition();
    while(pos != NULL)
    {
      CPanel * pChild = pRoot->Children.GetNext(pos);
      CPanel * pFound = FindPanelByName(pChild, name);
      if (pFound != NULL )
      {
        return pFound;
      }
    }
  }
  
  return NULL;
}
void CWndResizer::GetUIPanels(CWndResizer::CPanel * pRoot, CPanelList * pList, BOOL bOle)
{
  if (pRoot == NULL )
  {
    return ;
  }

  CUIPanel * pUIPanel = dynamic_cast<CUIPanel *> ( pRoot);

  if (pUIPanel != NULL && pUIPanel->m_bOle == bOle)
  {
    pList->AddTail( pRoot );
  }

  // try the childreen
  POSITION pos = pRoot->Children.GetHeadPosition();
  while(pos != NULL)
  {
    CPanel * pChild = pRoot->Children.GetNext(pos);
    GetUIPanels(pChild, pList, bOle);

  }
  
}

void CWndResizer::GetVisualPanels(CWndResizer::CPanel * pRoot, CPanelList * pList)
{
  if (pRoot == NULL )
  {
    return ;
  }

  CVisualPanel * pUIPanel = dynamic_cast<CVisualPanel *> ( pRoot);

  if (pUIPanel != NULL)
  {
    pList->AddTail( pRoot );
  }

  // try the childreen
  POSITION pos = pRoot->Children.GetHeadPosition();
  while(pos != NULL)
  {
    CPanel * pChild = pRoot->Children.GetNext(pos);
    GetVisualPanels(pChild, pList);
  }  
}


CWndResizer::CPanel * CWndResizer::FindSplitterFromPoint(CWndResizer::CPanel * pRoot, CPoint point)
{  
  if (pRoot == NULL )
  {
    return NULL;
  }

  CSpitterPanel * pSpitterPanel = dynamic_cast<CSpitterPanel *>(pRoot);

  if (pSpitterPanel != NULL && pRoot->PtInRect(point) == TRUE )
  {
    CSplitContainer * pContainer = (CSplitContainer *)pRoot->Parent;
    if (!pContainer->GetIsSplitterFixed())
    {
      CPoint ptScreen = point;
      m_pHookedWnd->ClientToScreen(&ptScreen);
      HWND hWndFromPoint = ::WindowFromPoint(ptScreen);
      if (m_pHookedWnd->m_hWnd == hWndFromPoint)
      {
        return pRoot;
      }
    }
  }

  // try the childreen
  POSITION pos = pRoot->Children.GetHeadPosition();
  while(pos != NULL)
  {
    CPanel * pChild = pRoot->Children.GetNext(pos);
    CPanel * pFound = FindSplitterFromPoint(pChild, point);
    if (pFound != NULL )
    {
      return pFound;
    }
  }
  
  
  return NULL;
}

CString CWndResizer::IdToName(UINT uID)
{
  CString sName;
  sName.Format(_T("%d"), uID);
  return sName;
}

CWndResizer::CUIPanel * CWndResizer::CreateUIPanel(UINT uID)
{
  ASSERT(m_pHookedWnd != NULL);
  CWnd * pWnd = m_pHookedWnd->GetDlgItem(uID);

  if ( pWnd == NULL )
  {
    return NULL;
  }
  CRect rc;
  pWnd->GetWindowRect( &rc );  
  m_pHookedWnd->ScreenToClient( &rc );

  CUIPanel * pPanel = new CUIPanel(&rc, uID);
  pPanel->Name = IdToName(uID);
  return pPanel ;
}

CWndResizer::CUIPanel * CWndResizer::GetUIPanel(UINT uID)
{
  CUIPanel * pPanel = NULL;
  if ((pPanel = (CUIPanel *)FindPanelByName(&root, IdToName(uID))) == NULL)  
  {
    pPanel = CreateUIPanel(uID);
    if (pPanel != NULL)
    {
      root.AddChild( pPanel );
    }
  }
  return pPanel;
}

BOOL CWndResizer::InvokeOnResized()
{
  ASSERT(m_pHookedWnd != NULL);

  CRect rc;
  m_pHookedWnd->GetClientRect(&rc);
  OnSize(0, rc.Width(), rc.Height());
  return TRUE;
}


CString CWndResizer::GetDebugInfo()
{
  ASSERT(m_pHookedWnd != NULL);

  CString sInfo;
  CString sIndent;

  GetDebugInfo(&root, sInfo, sIndent);

  return sInfo;
}
void CWndResizer::GetDebugInfo(CPanel * pRoot, CString & info, CString indent)
{
  if (pRoot == NULL )
  {
    return ;
  }

  info.Append(_T("\n"));
  info.Append(indent);
  info.Append(pRoot->ToString() );

  indent.Append(_T("  "));
  for(int i = 0; i < pRoot->Children.GetCount(); i++)
  {
    CPanel * pChild = pRoot->Children.GetAt(pRoot->Children.FindIndex(i));
    GetDebugInfo(pChild, info, indent);
  }
  
}


/  CPanel
///
CWndResizer::CPanel::CPanel()
{
  Init();
}
CWndResizer::CPanel::CPanel(const CRect * prc) : CRect(prc)
{
  Init();
}
void CWndResizer::CPanel::Init()
{
  Parent = NULL;
  LeftOffset = 0;
  TopOffset = 0;
  RightOffset = 0;
  BottomOffset = 0; 
  MinSize.SetSize(10, 10);
  MaxSize.SetSize(100000, 100000);
  Anchor =(ANCHOR_LEFT | ANCHOR_TOP);  
  Dock = DOCK_NONE;
}

CWndResizer::CPanel::~CPanel()
{
  while(Children.GetCount() > 0 )
  {
    delete Children.RemoveHead();
  }
}
void CWndResizer::CPanel::OnResized()
{
  BOOL bOk = FALSE;
  CRect rcEmpty(this);  // available area for docking.  ininitally it is the entire area

  POSITION pos = Children.GetHeadPosition();
  while(pos != NULL)
  {
    CPanel * pChild = Children.GetNext(pos);    
    
    if (pChild->Dock != DOCK_NONE)
    {
      switch(pChild->Dock)
      {
      case DOCK_LEFT:
        pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.left + pChild->Width(), rcEmpty.bottom);
        bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
        //ASSERT( bOk == TRUE);
        break;
      case DOCK_TOP:
        pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.right, rcEmpty.top + pChild->Height());
        bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
        //ASSERT( bOk == TRUE);
        break;
      case DOCK_RIGHT:
        pChild->SetRect(rcEmpty.right - pChild->Width(), rcEmpty.top, rcEmpty.right, rcEmpty.bottom);
        bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
        //ASSERT( bOk == TRUE);
        break;
      case DOCK_BOTTOM:
        pChild->SetRect(rcEmpty.left, rcEmpty.bottom - pChild->Height(), rcEmpty.right, rcEmpty.bottom);
        bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
        //ASSERT( bOk == TRUE);
        break;
      case DOCK_FILL:
        pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.right, rcEmpty.bottom);
        break;
      }
      pChild->OnResized();

      // if docking is in action, then we igonre anchor, therefore we continue
      continue;
    }

    CRect rc;
    if ((pChild->Anchor & ANCHOR_HORIZONTALLY_CENTERED) ==  ANCHOR_HORIZONTALLY_CENTERED )
    {
      rc.left = this->left + ((int)( (this->Width() - pChild->Width()) /  2));
      rc.right = rc.left + pChild->Width();

      BOOL bReposition = FALSE;
      if (pChild->MinSize.cx > rc.Width() )
      {
        bReposition = TRUE;
        rc.right = rc.left + pChild->MinSize.cx;
      }
      if (pChild->MaxSize.cx < rc.Width() )
      {
        bReposition = TRUE;
        rc.right = rc.left + pChild->MaxSize.cx;
      }

      if (bReposition)
      {
        int nWidth = rc.Width();
        rc.left = (int)( (this->Width() - nWidth) /  2) ;
        rc.right = rc.left + nWidth;
      }
    }
    else if ((pChild->Anchor & ANCHOR_HORIZONTALLY) ==  ANCHOR_HORIZONTALLY )
    {
      rc.left = this->left + pChild->LeftOffset;
      rc.right = this->right - pChild->RightOffset;

      // we will be left anchor if minsize or maxsize does not match
      // (giving ANCHOR_LEFT priority over ANCHOR_RIGHT)
      if ((pChild->Anchor & ANCHOR_PRIORITY_RIGHT) == ANCHOR_PRIORITY_RIGHT)
      {
        if (pChild->MinSize.cx > rc.Width() )
        {
          rc.left = rc.right - pChild->MinSize.cx;
        }
        if (pChild->MaxSize.cx < rc.Width() )
        {
          rc.left = rc.right - pChild->MaxSize.cx;
        }

      }
      else
      {
        if (pChild->MinSize.cx > rc.Width() )
        {
          rc.right = rc.left + pChild->MinSize.cx;
        }
        if (pChild->MaxSize.cx < rc.Width() )
        {
          rc.right = rc.left + pChild->MaxSize.cx;
        }
      }
    }
    else if ((pChild->Anchor & ANCHOR_RIGHT) ==  ANCHOR_RIGHT )
    {
      rc.right = this->right - pChild->RightOffset;     
      rc.left = rc.right - pChild->Width();

      if (pChild->MinSize.cx > rc.Width() )
      {
        rc.left = rc.right - pChild->MinSize.cx;
      }
      if (pChild->MaxSize.cx < rc.Width() )
      {
        rc.left = rc.right - pChild->MaxSize.cx;
      }
    }
    else if ((pChild->Anchor & ANCHOR_LEFT) == ANCHOR_LEFT )
    {
      rc.left = this->left + pChild->LeftOffset;
      rc.right = rc.left + pChild->Width();   

      if (pChild->MinSize.cx > rc.Width() )
      {
        rc.right = rc.left + pChild->MinSize.cx;
      }
      if (pChild->MaxSize.cx < rc.Width() )
      {
        rc.right = rc.left + pChild->MaxSize.cx;
      }
    }
    else
    {
      // it should never be here
      ASSERT( FALSE );
    }


    if ((pChild->Anchor & ANCHOR_VERTICALLY_CENTERED) ==  ANCHOR_VERTICALLY_CENTERED )
    {
      rc.top = this->top + ((int)( (this->Height() - pChild->Height()) /  2));
      rc.bottom = rc.top + pChild->Height();

      BOOL bReposition = FALSE;
      if (pChild->MinSize.cy > rc.Height() )
      {
        bReposition = TRUE;
        rc.bottom = rc.top + pChild->MinSize.cy;
      }
      if (pChild->MaxSize.cy < rc.Height() )
      {
        bReposition = TRUE;
        rc.bottom = rc.top + pChild->MaxSize.cy;
      }

      if (bReposition)
      {
        int nHeight = rc.Height();
        rc.top = (int)( (this->Height() - nHeight) /  2);
        rc.bottom = rc.top + nHeight;
      }
    }
    else if ((pChild->Anchor & ANCHOR_VERTICALLY ) == ANCHOR_VERTICALLY )
    {
      rc.top = this->top + pChild->TopOffset;
      rc.bottom = this->bottom - pChild->BottomOffset;

      if ((pChild->Anchor & ANCHOR_PRIORITY_BOTTOM) == ANCHOR_PRIORITY_BOTTOM)
      {
        if (pChild->MinSize.cy > rc.Height() )
        {
          rc.top = rc.bottom - pChild->MinSize.cy;
        }
        if (pChild->MaxSize.cy < rc.Height() )
        {
          rc.top = rc.bottom - pChild->MaxSize.cy;
        }
      }
      else
      {
        if (pChild->MinSize.cy > rc.Height() )
        {
          rc.bottom = rc.top + pChild->MinSize.cy;
        }
        if (pChild->MaxSize.cy < rc.Height() )
        {
          rc.bottom = rc.top + pChild->MaxSize.cy;
        }
      }
    }
    else if ((pChild->Anchor & ANCHOR_BOTTOM) == ANCHOR_BOTTOM )
    {
      rc.bottom = this->bottom - pChild->BottomOffset;     
      rc.top = rc.bottom - pChild->Height();

      if (pChild->MinSize.cy > rc.Height() )
      {
        rc.top = rc.bottom - pChild->MinSize.cy;
      }
      if (pChild->MaxSize.cy < rc.Height() )
      {
        rc.top = rc.bottom - pChild->MaxSize.cy;
      }
    }
    else if ((pChild->Anchor & ANCHOR_TOP) == ANCHOR_TOP )
    {
      rc.top = this->top + pChild->TopOffset;
      rc.bottom = rc.top + pChild->Height();   

      if (pChild->MinSize.cy > rc.Height() )
      {
        rc.bottom = rc.top + pChild->MinSize.cy;
      }
      if (pChild->MaxSize.cy < rc.Height() )
      {
        rc.bottom = rc.top + pChild->MaxSize.cy;
      }
    }
    else
    {
      // it should never be here
      ASSERT( FALSE );
    }
    pChild->SetRect(rc.TopLeft(), rc.BottomRight());

    pChild->OnResized();

  }
}
BOOL CWndResizer::CPanel::AddChild(CPanel * pChild)
{
  if (pChild->Parent != NULL)
  {
    BOOL bOk = pChild->Parent->RemoveChild(pChild);
    if (bOk == FALSE)
    {
      return FALSE;
    }
  }
  pChild->LeftOffset = pChild->left - this->left;
  pChild->TopOffset = pChild->top - this->top;
  pChild->RightOffset = this->right - pChild->right;
  pChild->BottomOffset = this->bottom - pChild->bottom;

  pChild->Parent = this;

  Children.AddTail( pChild );
  return TRUE;
}

BOOL CWndResizer::CPanel::RemoveChild(CPanel * pChild)
{
  POSITION pos = Children.Find(pChild);
  if (pos == NULL)
  {
    return FALSE;
  }
  Children.RemoveAt(pos);
  return TRUE;
  
}

BOOL CWndResizer::CPanel::SetMinSize(CSize & size)
{  
  if (MaxSize.cx < size.cx)  
  {
    return FALSE;
  }
  if (MaxSize.cy < size.cy)
  {
    return FALSE;
  }

  MinSize = size;
  return TRUE;
}
BOOL CWndResizer::CPanel::SetMaxSize(CSize & size)
{
  if (MinSize.cx > size.cx)  
  {
    return FALSE;
  }
  if (MinSize.cy > size.cy)
  {
    return FALSE;
  }

  MaxSize = size;
  return TRUE;
}

BOOL CWndResizer::CPanel::SetAnchor(UINT anchor)
{
  if ((anchor & ANCHOR_VERTICALLY_CENTERED) <= 0 )
  {
    if ((anchor & ANCHOR_TOP) <= 0 )
    {
      if ((anchor & ANCHOR_BOTTOM) <= 0 )
      {
        anchor |= ANCHOR_TOP;  // default
      }
    }
  }

  if ((anchor & ANCHOR_HORIZONTALLY_CENTERED) <= 0 )
  {
    if ((anchor & ANCHOR_LEFT) <= 0 )
    {
      if ((anchor & ANCHOR_RIGHT) <= 0 )
      {
        anchor |= ANCHOR_LEFT; // default
      }
    }
  }
  Anchor = anchor;

  return TRUE;
}
CString CWndResizer::CPanel::ToString()
{
  CString sFormat(_T("Name(%s), Type(%s), Anchor(%d), Size(w:%d, h:%d), Area(l:%d, t:%d, r:%d, b:%d), MinSize(w:%d, h:%d), MaxSize(w:%d, h:%d), Parent(%s), ChildrenCount(%d)"));

  CString sTo;
  sTo.Format(sFormat, Name, GetTypeName(), Anchor, Width(), Height(), left, top, right, bottom, MinSize.cx, MinSize.cy, MaxSize.cx, MaxSize.cy, (Parent == NULL? "NULL" : Parent->Name), Children.GetCount());
  return sTo;
}
CString CWndResizer::CPanel::GetTypeName()
{
  return _T("CPanel");
}

CWnd * CWndResizer::CPanel::GetHookedWnd()
{
  if (Parent != NULL)
  {
    return Parent->GetHookedWnd();
  }
  return NULL;
}

/  CSplitContainer
///
CWndResizer::CSplitContainer::CSplitContainer(CSplitPanel * pPanelA, CSplitPanel * pPanelB, CWndResizer::SplitterOrientation type) : CPanel()
{
  m_IsSplitterFixed = FALSE;
  m_FixedPanel = 0;

  m_pPanelA = NULL;
  m_pPanelB = NULL;
  m_pSplitter = NULL;

  m_Orientation = type;
  m_pPanelA = pPanelA;
  m_pPanelB = pPanelB;
  UnionRect(m_pPanelA, m_pPanelB);  

  CRect rc;  
  GetSplitArea(&rc);
  m_pSplitter = new CSpitterPanel(&rc, type);
  m_pSplitter->m_pGrippePanel->m_bVisible = FALSE;


  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
  {
    m_pPanelA->Anchor = (ANCHOR_LEFT | ANCHOR_TOP | ANCHOR_BOTTOM);
    m_pPanelB->Anchor = (ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM);
  }
  else
  {
    m_pPanelA->Anchor = (ANCHOR_LEFT | ANCHOR_TOP | ANCHOR_RIGHT);
    m_pPanelB->Anchor = (ANCHOR_LEFT | ANCHOR_BOTTOM | ANCHOR_RIGHT);
  }

  m_nSplitterSize = GetSplitterSize(m_pPanelA, m_pPanelB);

  BOOL bOk = AddChild(m_pPanelA);
  ASSERT(bOk == TRUE);

  bOk = AddChild(m_pSplitter);
  ASSERT(bOk == TRUE);

  bOk = AddChild(m_pPanelB);
  ASSERT(bOk == TRUE);

  UpdateRatio();
}

CWndResizer::CSplitContainer::~CSplitContainer()
{

}

void CWndResizer::CSplitContainer::OnResized()
{
  CPanel::OnResized();
 
  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
  {
    if (Width() < MinSize.cx)
    {
      return;
    }

    if (m_FixedPanel == 1 ) // left panel is fixed
    {
      m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;

      if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
      {
        m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
        m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
      }
    }
    else if (m_FixedPanel == 2 )  // right panel is fixed
    {
      m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;

      if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
      {
        m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
        m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
      }
    }
    else
    {
      m_pPanelA->right = (LONG) ((double)m_pPanelA->left + ((double)this->Width() * m_nRatio));

      if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
      {
        m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
      }

      m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;

      if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
      {
        m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
        m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
      }
    }

  }
  else /*if (m_Orientation == CWndResizer::SPLIT_CONTAINER_V)*/
  {
    if (Height() < MinSize.cy)
    {
      return;
    }

    if (m_FixedPanel == 1 ) // top panel is fixed
    {
      m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;

      if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
      {
        m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
        m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
      }
    }
    else if (m_FixedPanel == 2 )  // bottom panel is fixed
    {
      m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;

      if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
      {
        m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
        m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
      }
    }
    else
    {
      m_pPanelA->bottom = (LONG) ((double)m_pPanelA->top + ((double)this->Height() * m_nRatio));

      if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
      {
        m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
      }

      m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;

      if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
      {
        m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
        m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
      }
    }


  }

  GetSplitArea(m_pSplitter);
  m_pPanelA->OnResized();
  m_pPanelB->OnResized();
  m_pSplitter->OnResized();

}
void CWndResizer::CSplitContainer::SetSplitterPosition(int leftOfSplitter)
{ 

  short nFixedPanel = m_FixedPanel;
  m_FixedPanel = 0;
  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
  {    
    m_pPanelA->right = leftOfSplitter;
    m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
  }
  else
  {
    m_pPanelA->bottom = leftOfSplitter;
    m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
  }
  UpdateRatio();

  OnResized();

  UpdateRatio();
  m_FixedPanel = nFixedPanel;

}
int CWndResizer::CSplitContainer::GetSplitterPosition()
{ 
  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
  {    
    return m_pPanelA->right;
  }
  else
  {
    return m_pPanelA->bottom;
  }
}
BOOL CWndResizer::CSplitContainer::AddChild(CPanel * prc)
{
  if (Children.GetCount() == 3)
  {
    return FALSE;
  }
  return CPanel::AddChild(prc);

}
BOOL CWndResizer::CSplitContainer::RemoveChild(CPanel * prc)
{
  return FALSE; // cannot remove child from split container
}

void CWndResizer::CSplitContainer::GetSplitArea(CRect * pSplitterPanel)
{

  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
  {
    pSplitterPanel->left = m_pPanelA->right;
    pSplitterPanel->top = this->top;
    pSplitterPanel->right = m_pPanelB->left;
    pSplitterPanel->bottom = this->bottom;
  }
  else // vertical
  {
    pSplitterPanel->left = this->left;
    pSplitterPanel->top = m_pPanelA->bottom;
    pSplitterPanel->right = this->right;
    pSplitterPanel->bottom = m_pPanelB->top;
  }  
}
int CWndResizer::CSplitContainer::GetSplitterSize(CPanel * m_pPanelA, CPanel * m_pPanelB)
{
  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
  {
    int nWidth = m_pPanelB->left - m_pPanelA->right;
    return nWidth;
  }
  else // vertical
  {
    int nHeight = m_pPanelB->top - m_pPanelA->bottom;
    return nHeight;
  }  
}




void CWndResizer::CSplitContainer::UpdateRatio()
{

  if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
  {    
    m_nRatio = (double)m_pPanelA->Width() / (double)this->Width();
  }
  else
  {
    m_nRatio = (double)m_pPanelA->Height() / (double)this->Height();
  }

}

CWndResizer::CSplitContainer *  CWndResizer::CSplitContainer::Create(CPanel * pPanelA, CPanel * pPanelB)
{
  CSplitPanel * pSplitPanelA =  dynamic_cast<CSplitPanel *>( pPanelA );
  if (pSplitPanelA != NULL)
  {
    return NULL;  // already a part of a CSplitContainer
  }

  CSplitPanel * pSplitPanelB =  dynamic_cast<CSplitPanel *>( pPanelB );
  if (pSplitPanelB != NULL)
  {
    return NULL; // already a part of a CSplitContainer
  }

  CRect rcDest;
  CWndResizer::SplitterOrientation orien = CWndResizer::SPLIT_CONTAINER_H;

  if (::IntersectRect(&rcDest, pPanelA, pPanelB) == TRUE) // invalid spliter container, a spliter continer's two panel cannot intersect each other
  {
    return NULL;
  } 


  if (pPanelA->right < pPanelB->left)
  {
      orien = CWndResizer::SPLIT_CONTAINER_H;    
  }
  else if (pPanelA->bottom < pPanelB->top)
  {
      orien =  CWndResizer::SPLIT_CONTAINER_V;    
  }
  else
  {
    return NULL;
  }
  if (pPanelA->Parent != NULL)
  {
    if (pPanelA->Parent->RemoveChild( pPanelA ) == FALSE)
    {
      return NULL;
    }
  }
  if (pPanelB->Parent != NULL)
  {
    if (pPanelB->Parent->RemoveChild( pPanelB ) == FALSE)
    {
      return NULL;
    }
  }

  pSplitPanelA = new CSplitPanel( pPanelA );  
  pSplitPanelB = new CSplitPanel( pPanelB );  


  CSplitContainer * pSpliter = new CSplitContainer(pSplitPanelA, pSplitPanelB, orien);
  return pSpliter;

}

CString CWndResizer::CSplitContainer::GetTypeName()
{
  return _T("CSplitContainer");
}

void CWndResizer::CSplitContainer::SetFixedPanel(short nFixedPanel /* 1=left/top; 2=right/bototm; other=no fixed panel */)
{
  m_FixedPanel = nFixedPanel;
}
short CWndResizer::CSplitContainer::GetFixedPanel()
{
  return m_FixedPanel;
}
void CWndResizer::CSplitContainer::SetIsSplitterFixed(BOOL bFixed)
{
  m_IsSplitterFixed = bFixed;
}
BOOL CWndResizer::CSplitContainer::GetIsSplitterFixed()
{
  return m_IsSplitterFixed;
}
void CWndResizer::CSplitContainer::SetShowSplitterGrip(BOOL bShow)
{
  m_pSplitter->m_pGrippePanel->m_bVisible = bShow;
}
BOOL CWndResizer::CSplitContainer::GetShowSplitterGrip()
{
  return m_pSplitter->m_pGrippePanel->m_bVisible;
}


/  CRootPanel
///
CWndResizer::CRootPanel::CRootPanel() : CPanel()
{
  m_pHookWnd = NULL;
}
CWndResizer::CRootPanel::~CRootPanel()
{

}
CWnd * CWndResizer::CRootPanel::GetHookedWnd()
{
  return m_pHookWnd;
}
CString CWndResizer::CRootPanel::GetTypeName()
{
  return _T("CRootPanel");
}
/  CUIPanel
///
CWndResizer::CUIPanel::CUIPanel(const CRect * prc, UINT uID) : CPanel(prc)
{
  m_uID = uID;
  m_bOle = FALSE;
}
CWndResizer::CUIPanel::~CUIPanel()
{

}
CString CWndResizer::CUIPanel::GetTypeName()
{
  return _T("CUIPanel");
}

/  CVisualPanel
///
CWndResizer::CVisualPanel::CVisualPanel() : CPanel()
{
  m_bVisible = FALSE;
}
CWndResizer::CVisualPanel::CVisualPanel(const CRect * prc) : CPanel(prc)
{
  m_bVisible = FALSE;
  m_rcPrev.SetRect(this->left, this->top, this->right, this->bottom);
}
CWndResizer::CVisualPanel::~CVisualPanel()
{


}
void CWndResizer::CVisualPanel::Draw(CDC * pDC)
{

}
CString CWndResizer::CVisualPanel::GetTypeName()
{
  return _T("CVisualPanel");
}
void CWndResizer::CVisualPanel::OnResized()
{
  CWnd * pWnd = NULL;
  if ((pWnd = GetHookedWnd()) != NULL)
  {
    pWnd->InvalidateRect( &m_rcPrev, FALSE );
    pWnd->InvalidateRect( this, FALSE );
  }
  m_rcPrev.SetRect(this->left, this->top, this->right, this->bottom);
}

/  CGripperPanel
///
CWndResizer::CGripperPanel::CGripperPanel() : CVisualPanel()
{
  m_hTheme = NULL;
  m_iPartId = SBP_SIZEBOX;
  m_iStateId = 5; //SZB_HALFBOTTOMRIGHTALIGN;
  m_sClassName = _T("SCROLLBAR");
}
CWndResizer::CGripperPanel::CGripperPanel(const CRect * prc) : CVisualPanel(prc)
{
  m_hTheme = NULL;
  m_iPartId = SBP_SIZEBOX;
  m_iStateId = 5; //SZB_HALFBOTTOMRIGHTALIGN;
  m_sClassName = _T("SCROLLBAR");
}
CWndResizer::CGripperPanel::~CGripperPanel()
{
  if (m_hTheme != NULL)
  {
    HRESULT lres = ::CloseThemeData(m_hTheme);
    ASSERT(SUCCEEDED(lres) == TRUE);  
    m_hTheme = NULL;
  }
}
void CWndResizer::CGripperPanel::Draw(CDC * pDC)
{
  if (m_hTheme == NULL)
  {
    CWnd * pHookedWnd = GetHookedWnd();
    if (pHookedWnd == NULL)
    {
      return;
    }
    m_hTheme = ::OpenThemeData(pHookedWnd->m_hWnd, m_sClassName.AllocSysString());
  }

  if (m_hTheme == NULL)
  {
    BOOL bOk = pDC->DrawFrameControl(this, DFC_SCROLL, DFCS_SCROLLSIZEGRIP );
    ASSERT( bOk == TRUE);
  }
  else
  {
    HRESULT lres = ::DrawThemeBackground(m_hTheme, pDC->m_hDC, m_iPartId, m_iStateId, this, this);
    ASSERT(SUCCEEDED(lres) == TRUE);
  }
}

CString CWndResizer::CGripperPanel::GetTypeName()
{
  return _T("CGripperPanel");
}

/  CSplitterGripperPanel
///

CWndResizer::CSplitterGripperPanel::CSplitterGripperPanel(CWndResizer::SplitterOrientation type) : CVisualPanel()
{
  m_OrienType = type;
}
CWndResizer::CSplitterGripperPanel::~CSplitterGripperPanel()
{

}
void CWndResizer::CSplitterGripperPanel::Draw(CDC * pDC)
{
  CPen penDark(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
  CPen penWhite(PS_SOLID, 1, RGB(255, 255, 255));

  if (m_OrienType == CWndResizer::SPLIT_CONTAINER_H )
  {
    CPen * pOrigPen = pDC->SelectObject(&penWhite);    

    CRect rc;
    rc.SetRect(left + 1, top + 1, left + 3, top + 3); 
    while(rc.bottom <= bottom)
    {
      pDC->Rectangle(&rc);
      rc.OffsetRect(0, 4);
   }

    pDC->SelectObject(&penDark);
    rc.SetRect(left, top, left + 2, top + 2);
    while(rc.bottom <= bottom)
    {
      pDC->Rectangle(&rc);
     rc.OffsetRect(0, 4);
   }

    pDC->SelectObject(pOrigPen);

  }
  else
  {
    CPen * pOrigPen = pDC->SelectObject(&penWhite);    

    CRect rc;
    rc.SetRect(left + 1, top + 1, left + 3, top + 3); 
    while(rc.right <= right)
    {
      pDC->Rectangle(&rc);
      rc.OffsetRect(4, 0);
    }

    pDC->SelectObject(&penDark);
    rc.SetRect(left, top, left + 2, top + 2);
    while(rc.right <= right)
    {
      pDC->Rectangle(&rc);
      rc.OffsetRect(4, 0);
    }

    pDC->SelectObject(pOrigPen);
  } 
}

CString CWndResizer::CSplitterGripperPanel::GetTypeName()
{
  return _T("CSplitterGripperPanel");
}


/  CSpitterPanel
///
CWndResizer::CSpitterPanel::CSpitterPanel(const CRect * prc, CWndResizer::SplitterOrientation type) : CPanel(prc)
{
  m_OrienType = type;
  m_pGrippePanel = NULL;

  if (m_pGrippePanel == NULL)
  {
    m_pGrippePanel = new CSplitterGripperPanel(type);
    if (m_OrienType == CWndResizer::SPLIT_CONTAINER_H )
    {
      m_pGrippePanel->SetRect(0, 0, 3, 12);
    }
    else
    {
      m_pGrippePanel->SetRect(0, 0, 12, 3);
    }
    m_pGrippePanel->SetAnchor ( ANCHOR_HORIZONTALLY_CENTERED | ANCHOR_VERTICALLY_CENTERED );
    m_pGrippePanel->SetMinSize(CSize(2,2));
    BOOL bOk = AddChild(m_pGrippePanel);
    ASSERT(bOk == TRUE);
  }
}
CWndResizer::CSpitterPanel::CSpitterPanel(CWndResizer::SplitterOrientation type) : CPanel()
{
  m_OrienType = type;
  m_pGrippePanel = NULL;

}

CWndResizer::CSpitterPanel::~CSpitterPanel()
{

}


CString CWndResizer::CSpitterPanel::GetTypeName()
{
  return _T("CSpitterPanel");
}
/  CSpitPanel
///
CWndResizer::CSplitPanel::CSplitPanel(CPanel * pPanel) : CPanel(pPanel)
{
  pPanel->LeftOffset = 0;
  pPanel->TopOffset = 0;
  pPanel->RightOffset = 0;
  pPanel->BottomOffset = 0;
  pPanel->Anchor = ANCHOR_ALL;
  Name = pPanel->Name;
  pPanel->Name = _T("");
  m_pOriginalPanel = pPanel;
  MaxSize = pPanel->MaxSize;
  MinSize = pPanel->MinSize;
  Children.AddTail( pPanel );
}

CWndResizer::CSplitPanel::~CSplitPanel()
{

}

BOOL CWndResizer::CSplitPanel::SetAnchor(UINT anchor)
{
  return FALSE;
}

BOOL CWndResizer::CSplitPanel::AddChild(CPanel * prc)
{
  return m_pOriginalPanel->AddChild(prc);
}
BOOL CWndResizer::CSplitPanel::RemoveChild(CPanel * prc)
{
  return m_pOriginalPanel->RemoveChild(prc);
}


CString CWndResizer::CSplitPanel::GetTypeName()
{
  return _T("CSplitPanel");
}

/  CFlowLayoutPanel
///
CWndResizer::CFlowLayoutPanel::CFlowLayoutPanel() : CPanel()
{
  m_nItemSpacingX = 0;
  m_nItemSpacingY = 0;
  m_nFlowDirection = CWndResizer::LEFT_TO_RIGHT;
}
CWndResizer::CFlowLayoutPanel::CFlowLayoutPanel(const CRect * prc) : CPanel(prc)
{
  m_nItemSpacingX = 0;
  m_nItemSpacingY = 0;
  m_nFlowDirection = CWndResizer::LEFT_TO_RIGHT;
}
CWndResizer::CFlowLayoutPanel::~CFlowLayoutPanel()
{

}
void CWndResizer::CFlowLayoutPanel::OnResized()
{
  int max = 0; // maximimum height of a item in the row in case of left-to-right, otherwise maximum width of a item
  int x = left;
  int y = top;
  POSITION pos = Children.GetHeadPosition();

  // first one will be at the top-left corner, no matter what
  if (pos != NULL)
  {
    CPanel * pPanel = Children.GetNext(pos);
    pPanel->MoveToXY(x, y);
    pPanel->OnResized();

    if (m_nFlowDirection == CWndResizer::LEFT_TO_RIGHT)
    {
      x += pPanel->Width() + m_nItemSpacingX;
      max = (pPanel->Height() > max ? pPanel->Height() : max);
    }
    else
    {
      y += pPanel->Height() + m_nItemSpacingY;
      max = (pPanel->Width() > max ? pPanel->Width() : max);
    }
  }


  if (m_nFlowDirection == CWndResizer::LEFT_TO_RIGHT)
  {
    while(pos != NULL)
    {
      CPanel * pPanel = Children.GetNext(pos);
      // check to see if it is to wrap
      if (x + pPanel->Width() > right)
      {
        x = left;
        y += (max + m_nItemSpacingY);
        max = 0;
      }

      pPanel->MoveToXY(x, y);
      pPanel->OnResized();

      x += pPanel->Width() + m_nItemSpacingX;
      max = (pPanel->Height() > max ? pPanel->Height() : max);
    }
  }
  else
  {
    while(pos != NULL)
    {
      CPanel * pPanel = Children.GetNext(pos);
      // check to see if it is to wrap
      if (y + pPanel->Height() > bottom)
      {
        x += (max + m_nItemSpacingX);
        y = top;
        max = 0;
      }

      pPanel->MoveToXY(x, y);
      pPanel->OnResized();

      y += pPanel->Height() + m_nItemSpacingY;
      max = (pPanel->Width() > max ? pPanel->Width() : max);
    }

  }
}
CString CWndResizer::CFlowLayoutPanel::GetTypeName()
{
  return _T("CFlowLayoutPanel");

}
void CWndResizer::CFlowLayoutPanel::SetFlowDirection(CWndResizer::FlowDirection direction)
{
  m_nFlowDirection = direction;
}
CWndResizer::FlowDirection CWndResizer::CFlowLayoutPanel::GetFlowDirection()
{
  return m_nFlowDirection;
}
void CWndResizer::CFlowLayoutPanel::SetItemSpacingX(int nSpace)
{
  m_nItemSpacingX = nSpace;
}
int CWndResizer::CFlowLayoutPanel::GetItemSpacingX()
{
  return m_nItemSpacingX;
}
void CWndResizer::CFlowLayoutPanel::SetItemSpacingY(int nSpace)
{
  m_nItemSpacingY = nSpace;
}
int CWndResizer::CFlowLayoutPanel::GetItemSpacingY()
{
  return m_nItemSpacingY;
}

// 使用用例

  BOOL bOk = FALSE;
  bOk = m_resizer.Hook(this);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDC_EDIT_INPUT_FILE, ANCHOR_HORIZONTALLY);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDC_BUTTON_BROWSE, ANCHOR_RIGHT);
  ASSERT(bOk == TRUE);


  bOk = m_resizer.SetAnchor(IDC_FRAME_INPUT_TYPE, ANCHOR_VERTICALLY);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDC_FRAME_COMMENTS, ANCHOR_ALL);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDC_EDIT_COMMENTS, ANCHOR_ALL);
  ASSERT(bOk == TRUE);


  bOk = m_resizer.SetAnchor(IDC_CHECK_LOG, ANCHOR_HORIZONTALLY_CENTERED | ANCHOR_BOTTOM);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDOK, ANCHOR_RIGHT | ANCHOR_BOTTOM);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDCANCEL, ANCHOR_RIGHT | ANCHOR_BOTTOM);
  ASSERT(bOk == TRUE);

  m_resizer.SetShowResizeGrip(TRUE);

  bOk = m_resizer.InvokeOnResized();
  ASSERT(bOk == TRUE);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值