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

📄 docktabpane.h

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 H
📖 第 1 页 / 共 2 页
字号:
#ifndef __DOCKTAB_PANE_H__
#define __DOCKTAB_PANE_H__

#ifndef __ATLWIN_H__
	#error DockTabSplitPane.h requires atlwin.h to be included first
#endif

#ifndef __ATLSPLIT_H__
	#error DockTabSplitPane.h requires atlsplit.h to be included first
#endif

#ifndef __ATLCOLL_H__
	#error DockTabSplitPane.h requires atlcoll.h to be included first
#endif

#ifndef __CUSTOMTABCTRL_H__
	#error DockTabSplitPane.h requires CustomTabCtrl.h to be included first
#endif

#ifndef __DOTNET_TABCTRL_H__
	#error DockTabSplitPane.h requires DotNetTabCtrl.h to be included first
#endif

/*********************************************************************
DockSplitTab::TabControl and 
DockSplitTab::TabPane classes implementation

Written by Igor Katrayev.
Copyright (c) 2003 Igor Katrayev.

This code may be used in compiled form in any way you desire. This
file may be redistributed unmodified 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 code is also based of work done by Bjarke Viksoe (bjarke@viksoe.dk)
and Daniel Bowen (dbowen@es.com).

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.
**********************************************************************/

namespace DockSplitTab {
	
	class CallBackListener {
	public:
		
		// client notification
		virtual void clientActivate(  HWND childWnd, HWND clientViewWnd) = 0;
		virtual void clientDblClick(  HWND childWnd, HWND clientViewWnd) = 0;
		virtual void clientCloseClick(     HWND childWnd, HWND clientViewWnd) = 0;
		
		// drag and drop notifications
		virtual void dragStart(  HWND childWnd, HWND clientViewWnd, long x, long y, DWORD keysPressed) = 0;
		virtual void dragOver(   HWND childWnd, HWND clientViewWnd, long x, long y, DWORD keysPressed) = 0;
		virtual void dragDrop(   HWND childWnd, HWND clientViewWnd, long x, long y, DWORD keysPressed) = 0;
		virtual void dragCancel( HWND childWnd, HWND clientViewWnd) = 0;
		
		// 
		void trackDragAndDrop( HWND hWnd, POINT startPoint, bool lockWindowUpdate = false) {
			
			ATLASSERT( NULL != this);
			ATLASSERT( ::IsWindow( hWnd));
			
			if ( !::DragDetect( hWnd, startPoint))
				return;
				
			// tracker drawing conflicts with dock pane drawing
			// disable drawing in the window during drag and drop operations.
			if ( lockWindowUpdate)
				::LockWindowUpdate( hWnd);
			
			MSG msg;
			bool dragging = false;
			::SetCapture( hWnd);
			while( ( ::GetCapture()==hWnd) && ( ::GetMessage( &msg, NULL, 0, 0))) {
				
				CPoint hitPoint = CPoint( GET_X_LPARAM( msg.lParam), GET_Y_LPARAM( msg.lParam));
				::ClientToScreen( hWnd, &hitPoint);
				switch( msg.message) {
				case WM_MOUSEMOVE:
					
					if ( !dragging) {
						
						dragging = true;
						this->dragStart( hWnd, NULL, hitPoint.x, hitPoint.y, static_cast<DWORD>(msg.wParam));
					}
					this->dragOver( hWnd, NULL, hitPoint.x, hitPoint.y, static_cast<DWORD>(msg.wParam));
					break;
					
				case WM_LBUTTONUP:
					
					if ( dragging) {
						dragging = false;
						this->dragDrop( hWnd, NULL, hitPoint.x, hitPoint.y, static_cast<DWORD>(msg.wParam));
					}
					::ReleaseCapture();
					break;
					
				case WM_KEYDOWN:
				case WM_SYSKEYDOWN:
					
					switch ( msg.wParam) {
					case VK_CONTROL:
					case VK_SHIFT:
						break;
					default:
						if ( dragging) {
							dragging = false;
							this->dragCancel( hWnd, NULL);
						}
						::ReleaseCapture();
					}
				default:
					::TranslateMessage(&msg);
					::DispatchMessage( &msg);
				}
			}
			
			// tidy up
			if ( dragging)
				this->dragCancel( hWnd, NULL);
			
			if ( lockWindowUpdate)
				::LockWindowUpdate( NULL);
			return;
		}
		
	}; // interface CallBackListenerr
	
	class TabControlItem: public CCustomTabItem {
	public:
		
		TabControlItem()
			: CCustomTabItem()
			, clientViewWnd( NULL)
		{}
		
		HWND clientViewWnd;
	};
	
	class TabControl: public CDotNetTabCtrlImpl< TabControl, TabControlItem> {
	
	// protected class members
	protected:
		
		typedef CDotNetTabCtrlImpl< TabControl, TabControlItem> baseClass;
		CallBackListener* cbListener;
		int height;
		
	public:
		
		TabControl( CallBackListener* listener)
			: CDotNetTabCtrlImpl<TabControl, TabControlItem>()
			, cbListener( listener)
			, height( 0)
		{}
		
		// Methods
		void create( HWND parentWnd, bool tabOnTop = false) {
			
			
			DWORD style = TCS_FOCUSNEVER | WS_VISIBLE | WS_CHILD;//| TCS_FLATBUTTONS | TCS_BUTTONS
			
			style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CTCS_SCROLL | CTCS_CLOSEBUTTON | CTCS_FLATEDGE | CTCS_BOLDSELECTEDTAB | CTCS_TOOLTIPS;

			if ( !tabOnTop)
				style |= CTCS_BOTTOM;
			
			DWORD exStyle = TCS_EX_REGISTERDROP; //| TCS_EX_FLATSEPARATORS
			this->Create( parentWnd, rcDefault, NULL, style, exStyle);
			this->SetDlgCtrlID(0);
			
			// calculate tab height
			const int nNominalHeight = 24;
			const int nNominalFontLogicalUnits = 11;	// 8 point Tahoma with 96 DPI
			
			// Initialize nFontLogicalUnits to the typical case
			// appropriate for CDotNetTabCtrl
			LOGFONT lfIcon = { 0 };
			::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIcon), &lfIcon, 0);
			int nFontLogicalUnits = -lfIcon.lfHeight;
			
			// Use the actual font of the tab control
			if( this->IsWindow()) {
				
				HFONT hFont = this->GetFont();
				if ( hFont != NULL) {
					
					CDC dc = this->GetDC();
					CFontHandle hFontOld = dc.SelectFont(hFont);
					TEXTMETRIC tm = {0};
					dc.GetTextMetrics(&tm);
					nFontLogicalUnits = tm.tmAscent;
					dc.SelectFont(hFontOld);
				}
			}
			
			this->height = nNominalHeight + ( ::MulDiv(nNominalHeight, nFontLogicalUnits, nNominalFontLogicalUnits) - nNominalHeight ) / 2;
		}
		
		int getHeight() {
			return this->height;
		}
		
		HWND getWND( int index) const {
			
			ATLASSERT( 0 <= index && index < this->GetItemCount());
			
			return this->GetItem( index)->clientViewWnd;
		}
		
		int getIndex( HWND win) const {
			
			for ( int i=0; i<this->GetItemCount(); i++)
				if ( this->GetItem( i)->clientViewWnd == win)
					return i;
			
			return -1;
		}
		
		bool removeTab( HWND clientViewWnd) {
			
			int index = this->getIndex( clientViewWnd);
			if ( index == -1)
				return false;
			
			return this->DeleteItem( index) == TRUE;
		}
		
		bool removeTab( int index) {
			
			ATLASSERT( 0 <= index && index < this->GetItemCount());
			
			return this->DeleteItem( index) == TRUE;
		}
		
		int getCurrentTab() const {
			
			return this->GetCurSel();
		}
		
		int setCurrentTab( int index) {
			
			ATLASSERT( 0 <= index && index < this->GetItemCount());
			
			int result = this->SetCurSel( index);
			if ( result > -1 && index != result)
				::ShowWindow( this->getWND( result), FALSE);
			return result;
		}
		
		// Message map handlers
		DECLARE_WND_CLASS(_T("DockTab::TabControl"))  
		
		BEGIN_MSG_MAP( TabControl)
			
			MESSAGE_HANDLER( WM_CREATE,        OnCreate)
			MESSAGE_HANDLER( WM_CONTEXTMENU,   OnContextMenu)
			MESSAGE_HANDLER( WM_LBUTTONDOWN,   OnLButtonDown)
//			MESSAGE_HANDLER( WM_LBUTTONDBLCLK, OnLDoubleClick)
			MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate)
//			MESSAGE_HANDLER( WM_MOUSEMOVE,     OnMouseMove)
			
			CHAIN_MSG_MAP( baseClass)
		END_MSG_MAP()
		
		LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
			
			LRESULT result;
			baseClass::ProcessWindowMessage( this->m_hWnd, uMsg, wParam, lParam, result);
			if ( MA_ACTIVATE == result || MA_ACTIVATEANDEAT == result)
				this->SetFocus();
			return result;
		}
		
		LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
			
			CPoint hitPoint( GET_X_LPARAM( lParam), GET_Y_LPARAM( lParam));
			this->ScreenToClient( &hitPoint);
			CTCHITTESTINFO hci;
			hci.pt.x = hitPoint.x;
			hci.pt.y = hitPoint.y;
			hci.flags = TCHT_ONITEM;
			int tabItemTarget = this->HitTest( &hci);
			if ( tabItemTarget > -1) {
				
				this->SetCurSel( tabItemTarget);
				::SendMessage( this->getWND( tabItemTarget)
							, WM_CONTEXTMENU
							, wParam
							, lParam
							);
			}
			return 0;
		}
		
		LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
			
			// process with the default handler. select a 駂osen item
			LRESULT result;
			baseClass::ProcessWindowMessage( this->m_hWnd, uMsg, wParam, lParam, result);
			
			//CRect clientRect;
			//this->GetClientRect( clientRect);
			//CRect closeButtonRect = clientRect;
			//CRect scrollButtonRect = clientRect;
			//CRect nonClientRect = clientRect;
			//this->CalcSize_CloseButton( closeButtonRect);
			//this->CalcSize_ScrollButtons( scrollButtonRect);
			//this->CalcSize_NonClient( nonClientRect);
			
			CRect itemRect;
			int tabItem = this->GetCurSel();
			CPoint startHitPoint( GET_X_LPARAM( lParam), GET_Y_LPARAM( lParam));
			
			if (    tabItem < 0
				 //|| closeButtonRect.PtInRect( startHitPoint)  /***** ti does not work unfortunately*****/
				 //|| scrollButtonRect.PtInRect( startHitPoint)
				 //|| nonClientRect.PtInRect( startHitPoint)
			     || !this->GetItemRect( tabItem, itemRect)
				 || !itemRect.PtInRect( startHitPoint)
			     || !::DragDetect( this->m_hWnd, startHitPoint)
			   )
				return result;
			
			HCURSOR cursorSizeWE = LoadCursor( NULL, IDC_SIZEWE);
			HCURSOR oldCursor = ::GetCursor();
			
			// do drag and drop
			
			::SetCapture( this->m_hWnd);
			HWND clientViewWnd = this->getWND( tabItem);
			
			bool globalDrag = false;
			MSG msg;
			while( ( ::GetCapture()==this->m_hWnd) && ( ::GetMessage( &msg, NULL, 0, 0))) {
				
				CTCHITTESTINFO hci;
				int tabItemTarget;
				
				switch(msg.message) {
				case WM_MOUSEMOVE:
				{
					CPoint hitPoint( GET_X_LPARAM( msg.lParam), GET_Y_LPARAM( msg.lParam));
					hci.pt.x = hitPoint.x;
					hci.pt.y = hitPoint.y;
					hci.flags = TCHT_ONITEM;
					tabItemTarget = this->HitTest( &hci);
					
					::SetCursor( ( tabItemTarget == tabItem && startHitPoint != hitPoint)? cursorSizeWE: oldCursor);
					
					if ( tabItemTarget > -1 && tabItemTarget != tabItem) {
						
						// tab shifting
						if ( globalDrag) {
							globalDrag = false;
							this->cbListener->dragCancel( this->m_hWnd, clientViewWnd);
						}
						
						if ( tabItemTarget < tabItem) {
							
							// shift the tab left
							for ( int i=tabItem; i > tabItemTarget; i--)
								this->SwapItemPositions( i-1, i);
							
						} else if ( tabItem < tabItemTarget) {
							// shift the tab right
							for ( int i=tabItem; i < tabItemTarget; i++)
								this->SwapItemPositions( i, i+1);
						}
						this->SetCurSel( tabItemTarget);
						tabItem = tabItemTarget;
					} else if ( tabItemTarget == -1) {
						
						// handle drag moving
						CPoint point( GET_X_LPARAM( msg.lParam), GET_Y_LPARAM( msg.lParam));
						this->ClientToScreen( &point);
						if ( !globalDrag) {
							
							globalDrag = true;
							if ( NULL != this->cbListener)
								this->cbListener->dragStart( this->m_hWnd, clientViewWnd, point.x, point.y, static_cast<DWORD>(msg.wParam));
						}
						if ( NULL != this->cbListener)
							this->cbListener->dragOver( this->m_hWnd, clientViewWnd, point.x, point.y, static_cast<DWORD>(msg.wParam));
					}
					startHitPoint = hitPoint;
					break;
				}
				case WM_RBUTTONUP:
				case WM_LBUTTONUP:
				{
					::ReleaseCapture();
					if ( NULL != this->cbListener && globalDrag) {
						
						CPoint point( GET_X_LPARAM( msg.lParam), GET_Y_LPARAM( msg.lParam));
						this->ClientToScreen( &point);
						this->cbListener->dragDrop( this->m_hWnd, clientViewWnd, point.x, point.y, static_cast<DWORD>(msg.wParam));
						globalDrag = false;
					}
					break;
				}	
				case WM_KEYDOWN:
					if( msg.wParam != VK_ESCAPE)
						break;
				case WM_SYSKEYDOWN:
					::ReleaseCapture();
					if ( NULL != this->cbListener && globalDrag) {
						
						this->cbListener->dragCancel( this->m_hWnd, clientViewWnd);
						globalDrag = false;
					}
				case WM_CAPTURECHANGED:
					result = 0;
					break;
				default:
					::TranslateMessage(&msg);
					::DispatchMessage( &msg);
				}
			}
			::SetCursor( oldCursor);
			::DestroyCursor( cursorSizeWE);
			return result;
		}
		
		LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
			
			return this->DefWindowProc( uMsg, wParam, lParam);
		}
		
		LRESULT OnEraseBackground( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
			return 1;
		}
		
	};
	
	class ClientProperties {
	public:
		
		CString caption;
		CString toolTip;
		int     imageIndex;
	};
	
	// class Pane
	class Pane
		: public CWindowImpl<Pane, CWindow>
		, public CallBackListener
	{
	
	//----------------- protected members
	protected:
		
		TabControl tabs;
		CallBackListener* cbListener;
		bool isTabsOnTop;
		
	//----------------- protected interface
	protected:
		
		int insertTab( int index, const TCHAR* caption, HWND clientViewWnd, const TCHAR* toolTip = NULL, int imageIndex = -1) {
			
			ATLASSERT( ::IsWindow( clientViewWnd));
			
			::SetParent( clientViewWnd, this->m_hWnd);
			TabControlItem* item = this->tabs.CreateNewItem();
			item->clientViewWnd = clientViewWnd;
			item->SetText( caption);
			item->SetToolTip( toolTip);
			item->SetImageIndex( imageIndex);
			return this->tabs.InsertItem( index, item, true);
		}
		
		int getCurrentTab() const {
			
			return this->tabs.getCurrentTab();
		}
		
		int setCurrentTab( int index) {
			
			return this->tabs.setCurrentTab( index);
		}
		

⌨️ 快捷键说明

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