Fernando_Fiore

atlsplit2.h - see BEGIN_CHANGE

Sep 21st, 2020 (edited)
41
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Windows Template Library - WTL version 7.0
  2. // Copyright (C) 1997-2002 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This file is a part of the Windows Template Library.
  6. // The code and information is provided "as-is" without
  7. // warranty of any kind, either expressed or implied.
  8. // see BEGIN_CHANGE and END_CHANGE for the modifications
  9. // this splitter doesn't have to be parent of the contained windows
  10. // fernando fiore
  11.  
  12. #ifndef __ATLSPLIT_H__
  13. #define __ATLSPLIT_H__
  14.  
  15. #pragma once
  16.  
  17. #ifndef __cplusplus
  18.     #error ATL requires C++ compilation (use a .cpp suffix)
  19. #endif
  20.  
  21. #ifndef __ATLAPP_H__
  22.     #error atlsplit.h requires atlapp.h to be included first
  23. #endif
  24.  
  25. #ifndef __ATLWIN_H__
  26.     #error atlsplit.h requires atlwin.h to be included first
  27. #endif
  28.  
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // Classes in this file
  32. //
  33. // CSplitterImpl<T, t_bVertical>
  34. // CSplitterWindowImpl<T, t_bVertical, TBase, TWinTraits>
  35. // CSplitterWindowT<t_bVertical>
  36.  
  37.  
  38. namespace WTL
  39. {
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CSplitterImpl - Provides splitter support to any window
  43.  
  44. // Splitter panes constants
  45. #define SPLIT_PANE_LEFT          0
  46. #define SPLIT_PANE_RIGHT         1
  47. #define SPLIT_PANE_TOP           SPLIT_PANE_LEFT
  48. #define SPLIT_PANE_BOTTOM        SPLIT_PANE_RIGHT
  49. #define SPLIT_PANE_NONE         -1
  50.  
  51. // Splitter extended styles
  52. #define SPLIT_PROPORTIONAL      0x00000001
  53. #define SPLIT_NONINTERACTIVE        0x00000002
  54. #define SPLIT_RIGHTALIGNED      0x00000004
  55. #define SPLIT_BOTTOMALIGNED     SPLIT_RIGHTALIGNED
  56.  
  57. // Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are
  58. // mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL
  59.  
  60.  
  61. template <class T, bool t_bVertical = true>
  62. class CSplitterImpl
  63. {
  64. public:
  65.     enum { m_nPanesCount = 2, m_nPropMax = 10000 };
  66.  
  67.     HWND m_hWndPane[m_nPanesCount];
  68.     RECT m_rcSplitter;
  69.     int m_xySplitterPos;
  70.     int m_nDefActivePane;
  71.     int m_cxySplitBar;      // splitter bar width/height
  72.     static HCURSOR m_hCursor;
  73.     int m_cxyMin;           // minimum pane size
  74.     int m_cxyBarEdge;       // splitter bar edge
  75.     bool m_bFullDrag;
  76.     int m_cxyDragOffset;
  77.     int m_nProportionalPos;
  78.     bool m_bUpdateProportionalPos;
  79.     DWORD m_dwExtendedStyle;    // splitter specific extended styles
  80.     int m_nSinglePane;      // single pane mode
  81.  
  82. // Constructor
  83.     CSplitterImpl() :
  84.             m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE),
  85.             m_cxySplitBar(0), m_cxyMin(0), m_cxyBarEdge(0), m_bFullDrag(true),
  86.             m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true),
  87.             m_dwExtendedStyle(SPLIT_PROPORTIONAL),
  88.             m_nSinglePane(SPLIT_PANE_NONE)
  89.     {
  90.         m_hWndPane[SPLIT_PANE_LEFT] = NULL;
  91.         m_hWndPane[SPLIT_PANE_RIGHT] = NULL;
  92.  
  93.         ::SetRectEmpty(&m_rcSplitter);
  94.  
  95.         if(m_hCursor == NULL)
  96.         {
  97.             ::EnterCriticalSection(&_Module.m_csStaticDataInit);
  98.             if(m_hCursor == NULL)
  99.                 m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS);
  100.             ::LeaveCriticalSection(&_Module.m_csStaticDataInit);
  101.         }
  102.     }
  103.  
  104. // Attributes
  105.     void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true)
  106.     {
  107.         if(lpRect == NULL)
  108.         {
  109.             T* pT = static_cast<T*>(this);
  110.             pT->GetClientRect(&m_rcSplitter);
  111.         }
  112.         else
  113.         {
  114.             m_rcSplitter = *lpRect;
  115.         }
  116.  
  117.         if(IsProportional())
  118.             UpdateProportionalPos();
  119.         else if(IsRightAligned())
  120.             UpdateRightAlignPos();
  121.  
  122.         if(bUpdate)
  123.             UpdateSplitterLayout();
  124.     }
  125.  
  126.     void GetSplitterRect(LPRECT lpRect) const
  127.     {
  128.         ATLASSERT(lpRect != NULL);
  129.         *lpRect = m_rcSplitter;
  130.     }
  131.  
  132.     bool SetSplitterPos(int xyPos = -1, bool bUpdate = true)
  133.     {
  134.         if(xyPos == -1)     // -1 == middle
  135.         {
  136.             if(t_bVertical)
  137.                 xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
  138.             else
  139.                 xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
  140.         }
  141.  
  142.         // Adjust if out of valid range
  143.         int cxyMax = 0;
  144.         if(t_bVertical)
  145.             cxyMax = m_rcSplitter.right - m_rcSplitter.left;
  146.         else
  147.             cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
  148.  
  149.         if(xyPos < m_cxyMin + m_cxyBarEdge)
  150.             xyPos = m_cxyMin;
  151.         else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
  152.             xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
  153.  
  154.         // Set new position and update if requested
  155.         bool bRet = (m_xySplitterPos != xyPos);
  156.         m_xySplitterPos = xyPos;
  157.  
  158.         if(m_bUpdateProportionalPos)
  159.         {
  160.             if(IsProportional())
  161.                 StoreProportionalPos();
  162.             else if(IsRightAligned())
  163.                 StoreRightAlignPos();
  164.         }
  165.         else
  166.         {
  167.             m_bUpdateProportionalPos = true;
  168.         }
  169.  
  170.         if(bUpdate && bRet)
  171.             UpdateSplitterLayout();
  172.  
  173.         return bRet;
  174.     }
  175.  
  176.     void SetSplitterPosPct(int nPct, bool bUpdate = true)
  177.     {
  178.         ATLASSERT((nPct >= 0) && (nPct <= 100));
  179.         m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100);
  180.         UpdateProportionalPos();
  181.         if (bUpdate)
  182.             UpdateSplitterLayout();
  183.     }
  184.  
  185.     int GetSplitterPos() const
  186.     {
  187.         return m_xySplitterPos;
  188.     }
  189.  
  190.     bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE)
  191.     {
  192.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE);
  193.         if(!(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE))
  194.             return false;
  195.  
  196.         if(nPane != SPLIT_PANE_NONE)
  197.         {
  198.             if(!::IsWindowVisible(m_hWndPane[nPane]))
  199.                 ::ShowWindow(m_hWndPane[nPane], SW_SHOW);
  200.             int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
  201.             ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE);
  202.             if(m_nDefActivePane != nPane)
  203.                 m_nDefActivePane = nPane;
  204.         }
  205.         else if(m_nSinglePane != SPLIT_PANE_NONE)
  206.         {
  207.             int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
  208.             ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW);
  209.         }
  210.  
  211.         m_nSinglePane = nPane;
  212.         UpdateSplitterLayout();
  213.         return true;
  214.     }
  215.  
  216.     int GetSinglePaneMode() const
  217.     {
  218.         return m_nSinglePane;
  219.     }
  220.  
  221.     DWORD GetSplitterExtendedStyle() const
  222.     {
  223.         return m_dwExtendedStyle;
  224.     }
  225.  
  226.     DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
  227.     {
  228.         DWORD dwPrevStyle = m_dwExtendedStyle;
  229.         if(dwMask == 0)
  230.             m_dwExtendedStyle = dwExtendedStyle;
  231.         else
  232.             m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
  233. #ifdef _DEBUG
  234.         if(IsProportional() && IsRightAligned())
  235.             ATLTRACE2(atlTraceUI, 0, "CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n");
  236. #endif //_DEBUG
  237.         return dwPrevStyle;
  238.     }
  239.  
  240. // Splitter operations
  241.     void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true)
  242.     {
  243.         m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop;
  244.         m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom;
  245.         ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]);
  246.         if(bUpdate)
  247.             UpdateSplitterLayout();
  248.     }
  249.  
  250.     bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true)
  251.     {
  252.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
  253.  
  254.         if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
  255.             return false;
  256.         m_hWndPane[nPane] = hWnd;
  257.         ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]);
  258.         if(bUpdate)
  259.             UpdateSplitterLayout();
  260.         return true;
  261.     }
  262.  
  263.     HWND GetSplitterPane(int nPane) const
  264.     {
  265.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
  266.  
  267.         if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
  268.             return false;
  269.         return m_hWndPane[nPane];
  270.     }
  271.  
  272.     bool SetActivePane(int nPane)
  273.     {
  274.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
  275.  
  276.         if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
  277.             return false;
  278.         if(m_nSinglePane != SPLIT_PANE_NONE && nPane != m_nSinglePane)
  279.             return false;
  280.         ::SetFocus(m_hWndPane[nPane]);
  281.         m_nDefActivePane = nPane;
  282.         return true;
  283.     }
  284.  
  285.     int GetActivePane() const
  286.     {
  287.         int nRet = SPLIT_PANE_NONE;
  288.         HWND hWndFocus = ::GetFocus();
  289.         if(hWndFocus != NULL)
  290.         {
  291.             for(int nPane = 0; nPane < m_nPanesCount; nPane++)
  292.             {
  293.                 if(hWndFocus == m_hWndPane[nPane] || ::IsChild(m_hWndPane[nPane], hWndFocus))
  294.                 {
  295.                     nRet = nPane;
  296.                     break;
  297.                 }
  298.             }
  299.         }
  300.         return nRet;
  301.     }
  302.  
  303.     bool ActivateNextPane(bool bNext = true)
  304.     {
  305.         int nPane = m_nSinglePane;
  306.         if(nPane == SPLIT_PANE_NONE)
  307.         {
  308.             switch(GetActivePane())
  309.             {
  310.             case SPLIT_PANE_LEFT:
  311.                 nPane = SPLIT_PANE_RIGHT;
  312.                 break;
  313.             case SPLIT_PANE_RIGHT:
  314.                 nPane = SPLIT_PANE_LEFT;
  315.                 break;
  316.             default:
  317.                 nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT;
  318.                 break;
  319.             }
  320.         }
  321.         return SetActivePane(nPane);
  322.     }
  323.  
  324.     bool SetDefaultActivePane(int nPane)
  325.     {
  326.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
  327.  
  328.         if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT)
  329.             return false;
  330.         m_nDefActivePane = nPane;
  331.         return true;
  332.     }
  333.  
  334.     bool SetDefaultActivePane(HWND hWnd)
  335.     {
  336.         for(int nPane = 0; nPane < m_nPanesCount; nPane++)
  337.         {
  338.             if(hWnd == m_hWndPane[nPane])
  339.             {
  340.                 m_nDefActivePane = nPane;
  341.                 return true;
  342.             }
  343.         }
  344.         return false;   // not found
  345.     }
  346.  
  347.     int GetDefaultActivePane() const
  348.     {
  349.         return m_nDefActivePane;
  350.     }
  351.  
  352.     void DrawSplitter(CDCHandle dc)
  353.     {
  354.         ATLASSERT(dc.m_hDC != NULL);
  355.         if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
  356.             return;
  357.  
  358.         T* pT = static_cast<T*>(this);
  359.         if(m_nSinglePane == SPLIT_PANE_NONE)
  360.         {
  361.             pT->DrawSplitterBar(dc);
  362.  
  363.             for(int nPane = 0; nPane < m_nPanesCount; nPane++)
  364.             {
  365.                 if(m_hWndPane[nPane] == NULL)
  366.                     pT->DrawSplitterPane(dc, nPane);
  367.             }
  368.         }
  369.         else
  370.         {
  371.             if(m_hWndPane[m_nSinglePane] == NULL)
  372.                 pT->DrawSplitterPane(dc, m_nSinglePane);
  373.         }
  374.     }
  375.  
  376. // Overrideables
  377.     void DrawSplitterBar(CDCHandle dc)
  378.     {
  379.         RECT rect;
  380.         if(GetSplitterBarRect(&rect))
  381.         {
  382.             dc.FillRect(&rect, COLOR_3DFACE);
  383.             // draw 3D edge if needed
  384.             T* pT = static_cast<T*>(this);
  385.             if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
  386.                 dc.DrawEdge(&rect, EDGE_RAISED, t_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM));
  387.         }
  388.     }
  389.  
  390.     // called only if pane is empty
  391.     void DrawSplitterPane(CDCHandle dc, int nPane)
  392.     {
  393.         RECT rect;
  394.         if(GetSplitterPaneRect(nPane, &rect))
  395.         {
  396.             T* pT = static_cast<T*>(this);
  397.             if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0)
  398.                 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  399.             dc.FillRect(&rect, COLOR_APPWORKSPACE);
  400.         }
  401.     }
  402.  
  403. // Message map and handlers
  404.     typedef CSplitterImpl< T, t_bVertical>  thisClass;
  405.     BEGIN_MSG_MAP(thisClass)
  406.         MESSAGE_HANDLER(WM_CREATE, OnCreate)
  407.         MESSAGE_HANDLER(WM_PAINT, OnPaint)
  408.         MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
  409.         if(IsInteractive())
  410.         {
  411.             MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
  412.             MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
  413.             MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
  414.             MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
  415.             MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick)
  416.         }
  417.         MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  418.         MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
  419.         MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
  420.     END_MSG_MAP()
  421.  
  422.     LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  423.     {
  424.         GetSystemSettings(false);
  425.         bHandled = FALSE;
  426.         return 1;
  427.     }
  428.  
  429.     LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  430.     {
  431.         T* pT = static_cast<T*>(this);
  432.         // try setting position if not set
  433.         if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
  434.             pT->SetSplitterPos();
  435.         // do painting
  436.         CPaintDC dc(pT->m_hWnd);
  437.         pT->DrawSplitter(dc.m_hDC);
  438.         return 0;
  439.     }
  440.  
  441.     LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  442.     {
  443.         T* pT = static_cast<T*>(this);
  444.         if((HWND)wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT)
  445.         {
  446.             DWORD dwPos = ::GetMessagePos();
  447.             POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
  448.             pT->ScreenToClient(&ptPos);
  449.             if(IsOverSplitterBar(ptPos.x, ptPos.y))
  450.                 return 1;
  451.         }
  452.  
  453.         bHandled = FALSE;
  454.         return 0;
  455.     }
  456.  
  457.     LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  458.     {
  459.         T* pT = static_cast<T*>(this);
  460.         int xPos = GET_X_LPARAM(lParam);
  461.         int yPos = GET_Y_LPARAM(lParam);
  462.         if((wParam & MK_LBUTTON) && ::GetCapture() == pT->m_hWnd)
  463.         {
  464.             int xyNewSplitPos = 0;
  465.             if(t_bVertical)
  466.                 xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset;
  467.             else
  468.                 xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset;
  469.  
  470.             if(xyNewSplitPos == -1) // avoid -1, that means middle
  471.                 xyNewSplitPos = -2;
  472.  
  473.             if(m_xySplitterPos != xyNewSplitPos)
  474.             {
  475.                 if(m_bFullDrag)
  476.                 {
  477.                     if(pT->SetSplitterPos(xyNewSplitPos, true))
  478.                         pT->UpdateWindow();
  479.                 }
  480.                 else
  481.                 {
  482.                     DrawGhostBar();
  483.                     pT->SetSplitterPos(xyNewSplitPos, false);
  484.                     DrawGhostBar();
  485.                 }
  486.             }
  487.         }
  488.         else        // not dragging, just set cursor
  489.         {
  490.             if(IsOverSplitterBar(xPos, yPos))
  491.                 ::SetCursor(m_hCursor);
  492.             bHandled = FALSE;
  493.         }
  494.  
  495.         return 0;
  496.     }
  497.  
  498.     LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
  499.     {
  500.         int xPos = GET_X_LPARAM(lParam);
  501.         int yPos = GET_Y_LPARAM(lParam);
  502.         if(IsOverSplitterBar(xPos, yPos))
  503.         {
  504.             T* pT = static_cast<T*>(this);
  505.             pT->SetCapture();
  506.             ::SetCursor(m_hCursor);
  507.             if(!m_bFullDrag)
  508.                 DrawGhostBar();
  509.             if(t_bVertical)
  510.                 m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos;
  511.             else
  512.                 m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos;
  513.         }
  514.         bHandled = FALSE;
  515.         return 1;
  516.     }
  517.  
  518.     LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  519.     {
  520.         if(!m_bFullDrag)
  521.         {
  522.             DrawGhostBar();
  523.             T* pT = static_cast<T*>(this);
  524.             UpdateSplitterLayout();
  525.             pT->UpdateWindow();
  526.         }
  527.         ::ReleaseCapture();
  528.         bHandled = FALSE;
  529.         return 1;
  530.     }
  531.  
  532.     LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  533.     {
  534.         T* pT = static_cast<T*>(this);
  535.         pT->SetSplitterPos();   // middle
  536.         return 0;
  537.     }
  538.  
  539.     LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled)
  540.     {
  541.         if(m_nSinglePane == SPLIT_PANE_NONE)
  542.         {
  543.             if(m_nDefActivePane == SPLIT_PANE_LEFT || m_nDefActivePane == SPLIT_PANE_RIGHT)
  544.                 ::SetFocus(m_hWndPane[m_nDefActivePane]);
  545.         }
  546.         else
  547.         {
  548.             ::SetFocus(m_hWndPane[m_nSinglePane]);
  549.         }
  550.         bHandled = FALSE;
  551.         return 1;
  552.     }
  553.  
  554.     LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  555.     {
  556.         T* pT = static_cast<T*>(this);
  557.         LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
  558.         if(lRet == MA_ACTIVATE || lRet == MA_ACTIVATEANDEAT)
  559.         {
  560.             DWORD dwPos = ::GetMessagePos();
  561.             POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
  562.             pT->ScreenToClient(&pt);
  563.             RECT rcPane;
  564.             for(int nPane = 0; nPane < m_nPanesCount; nPane++)
  565.             {
  566.                 if(GetSplitterPaneRect(nPane, &rcPane) && ::PtInRect(&rcPane, pt))
  567.                 {
  568.                     m_nDefActivePane = nPane;
  569.                     break;
  570.                 }
  571.             }
  572.         }
  573.         return lRet;
  574.     }
  575.  
  576.     LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  577.     {
  578.         GetSystemSettings(true);
  579.         return 0;
  580.     }
  581.  
  582. // Implementation - internal helpers
  583.     void UpdateSplitterLayout()
  584.     {
  585.         if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1)
  586.             return;
  587.  
  588.         T* pT = static_cast<T*>(this);
  589.         RECT rect = { 0, 0, 0, 0 };
  590.         if(m_nSinglePane == SPLIT_PANE_NONE)
  591.         {
  592.             if(GetSplitterBarRect(&rect))
  593.                 pT->InvalidateRect(&rect);
  594.  
  595.             for(int nPane = 0; nPane < m_nPanesCount; nPane++)
  596.             {
  597.                 if(GetSplitterPaneRect(nPane, &rect))
  598.                 {
  599.                     if(m_hWndPane[nPane] != NULL){
  600.                         /* BEGIN_CHANGE */
  601.                         CWindow wndParent = ::GetParent(m_hWndPane[nPane]);
  602.  
  603.                         if(pT->m_hWnd != wndParent.m_hWnd){
  604.                             pT->MapWindowPoints(wndParent,&rect);
  605.                         }
  606.                         BOOL bDebug = ::SetWindowPos(m_hWndPane[nPane], HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
  607.                         ATLASSERT(bDebug);
  608.                         /* END_CHANGE */
  609.                     }
  610.                     else
  611.                         pT->InvalidateRect(&rect);
  612.                 }
  613.             }
  614.         }
  615.         else
  616.         {
  617.             if(GetSplitterPaneRect(m_nSinglePane, &rect))
  618.             {
  619.                 if(m_hWndPane[m_nSinglePane] != NULL){
  620.                         /* BEGIN_CHANGE */
  621.                         CWindow wndParent = ::GetParent(m_hWndPane[m_nSinglePane]);
  622.  
  623.                         if(pT->m_hWnd != wndParent.m_hWnd){
  624.                             pT->MapWindowPoints(wndParent,&rect);
  625.                         }
  626.                         BOOL bDebug = ::SetWindowPos(m_hWndPane[m_nSinglePane], HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
  627.                         ATLASSERT(bDebug);
  628.                         /* END_CHANGE */
  629.                 }
  630.                 else
  631.                     pT->InvalidateRect(&rect);
  632.             }
  633.         }
  634.     }
  635.  
  636.     bool GetSplitterBarRect(LPRECT lpRect) const
  637.     {
  638.         ATLASSERT(lpRect != NULL);
  639.         if(m_nSinglePane != SPLIT_PANE_NONE || m_xySplitterPos == -1)
  640.             return false;
  641.  
  642.         if(t_bVertical)
  643.         {
  644.             lpRect->left = m_rcSplitter.left + m_xySplitterPos;
  645.             lpRect->top = m_rcSplitter.top;
  646.             lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
  647.             lpRect->bottom = m_rcSplitter.bottom;
  648.         }
  649.         else
  650.         {
  651.             lpRect->left = m_rcSplitter.left;
  652.             lpRect->top = m_rcSplitter.top + m_xySplitterPos;
  653.             lpRect->right = m_rcSplitter.right;
  654.             lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
  655.         }
  656.  
  657.         return true;
  658.     }
  659.  
  660.     bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const
  661.     {
  662.         ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT);
  663.         ATLASSERT(lpRect != NULL);
  664.         bool bRet = true;
  665.         if(m_nSinglePane != SPLIT_PANE_NONE)
  666.         {
  667.             if(nPane == m_nSinglePane)
  668.                 *lpRect = m_rcSplitter;
  669.             else
  670.                 bRet = false;
  671.         }
  672.         else if(nPane == SPLIT_PANE_LEFT)
  673.         {
  674.             if(t_bVertical)
  675.             {
  676.                 lpRect->left = m_rcSplitter.left;
  677.                 lpRect->top = m_rcSplitter.top;
  678.                 lpRect->right = m_rcSplitter.left + m_xySplitterPos;
  679.                 lpRect->bottom = m_rcSplitter.bottom;
  680.             }
  681.             else
  682.             {
  683.                 lpRect->left = m_rcSplitter.left;
  684.                 lpRect->top = m_rcSplitter.top;
  685.                 lpRect->right = m_rcSplitter.right;
  686.                 lpRect->bottom = m_rcSplitter.top + m_xySplitterPos;
  687.             }
  688.         }  
  689.         else if(nPane == SPLIT_PANE_RIGHT)
  690.         {
  691.             if(t_bVertical)
  692.             {
  693.                 lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
  694.                 lpRect->top = m_rcSplitter.top;
  695.                 lpRect->right = m_rcSplitter.right;
  696.                 lpRect->bottom = m_rcSplitter.bottom;
  697.             }
  698.             else
  699.             {
  700.                 lpRect->left = m_rcSplitter.left;
  701.                 lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
  702.                 lpRect->right = m_rcSplitter.right;
  703.                 lpRect->bottom = m_rcSplitter.bottom;
  704.             }
  705.         }
  706.         else
  707.         {
  708.             bRet = false;
  709.         }
  710.         return bRet;
  711.     }
  712.  
  713.     bool IsOverSplitterRect(int x, int y) const
  714.     {
  715.         // -1 == don't check
  716.         return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) &&
  717.             (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom)));
  718.     }
  719.  
  720.     bool IsOverSplitterBar(int x, int y) const
  721.     {
  722.         if(m_nSinglePane != SPLIT_PANE_NONE)
  723.             return false;
  724.         if(m_xySplitterPos == -1 || !IsOverSplitterRect(x, y))
  725.             return false;
  726.         int xy = t_bVertical ? x : y;
  727.         int xyOff = t_bVertical ? m_rcSplitter.left : m_rcSplitter.top;
  728.         return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge));
  729.     }
  730.  
  731.     void DrawGhostBar()
  732.     {
  733.         RECT rect = { 0, 0, 0, 0 };
  734.         if(GetSplitterBarRect(&rect))
  735.         {
  736.             // invert the brush pattern (looks just like frame window sizing)
  737.             T* pT = static_cast<T*>(this);
  738.             CWindowDC dc(pT->m_hWnd);
  739.             CBrush brush = CDCHandle::GetHalftoneBrush();
  740.             if(brush.m_hBrush != NULL)
  741.             {
  742.                 CBrushHandle brushOld = dc.SelectBrush(brush);
  743.                 dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
  744.                 dc.SelectBrush(brushOld);
  745.             }
  746.         }
  747.     }
  748.  
  749.     void GetSystemSettings(bool bUpdate)
  750.     {
  751.         m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME);
  752.  
  753.         T* pT = static_cast<T*>(this);
  754.         if((pT->GetExStyle() & WS_EX_CLIENTEDGE))
  755.         {
  756.             m_cxyBarEdge = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE);
  757.             m_cxyMin = 0;
  758.         }
  759.         else
  760.         {
  761.             m_cxyBarEdge = 0;
  762.             m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE);
  763.         }
  764.  
  765.         ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0);
  766.  
  767.         if(bUpdate)
  768.             UpdateSplitterLayout();
  769.     }
  770.  
  771.     bool IsProportional() const
  772.     {
  773.         return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0);
  774.     }
  775.  
  776.     void StoreProportionalPos()
  777.     {
  778.         int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
  779.         if(cxyTotal > 0)
  780.             m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal);
  781.         else
  782.             m_nProportionalPos = 0;
  783.         ATLTRACE2(atlTraceUI, 0, "CSplitterImpl::StoreProportionalPos - %i\n", m_nProportionalPos);
  784.     }
  785.  
  786.     void UpdateProportionalPos()
  787.     {
  788.         int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
  789.         if(cxyTotal > 0)
  790.         {
  791.             int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax);
  792.             m_bUpdateProportionalPos = false;
  793.             T* pT = static_cast<T*>(this);
  794.             pT->SetSplitterPos(xyNewPos, false);
  795.         }
  796.     }
  797.  
  798.     bool IsRightAligned() const
  799.     {
  800.         return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0);
  801.     }
  802.  
  803.     void StoreRightAlignPos()
  804.     {
  805.         int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
  806.         if(cxyTotal > 0)
  807.             m_nProportionalPos = cxyTotal - m_xySplitterPos;
  808.         else
  809.             m_nProportionalPos = 0;
  810.         ATLTRACE2(atlTraceUI, 0, "CSplitterImpl::StoreRightAlignPos - %i\n", m_nProportionalPos);
  811.     }
  812.  
  813.     void UpdateRightAlignPos()
  814.     {
  815.         int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
  816.         if(cxyTotal > 0)
  817.         {
  818.             m_bUpdateProportionalPos = false;
  819.             T* pT = static_cast<T*>(this);
  820.             pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false);
  821.         }
  822.     }
  823.  
  824.     bool IsInteractive() const
  825.     {
  826.         return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0);
  827.     }
  828. };
  829.  
  830. template <class T, bool t_bVertical> HCURSOR CSplitterImpl< T, t_bVertical>::m_hCursor = NULL;
  831.  
  832.  
  833. /////////////////////////////////////////////////////////////////////////////
  834. // CSplitterWindowImpl - Implements a splitter window
  835.  
  836. template <class T, bool t_bVertical = true, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  837. class ATL_NO_VTABLE CSplitterWindowImpl : public CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T , t_bVertical >
  838. {
  839. public:
  840.     DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW)
  841.  
  842.     typedef CSplitterWindowImpl< T , t_bVertical, TBase, TWinTraits >   thisClass;
  843.     typedef CSplitterImpl< T , t_bVertical >                baseClass;
  844.     BEGIN_MSG_MAP(thisClass)
  845.         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
  846.         MESSAGE_HANDLER(WM_SIZE, OnSize)
  847.         CHAIN_MSG_MAP(baseClass)
  848.         FORWARD_NOTIFICATIONS()
  849.     END_MSG_MAP()
  850.  
  851.     LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  852.     {
  853.         // handled, no background painting needed
  854.         return 1;
  855.     }
  856.  
  857.     LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
  858.     {
  859.         if(wParam != SIZE_MINIMIZED)
  860.             SetSplitterRect();
  861.  
  862.         bHandled = FALSE;
  863.         return 1;
  864.     }
  865. };
  866.  
  867.  
  868. /////////////////////////////////////////////////////////////////////////////
  869. // CSplitterWindow - Implements a splitter window to be used as is
  870.  
  871. template <bool t_bVertical = true>
  872. class CSplitterWindowT : public CSplitterWindowImpl<CSplitterWindowT<t_bVertical>, t_bVertical>
  873. {
  874. public:
  875.     DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW)
  876. };
  877.  
  878. typedef CSplitterWindowT<true>  CSplitterWindow;
  879. typedef CSplitterWindowT<false> CHorSplitterWindow;
  880.  
  881. }; //namespace WTL
  882.  
  883. #endif // __ATLSPLIT_H__
  884.  
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×