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

📄 atldock.h

📁 BCAM 1394 Driver
💻 H
📖 第 1 页 / 共 4 页
字号:
#ifndef __ATL_DOCK_H__
#define __ATL_DOCK_H__
//
// atldock.h - Docking framework for WTL library
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2000-2001 Bjarke Viksoe.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#pragma once

#ifndef __cplusplus
   #error ATL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
   #error atldock.h requires atlapp.h to be included first
#endif


// Dock positions
#define DOCK_LEFT      0
#define DOCK_TOP       1
#define DOCK_RIGHT     2
#define DOCK_BOTTOM    3
#define DOCK_FLOAT     4
#define DOCK_HIDDEN    5
#define DOCK_LASTKNOWN 6

// Windows flags
#define DCK_NOLEFT      1<<DOCK_LEFT
#define DCK_NOTOP       1<<DOCK_TOP
#define DCK_NORIGHT     1<<DOCK_RIGHT
#define DCK_NOBOTTOM    1<<DOCK_BOTTOM
#define DCK_NOSPLITTER  0x00000100L
#define DCK_NOFLOAT     0x00000200L
#define DCK_NOHIDE      0x00000400L

#define ATL_SIMPLE_DOCKVIEW_STYLE \
   (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)

// Dock child command chaining macro
#define CHAIN_DOCK_CHILD_COMMANDS(hwnd) \
   if(uMsg == WM_COMMAND) \
   { \
      if(::IsWindowVisible(hwnd)) \
         ::SendMessage(hwnd, uMsg, wParam, lParam); \
   }

// Docking position helpers
inline bool IsDockedVertically(short Side) { return (Side==DOCK_LEFT) || (Side==DOCK_RIGHT); };
inline bool IsDocked(short Side) { return (Side==DOCK_TOP) || (Side==DOCK_BOTTOM) || (Side==DOCK_LEFT) || (Side==DOCK_RIGHT); };


#define DOCK_INFO_CHILD 0x1000

#define MIN_DOCKPANE_SIZE 28
#define DEFAULT_DOCKPANE_SIZE 90
#define DEFAULT_FLOAT_SIZE 120
#define DEFAULT_SPLITTER_SIZE 6

#define WM_DOCK_QUERYRECT        WM_USER+840
#define WM_DOCK_QUERYTRACK       WM_USER+841
#define WM_DOCK_UNDOCK           WM_USER+842
#define WM_DOCK_UNFLOAT          WM_USER+843
#define WM_DOCK_DOCK             WM_USER+844
#define WM_DOCK_FLOAT            WM_USER+845
#define WM_DOCK_UPDATELAYOUT     WM_USER+846
#define WM_DOCK_REPOSITIONWINDOW WM_USER+847
#define WM_DOCK_SETSPLITTER      WM_USER+848

class CDockingPaneChildWindow;
class CFloatingWindow;

struct DOCKCONTEXT {
   HWND hwndDocked;  // The docked pane
   HWND hwndFloated; // The floating pane
   HWND hwndChild;   // The view window
   short Side;       // Dock state
   short LastSide;   // Last dock state
   RECT rcWindow;    // Preferred window size
   SIZE sizeFloat;   // Last window size (floating)
   HWND hwndRoot;    // Main dock window
   //
   DWORD dwFlags;    // Extra flags
   bool bKeepSize;   // Recommend using current size and avoid rescale
};

typedef CSimpleValArray<DOCKCONTEXT *> CDockMap;

struct TRACKINFO {
   HWND hWnd;
   DOCKCONTEXT *ctx;
   POINT ptPos;
   POINT ptStart;
   RECT rc;
   short Side;
};


///////////////////////////////////////////////////////
// CSplitterBar

#pragma warning(disable : 4100)

template<class T>
class CSplitterBar
{
public:
   LONG m_cxySplitter;
   bool m_bTracking;
   bool m_bDragging;
   static HCURSOR m_hVertCursor;
   static HCURSOR m_hHorizCursor;

   POINT m_ptStartDragPoint;
   POINT m_ptEndDragPoint;
   POINT m_ptDeltaDragPoint;
   RECT  m_rcTracker;
   SIZE  m_sizeTracker;
   RECT  m_rcTrackerBounds;   
   CDCHandle m_dc;

   CSplitterBar() :
      m_bTracking(false), m_bDragging(false)
   {
      if( m_hVertCursor==NULL ) {
         ::EnterCriticalSection(&_Module.m_csStaticDataInit);
         m_hVertCursor = ::LoadCursor(NULL, IDC_SIZENS);
         m_hHorizCursor = ::LoadCursor(NULL, IDC_SIZEWE);
         ::LeaveCriticalSection(&_Module.m_csStaticDataInit);
      }
      m_sizeTracker.cx = ::GetSystemMetrics(SM_CXFRAME);
      m_sizeTracker.cy = ::GetSystemMetrics(SM_CYFRAME);
      m_cxySplitter = DEFAULT_SPLITTER_SIZE;
   }

   LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
   {
      T* pT = static_cast<T*>(this);
      DWORD dwPos = ::GetMessagePos();
      POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
      pT->ScreenToClient(&ptPos);
      if( ::PtInRect(&pT->m_rcSplitter, ptPos) ) return 1;
      bHandled = FALSE;
      return 0;
   }

   void DrawGhostBar()
   {
      ATLASSERT(!m_dc.IsNull());
      RECT rect = m_rcTracker;
      if( !::IsRectEmpty(&rect) ) {
         // Invert the brush pattern (looks just like frame window sizing)
         CBrush brush = CDCHandle::GetHalftoneBrush();
         if( brush.m_hBrush!=NULL ) {
            ATLASSERT(!m_dc.IsNull());
            CBrushHandle brushOld = m_dc.SelectBrush(brush);
            m_dc.PatBlt(rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, PATINVERT);
            m_dc.SelectBrush(brushOld);
         }
      }
   }

   void DrawDragBar()
   {
      ATLASSERT(!m_dc.IsNull());
      RECT rect = m_rcTracker;
      if( !::IsRectEmpty(&rect) ) {
         // Invert the brush pattern (looks just like frame window sizing)
         CBrush brush = CDCHandle::GetHalftoneBrush();
         if( brush.m_hBrush!=NULL ) {
            ATLASSERT(!m_dc.IsNull());
            CBrushHandle brushOld = m_dc.SelectBrush(brush);
            m_dc.PatBlt(rect.left+m_sizeTracker.cx, rect.top, rect.right-rect.left-(m_sizeTracker.cx*2), m_sizeTracker.cy, PATINVERT);
            m_dc.PatBlt(rect.left, rect.bottom-m_sizeTracker.cy, rect.right-rect.left, m_sizeTracker.cy, PATINVERT);
            m_dc.PatBlt(rect.left, rect.top, m_sizeTracker.cx, rect.bottom-rect.top-m_sizeTracker.cy, PATINVERT);
            m_dc.PatBlt(rect.right-m_sizeTracker.cx, rect.top, m_sizeTracker.cx, rect.bottom-rect.top-m_sizeTracker.cy, PATINVERT);
            m_dc.SelectBrush(brushOld);
         }
      }
   }

   void DrawSplitterBar(CDCHandle dc, bool bVertical, RECT &rect)
   {      
      if( ::IsRectEmpty(&rect) ) return;
      dc.FillRect( &rect, (HBRUSH)LongToPtr(COLOR_3DFACE + 1) );
      dc.DrawEdge( &rect, EDGE_RAISED, (bVertical ? (BF_TOP|BF_BOTTOM) : (BF_LEFT|BF_RIGHT)) );
   }

   bool PtInSplitter(POINT &pt, short Side, DWORD dwFlags, RECT &rcSplitter)
   {
      if( !IsDocked(Side) ) return false;
      if( m_bTracking ) return false;
      if( (dwFlags & DCK_NOSPLITTER)!=0 ) return false;
      if( !::PtInRect(&rcSplitter, pt) ) return false;
      return true;
   }

   // Track loop

   bool Track(bool bDragging)
   {
      T* pT = static_cast<T*>(this);
      StartTracking(bDragging);
      // Get messages until capture lost or cancelled/accepted
      while( ::GetCapture() == pT->m_hWnd ) {
         MSG msg;
         if( !::GetMessage(&msg, NULL, 0, 0) ) {
            ::PostQuitMessage(msg.wParam);
            break;
         }
         switch( msg.message ) {
         case WM_LBUTTONUP:
            if( m_bDragging ) pT->OnEndDrag(); else pT->OnEndResize();
            CancelTracking();
            return true;
         case WM_MOUSEMOVE:
            if( m_bDragging ) pT->OnMove(msg.pt); else pT->OnStretch(msg.pt);
            break;
         case WM_KEYUP:
            if( m_bDragging ) pT->OnKey((int)msg.wParam, false);
            break;
         case WM_KEYDOWN:
            if( m_bDragging ) pT->OnKey((int)msg.wParam, true);
            if( msg.wParam == VK_ESCAPE ) {
               CancelTracking();
               return false;
            }
            break;
         case WM_RBUTTONDOWN:
            CancelTracking();
            return false;      
         default:
            // Just dispatch rest of the messages
            ::DispatchMessage(&msg);
            break;
         }
      }

      CancelTracking();
      return false;
   }

   void StartTracking(bool bDragging)
   {
      ATLASSERT(!m_bTracking);
      T* pT = static_cast<T*>(this);
      // Capture window
      m_bTracking = true;
      pT->SetCapture();
      // Make sure no updates are pending
      pT->RedrawWindow(NULL, NULL, RDW_ALLCHILDREN|RDW_UPDATENOW);
      // Lock Window update while dragging over desktop
      ATLASSERT(m_dc.IsNull());
      HWND hWnd = ::GetDesktopWindow();
      m_dc = ::GetDCEx(hWnd, NULL, ::LockWindowUpdate(hWnd) ? DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE : DCX_WINDOW|DCX_CACHE);
      ATLASSERT(!m_dc.IsNull());
      // Draw the initial focus rect
      m_bDragging = bDragging;
      if( m_bDragging ) DrawDragBar(); else DrawGhostBar();
      return;
   }

   void CancelTracking()
   {
      ATLASSERT(m_bTracking);
      if( !m_bTracking ) return;
      // Erase the focus rect
      if( m_bDragging ) DrawDragBar(); else DrawGhostBar();
      // Let window updates free
      ::LockWindowUpdate(NULL);
      HWND hWnd = ::GetDesktopWindow();
      if( !m_dc.IsNull() ) ::ReleaseDC(hWnd, m_dc.Detach());
      // Release the capture
      ::ReleaseCapture();
      m_bTracking = false;
   }

   // Overridables

   void OnEndDrag() { };
   void OnEndResize() { };
   void OnKey(int nCode, bool bDown) { };
   void OnMove(POINT &pt) { };
   void OnStretch(POINT &pt) { };
};

template<class T> HCURSOR CSplitterBar<T>::m_hVertCursor = NULL;
template<class T> HCURSOR CSplitterBar<T>::m_hHorizCursor = NULL;

#pragma warning(default : 4100)


///////////////////////////////////////////////////////
// CFloatingWindow

typedef CWinTraits<WS_OVERLAPPED|WS_CAPTION|WS_THICKFRAME|WS_SYSMENU, WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE> CFloatWinTraits;



template <class T, class TBase = CWindow, class TWinTraits = CFloatWinTraits>
class ATL_NO_VTABLE CFloatingWindowImpl : 
   public CWindowImpl< T, TBase, TWinTraits >,
   public CSplitterBar<CFloatingWindowImpl< T, TBase, TWinTraits > >
{
public:
   DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, NULL)

   typedef CFloatingWindowImpl< T , TBase, TWinTraits > thisClass;
   BEGIN_MSG_MAP(thisClass)
      MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
      MESSAGE_HANDLER(WM_SIZE, OnSize)
      MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
      MESSAGE_HANDLER(WM_DOCK_UPDATELAYOUT, OnSize)
      MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnLeftButtonDown);
      MESSAGE_HANDLER(WM_NCRBUTTONDOWN, OnRightButtonDown);
      MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnButtonDblClick);
   END_MSG_MAP()

   DOCKCONTEXT *m_ctx;

   CFloatingWindowImpl(DOCKCONTEXT *ctx) :
      m_ctx(ctx)
   { 
   }

   HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
         DWORD dwStyle = 0, DWORD dwExStyle = 0,
         UINT nID = 0, LPVOID lpCreateParam = NULL)
   {
      ATLASSERT(m_ctx);
      if( m_ctx->dwFlags & DCK_NOHIDE ) dwStyle = T::GetWndStyle(dwStyle) & ~WS_SYSMENU;
      return CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
   }

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

   // Message handlers

   LRESULT OnLeftButtonDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
   {
      SetFocus();
      if( wParam==HTCAPTION ) {
         POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
         m_ptStartDragPoint = m_ptEndDragPoint = pt;
         GetWindowRect(&m_rcTracker);
         bool res = Track(true);
         if( res ) {
            TRACKINFO ti = { m_hWnd, m_ctx, m_ptEndDragPoint.x, m_ptEndDragPoint.y, m_ptStartDragPoint.x, m_ptStartDragPoint.y };
            ::SendMessage(m_ctx->hwndRoot, WM_DOCK_QUERYTRACK, 0, (LPARAM)&ti);

⌨️ 快捷键说明

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