⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atldock.h

📁 这是一本学习 window编程的很好的参考教材
💻 H
📖 第 1 页 / 共 4 页
字号:
         return 1;
      }
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnRightButtonDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {
      // We don't particular like the right - mousebutton. We need to
      // disable the system menu because it causes problems...
      if( wParam == HTCAPTION ) return 1;
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnButtonDblClick(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {
      // Don't like double-clicks either. We need to disable
      // maximize on double-click for floating windows as well.
      if( wParam == HTCAPTION ) return 1;
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Forward a failed menu-key strike to main window.
      // Perhaps it will show the menu for this key.
      LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
      if( HIWORD(lRes) == MNC_IGNORE ) {
         CWindow wndRoot = m_pCtx->hwndRoot;
         return ::SendMessage(wndRoot.GetTopLevelParent(), uMsg, wParam, lParam);
      }
      return lRes;
   }

   LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
   {
      switch( wParam & 0xFFF0 ) {
      case SC_CLOSE:
         if( m_pCtx->dwFlags & DCK_NOHIDE ) return 0;
         // Use post message so it comes async
         ::PostMessage(m_pCtx->hwndRoot, WM_DOCK_CLIENT_CLOSE, WM_DOCK_UNFLOAT, (LPARAM) m_pCtx);
         return 0;
      }
      bHandled = FALSE;
      return 0;
   }

   LRESULT OnMsgForward(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
   {
      // Forward to view
      return ::SendMessage(m_pCtx->hwndChild, uMsg, wParam, lParam);
   }

   // Track methods

   void OnMove(POINT& pt)
   {
      TRACKINFO ti = { m_hWnd, m_pCtx, pt.x, pt.y, m_ptStartDragPoint.x, m_ptStartDragPoint.y };
      ::SendMessage(m_pCtx->hwndRoot, WM_DOCK_QUERYTRACK, 0, (LPARAM) &ti);
      if( !::EqualRect(&m_rcTracker, &ti.rc) ) {
         DrawDragBar();
         m_rcTracker = ti.rc;
         DrawDragBar();
      }
      m_ptEndDragPoint = pt;
   }

   // Overridables

   void UpdateLayout()
   {
      RECT rc;
      GetWindowRect(&rc);
      m_pCtx->sizeFloat.cx = rc.right - rc.left;
      m_pCtx->sizeFloat.cy = rc.bottom - rc.top;
      GetClientRect(&rc);
      ::SetWindowPos(m_pCtx->hwndChild, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER);
   }
};

class CFloatingWindow : public CFloatingWindowImpl<CFloatingWindow>
{
public:
   DECLARE_WND_CLASS_EX(_T("WTL_FloatingWindow"), CS_DBLCLKS, NULL)

   CFloatingWindow(DOCKCONTEXT* ctx) :
      CFloatingWindowImpl<CFloatingWindow>(ctx)
   { 
   }
};


///////////////////////////////////////////////////////
// CDockingPaneChildWindow

template< class T, class TBase = CWindow, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE CDockingPaneChildWindowImpl : 
   public CWindowImpl< T, TBase, TWinTraits >,
   public CSplitterBar<CDockingPaneChildWindowImpl>
{
public:
   DECLARE_WND_CLASS_EX(NULL, CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, NULL)

   typedef CDockingPaneChildWindowImpl< T , TBase, TWinTraits > thisClass;
   
   BEGIN_MSG_MAP(CDockingPaneChildWindowImpl)
      MESSAGE_HANDLER(WM_PAINT, OnPaint)
      MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
      MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
      MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
      MESSAGE_HANDLER(WM_LBUTTONDOWN, OnButtonDown)
      MESSAGE_HANDLER(WM_LBUTTONUP, OnButtonUp)
      MESSAGE_HANDLER(WM_SIZE, OnSize)
      MESSAGE_HANDLER(WM_DOCK_UPDATELAYOUT, OnSize)
      MESSAGE_HANDLER(WM_DOCK_SETSPLITTER, OnSetSplitter)
   END_MSG_MAP()

   DOCKCONTEXT* m_pCtx;
   RECT m_rcChild;
   RECT m_rcSplitter;
   RECT m_rcGripper;
   RECT m_rcCloseButton;
   int m_cxyGripper;
   int m_cxyCloseButton;
   bool m_fCloseCapture;
   bool m_fCloseDown;

   CDockingPaneChildWindowImpl(DOCKCONTEXT* pCtx) :
      m_pCtx(pCtx), 
      m_fCloseDown(false), 
      m_fCloseCapture(false)
   {
      ::SetRectEmpty(&m_rcChild);
      ::SetRectEmpty(&m_rcGripper);
      ::SetRectEmpty(&m_rcSplitter);
      ::SetRectEmpty(&m_rcCloseButton);
      //m_cxyGripper = ::GetSystemMetrics(SM_CYCAPTION)*4/5;
      //m_cxyCloseButton = m_cxyGripper-2;
      m_cxyGripper = ::GetSystemMetrics(SM_CYSMCAPTION);
      m_cxyCloseButton = ::GetSystemMetrics(SM_CYSMSIZE)-4;

   }

   virtual void OnFinalMessage(HWND /*hWnd*/)
   {
      delete (T*) this;
   }

   LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      return 1; // handled, no background painting needed
   }

   LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      T* pT = static_cast<T*>(this);
      pT->UpdateLayout();
      return 0;
   }

   LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      T* pT = static_cast<T*>(this);
      CPaintDC dc(m_hWnd);
      dc.ExcludeClipRect(&m_rcChild);
      RECT rc;
      GetClientRect(&rc);
      dc.FillRect(&rc, ::GetSysColorBrush(COLOR_3DFACE));
      short Side = m_pCtx->Side;
      bool bVertical = IsDockedVertically(Side);
      if( m_cxySplitter>0 ) pT->DrawSplitterBar((HDC) dc, bVertical, m_rcSplitter);
      pT->DrawGripperBar((HDC) dc, Side, m_rcGripper, m_rcCloseButton, m_fCloseDown);
      pT->DrawPaneFrame((HDC) dc, Side, rc);
      return 0;
   }

   LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
   {
      POINT ptPos = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
      if( m_fCloseCapture ) {
         // Mouse capture because we're in a close-button loop
         bool fCloseDown = ::PtInRect(&m_rcCloseButton, ptPos) == TRUE;
         if( m_fCloseDown != fCloseDown ) {
            m_fCloseDown = fCloseDown;
            InvalidateRect(&m_rcCloseButton);
         }
      }
      else if( PtInSplitter(ptPos, m_pCtx->Side, m_pCtx->dwFlags, m_rcSplitter) ) {
         bool bVertical = IsDockedVertically(m_pCtx->Side);
         ::SetCursor( bVertical ? s_hVertCursor : s_hHorizCursor);
         bHandled = FALSE;
      }
      return 0;
   }

   LRESULT OnButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      POINT ptPos = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
      if( ::PtInRect(&m_rcCloseButton, ptPos) ) {
         // Clicked on close button? Start a mouse capture look because you
         // can still move the mouse away from the button...
         m_fCloseCapture = m_fCloseDown = true;
         InvalidateRect(&m_rcCloseButton);
         SetCapture();
      }
      else if( PtInSplitter(ptPos, m_pCtx->Side, m_pCtx->dwFlags, m_rcSplitter) ) {
         // Clicked on splitter. Start dragging then...
         ::ClientToScreen(m_hWnd,& ptPos);
         m_ptStartDragPoint = m_ptEndDragPoint = m_ptDeltaDragPoint = ptPos;
         //
         RECT rcWin;
         GetWindowRect(&rcWin);
         m_rcTracker = m_rcSplitter;
         ::OffsetRect(&m_rcTracker, rcWin.left, rcWin.top);
         //
         ::GetWindowRect(::GetParent(m_hWnd),& m_rcTrackerBounds);
         ::InflateRect(&m_rcTrackerBounds, -MIN_DOCKPANE_SIZE, -MIN_DOCKPANE_SIZE);
         // Enter tracking loop
         bool res = Track(false);
         if( res ) {
            if( IsDockedVertically(m_pCtx->Side) ) {
               m_pCtx->rcWindow.bottom += m_ptEndDragPoint.y - m_ptStartDragPoint.y;
            }
            else {
               m_pCtx->rcWindow.right += m_ptEndDragPoint.x - m_ptStartDragPoint.x;
            }
            m_pCtx->bKeepSize = true;
            ::SendMessage(GetParent(), WM_DOCK_UPDATELAYOUT, 0,0);
         }
      }
      else if( ::PtInRect(&m_rcGripper, ptPos) ) {
         // Clicked on gripper? Allow user to move/drag the window out...
         ::ClientToScreen(m_hWnd,& ptPos);
         m_ptStartDragPoint = m_ptEndDragPoint = m_ptDeltaDragPoint = ptPos;
         GetWindowRect(&m_rcTracker);
         // Enter tracking loop
         bool res = Track(true);
         if( res ) {
            // Done dragging! Let's determine where the window went...
            TRACKINFO ti = { m_hWnd, m_pCtx, m_ptEndDragPoint.x, m_ptEndDragPoint.y, m_ptStartDragPoint.x, m_ptStartDragPoint.y };
            ::SendMessage(m_pCtx->hwndRoot, WM_DOCK_QUERYTRACK, 0, (LPARAM)&ti);
            if( ti.Side == m_pCtx->Side ) {
               // Dragged window to same side. Move the window to top position...
               RECT rc;
               GetWindowRect(&rc);
               if( !::PtInRect(&rc, m_ptEndDragPoint) ) ::SendMessage(m_pCtx->hwndRoot, WM_DOCK_REPOSITIONWINDOW, 0, (LPARAM) m_pCtx);
            }
            else {
               // Move the window out in the open or to another pane...
               ::SendMessage(m_pCtx->hwndRoot, WM_DOCK_UNDOCK, 0, (LPARAM) m_pCtx);
               if( ti.Side == DOCK_FLOAT ) m_pCtx->rcWindow = ti.rc;
               ::SendMessage(m_pCtx->hwndRoot, ti.Side == DOCK_FLOAT ? WM_DOCK_FLOAT : WM_DOCK_DOCK, ti.Side, (LPARAM) m_pCtx);
            }
         }
      }
      return 0;
   }

   LRESULT OnButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
   {
      if( m_fCloseCapture ) {
         // We're in a mouse capture loop. That means we're trying to figure
         // out if the close button is being hit...
         m_fCloseCapture = m_fCloseDown = false;
         ::ReleaseCapture();
         InvalidateRect(&m_rcCloseButton);
         POINT ptPos = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
         if( ::PtInRect(&m_rcCloseButton, ptPos) ) {
            ::PostMessage(m_pCtx->hwndRoot, WM_DOCK_CLIENT_CLOSE, WM_DOCK_UNDOCK, (LPARAM) m_pCtx);
         }
      }
      return 0;
   }

   // Track methods

   void OnMove(POINT& pt)
   {
      TRACKINFO ti = { m_hWnd, m_pCtx, pt.x, pt.y, m_ptStartDragPoint.x, m_ptStartDragPoint.y };
      ::SendMessage(m_pCtx->hwndRoot, WM_DOCK_QUERYTRACK, 0, (LPARAM)&ti);
      if( !::EqualRect(&m_rcTracker, &ti.rc) ) {
         DrawDragBar();
         m_rcTracker = ti.rc;
         DrawDragBar();
      }
      m_ptDeltaDragPoint = pt;
   }

   void OnStretch(POINT& pt)
   {
      DrawGhostBar();
      if( IsDockedVertically(m_pCtx->Side) ) {
         int nOffset = pt.y - m_ptDeltaDragPoint.y;
         if( m_rcTracker.top + nOffset <= m_rcTrackerBounds.top ) nOffset = m_rcTrackerBounds.top - m_rcTracker.top;
         if( m_rcTracker.bottom + nOffset >= m_rcTrackerBounds.bottom ) nOffset = m_rcTrackerBounds.bottom - m_rcTracker.bottom;
         ::OffsetRect(&m_rcTracker, 0,nOffset);
         m_ptDeltaDragPoint.y += nOffset;
      }
      else {
         int nOffset = pt.x - m_ptDeltaDragPoint.x;
         if( m_rcTracker.left + nOffset <= m_rcTrackerBounds.left ) nOffset = m_rcTrackerBounds.left - m_rcTracker.left;
         if( m_rcTracker.right + nOffset >= m_rcTrackerBounds.right ) nOffset = m_rcTrackerBounds.right - m_rcTracker.right;
         ::OffsetRect(&m_rcTracker, nOffset,0);
         m_ptDeltaDragPoint.x += nOffset;
      }
      DrawGhostBar();
   }

   void OnEndResize()
   {
      m_ptEndDragPoint = m_ptDeltaDragPoint;
   }

   void OnEndDrag()
   {
      m_ptEndDragPoint = m_ptDeltaDragPoint;
   }

   LRESULT OnSetSplitter(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      m_cxySplitter = wParam;
      return 0;
   }

   // Overridables

   void UpdateLayout()
   {     
      const int CHILD_GAP = 4;
      bool bVertical = IsDockedVertically(m_pCtx->Side);

      // Reposition splitter and gripper bars
      RECT rect;   
      GetClientRect(&rect);
      if( bVertical ) {
         int nGap = 0;
         if( (m_pCtx->dwFlags & DCK_NOHIDE) == 0 ) {
            nGap = CHILD_GAP + m_cxyCloseButton;
            m_rcCloseButton.left = rect.right-nGap;
            m_rcCloseButton.top = rect.top + 2 + (m_cxyGripper - m_cxyCloseButton)/2;
            m_rcCloseButton.right = m_rcCloseButton.left + m_cxyCloseButton;
            m_rcCloseButton.bottom = m_rcCloseButton.top + m_cxyCloseButton;
         }
         ::SetRect(&m_rcGripper, rect.left, rect.top, rect.right-nGap, rect.top + m_cxyGripper);
         ::SetRect(&m_rcSplitter, rect.left, rect.bottom - m_cxySplitter, rect.right, rect.bottom);
         rect.top += m_cxyGripper;
         rect.bottom -= m_cxySplitter;
      }
      else {
         int nGap = 0;
         if( (m_pCtx->dwFlags & DCK_NOHIDE) == 0 ) {
            nGap = CHILD_GAP + m_cxyCloseButton;
            m_rcCloseButton.left = rect.left + 4;
            m_rcCloseButton.top = rect.top + 2 + (m_cxyGripper - m_cxyCloseButton)/2;
            m_rcCloseButton.right = m_rcCloseButton.left + m_cxyCloseButton;
            m_rcCloseButton.bottom = m_rcCloseButton.top + m_cxyCloseButton;
         }
         ::SetRect(&m_rcGripper, rect.left, rect.top+nGap, rect.left + m_cxyGripper, rect.bottom);
         ::SetRect(&m_rcSplitter, rect.right - m_cxySplitter, rect.top, rect.right, rect.bottom);
         rect.left += m_cxyGripper;
         rect.right -= m_cxySplitter;
      }
      // Calculate the client window area
      ::InflateRect(&rect, -CHILD_GAP, -CHILD_GAP);
      m_rcChild = rect;

      ::SetWindowPos(m_pCtx->hwndChild, NULL, m_rcChild.left, m_rcChild.top, m_rcChild.right - m_rcChild.left, m_rcChild.bottom - m_rcChild.top, SWP_NOZORDER | SWP_NOACTIVATE);
   }

   void DrawPaneFrame(CDCHandle /*dc*/, short /*Side*/, const RECT& /*rc*/)
   {
   }

   void DrawGripperBar(CDCHandle dc, short Side, const RECT& rcBar, RECT& rcCloseButton, bool bCloseDown)
   {
      if( ::IsRectEmpty(&rcBar) ) return;
      const int INSET = 4;
      const int LINE_GAP = 4;
      bool bVertical = IsDockedVertically(Side);
      RECT rcLine;
      if( bVertical ) {
         ::SetRect(&rcLine, rcBar.left+INSET, rcBar.top+6, rcBar.right-INSET, rcBar.top+8);
      }
      else {
         ::SetRect(&rcLine, rcBar.left+6, rcBar.top+INSET, rcBar.left+8, rcBar.bottom-INSET);
      }
      dc.Draw3dRect(&rcLine, ::GetSysColor(COLOR_BTNHIGHLIGHT), ::GetSysColor(COLOR_BTNSHADOW));
      ::OffsetRect(&rcLine, bVertical ? 0 : LINE_GAP, bVertical ? LINE_GAP : 0);
      dc.Draw3dRect(&rcLine, ::GetSysColor(COLOR_BTNHIGHLIGHT), ::GetSysColor(COLOR_BTNSHADOW));
      if( !::IsRectEmpty(&rcCloseButton) ) {
         dc.DrawFrameControl(&rcCloseButton, DFC_CAPTION, bCloseDown ? DFCS_CAPTIONCLOSE|DFCS_PUSHED : DFCS_CAPTIONCLOSE);
      }
   }
};

class CDockingPaneChildWindow : public CDockingPaneChildWindowImpl<CDockingPaneChildWindow>
{
public:
   DECLARE_WND_CLASS_EX(_T("WTL_DockingChildWindow"), CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, NULL)

   CDockingPaneChildWindow(DOCKCONTEXT* ctx) : 
      CDockingPaneChildWindowImpl<CDockingPaneChildWindow>(ctx) 
   { 
   }
};


///////////////////////////////////////////////////////
// CDockingPaneWindow

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -