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

📄 docktabsplitpane.h

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 H
📖 第 1 页 / 共 3 页
字号:
						
						parentVerSplitter->SetSplitterPane( SPLIT_PANE_RIGHT, newSplitterWnd, false);
						parentVerSplitter->GetSplitterPaneRect( SPLIT_PANE_RIGHT, &newSplitterRect);
					}
					
				} else if ( NULL != ( horSplitPair = this->horSplitterMap.Lookup( targetPaneParent))) {
					
					// it is a horizontal splitter
					parentHorSplitter = horSplitPair->m_value;
					if ( parentHorSplitter->GetSplitterPane( SPLIT_PANE_LEFT) == targetPane->m_hWnd) {
						
						parentHorSplitter->SetSplitterPane( SPLIT_PANE_LEFT, newSplitterWnd, false);
						parentHorSplitter->GetSplitterPaneRect( SPLIT_PANE_LEFT, &newSplitterRect);
						
					} else if ( parentHorSplitter->GetSplitterPane( SPLIT_PANE_RIGHT) == targetPane->m_hWnd) {
						
						parentHorSplitter->SetSplitterPane( SPLIT_PANE_RIGHT, newSplitterWnd, false);
						parentHorSplitter->GetSplitterPaneRect( SPLIT_PANE_RIGHT, &newSplitterRect);
					}
					
				}
			}
			
			::SetWindowPos( newSplitterWnd, HWND_TOP, newSplitterRect.left, newSplitterRect.top, newSplitterRect.Width(), newSplitterRect.Height(), SWP_HIDEWINDOW);
			
			// set panes for the new splitter
			if ( isVertical) {
				
				int newPaneID;
				int targetPaneID;
				verSplitter->SetSplitterPos( -1, false);
				if ( where == Pane::TabPaneHitTest_Left) {
					
					targetPaneID = SPLIT_PANE_RIGHT;
					newPaneID    = SPLIT_PANE_LEFT;
					verSplitter->SetSplitterPanes( newPane->m_hWnd, targetPane->m_hWnd, false);
				} else {
					
					targetPaneID = SPLIT_PANE_LEFT;
					newPaneID    = SPLIT_PANE_RIGHT;
					verSplitter->SetSplitterPanes( targetPane->m_hWnd, newPane->m_hWnd, false);
				}
				verSplitter->GetSplitterPaneRect( targetPaneID, &targetPaneRect);
				verSplitter->GetSplitterPaneRect( newPaneID,    &newPaneRect);
				
			} else {
				
				int newPaneID;
				int targetPaneID;
				horSplitter->SetSplitterPos(-1, false);
				if ( where == Pane::TabPaneHitTest_Top) {
					
					targetPaneID = SPLIT_PANE_RIGHT;
					newPaneID    = SPLIT_PANE_LEFT;
					horSplitter->SetSplitterPanes( newPane->m_hWnd, targetPane->m_hWnd, false);
				} else {
					
					targetPaneID = SPLIT_PANE_LEFT;
					newPaneID    = SPLIT_PANE_RIGHT;
					horSplitter->SetSplitterPanes( targetPane->m_hWnd, newPane->m_hWnd, false);
				}
				horSplitter->GetSplitterPaneRect( targetPaneID, &targetPaneRect);
				horSplitter->GetSplitterPaneRect( newPaneID,    &newPaneRect);
			}
			
			// get the new splitter visible
			::SetWindowPos( newSplitterWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER);
			
			// Set new window position for the new pane, the target pane and the new splitter window
			newPane->SetWindowPos( HWND_TOP, newPaneRect.left, newPaneRect.top, newPaneRect.Width(), newPaneRect.Height(), SWP_SHOWWINDOW);
			targetPane->SetWindowPos( HWND_TOP, targetPaneRect.left, targetPaneRect.top, targetPaneRect.Width(), targetPaneRect.Height(), SWP_SHOWWINDOW);
			
			// Set focus to the new pane
			newPane->SetFocus();
			this->currentPane = newPane;
			
			// if there is no tab left in the source pane it needs to be destroyed
			HWND sourcePaneParentWnd = sourcePane->GetParent();
			if ( sourcePane->isEmpty() && sourcePaneParentWnd != this->m_hWnd) {
				
				// important:
				// destroy the source pane via the message queue becouse this call maybe done by a tab control
				// belonging to the source pane. we don't want to destroy it before it ends.
				this->PostMessage( WM_USER_DESTROY_PANE, 0, (LPARAM) sourcePane->m_hWnd);
			}
		} // splitWithCurrentTab( Pane* sourcePane, Pane* targetPane, Pane::TabPaneHitTest where)
		

		HSplitter* lookUpHSplitter( HWND splitterWnd) {
			
			CAtlMap< HWND, HSplitter*>::CPair* splitterPair = this->horSplitterMap.Lookup( splitterWnd);
			if ( NULL == splitterPair)
				return NULL;
			
			return splitterPair->m_value;
		} // HSplitter* lookUpHSplitter( HWND splitterWnd)
		
		VSplitter* lookUpVSplitter( HWND splitterWnd) {
			
			CAtlMap< HWND, VSplitter*>::CPair* splitterPair = this->verSplitterMap.Lookup( splitterWnd);
			if ( NULL == splitterPair)
				return NULL;
			
			return splitterPair->m_value;
		} // HSplitter* lookUpHSplitter( HWND splitterWnd)
		
		
		Pane* lookUpPane( HWND clientViewWnd) {
			
			CAtlMap< HWND, Pane*>::CPair* clientPanePair = this->clientViewPaneMap.Lookup( clientViewWnd);
			if ( NULL == clientPanePair)
				return NULL;
			
			return clientPanePair->m_value;
		} // Pane* lookUpPane( HWND clientViewWnd)
		
		Pane* lookUpPaneWnd( HWND paneWnd) {
			
			CAtlMap< HWND, Pane*>::CPair* clientPanePair = this->paneMap.Lookup( paneWnd);
			if ( NULL == clientPanePair)
				return NULL;
			
			return clientPanePair->m_value;
		} // Pane* lookUpPaneWnd( HWND paneWnd)
		
		Pane* getNextPane( HWND hWnd) {
			
			Pane* result = this->lookUpPaneWnd( hWnd);
			
			// check if hwnd is a Pane
			if ( NULL != result)
				return result;
			
			HWND splitter[2];
			memset( splitter, 0, sizeof(splitter));
			
			HWND childWnd = ::GetWindow( hWnd, GW_CHILD);
			int i = 0;
			while ( NULL != childWnd) {
				
				if ( NULL != ( result = this->lookUpPaneWnd( childWnd)))
					break;
				
				// TODO need to keep a beakpoint for debugging more time
				if ( NULL != this->lookUpHSplitter( childWnd) || NULL != this->lookUpHSplitter( childWnd))
					// dangerous code, but we know that there are no more than two splitters ;)
					splitter[i++] = childWnd;
				
				childWnd = ::GetWindow( hWnd, GW_HWNDNEXT);
			}
			
			if ( NULL == result) {
				
				if ( NULL != splitter[0])
					result = getNextPane( ::GetWindow( splitter[0], GW_CHILD));
				else if ( NULL != splitter[1])
					result = getNextPane( ::GetWindow( splitter[1], GW_CHILD));
			}
			
			return result;
		}
		
		bool setCurrentPane( HWND paneWnd) {
			
			Pane* pane = this->lookUpPaneWnd( paneWnd);
			if ( NULL != pane) {
				
				this->currentPane = pane;
				return true;
			} else
				return false;
		}
		
		void removeAll() {
			
			if ( NULL != this->dragContext)
				delete dragContext;
			
			POSITION position;
			if ( position = this->paneMap.GetStartPosition())
				do
					delete this->paneMap.GetNextValue( position);
				while ( position);
			this->paneMap.RemoveAll();
			
			if ( position = this->verSplitterMap.GetStartPosition())
				do
					delete this->verSplitterMap.GetNextValue( position);
				while ( position);
			this->verSplitterMap.RemoveAll();
			
			if ( position = this->horSplitterMap.GetStartPosition())
				do
					delete this->horSplitterMap.GetNextValue( position);
				while ( position);
			this->horSplitterMap.RemoveAll();
		}
		
		void updateLayout() {
			
			if ( NULL == this->rootWnd)
				return;
			
			CRect rect;
			this->GetClientRect( rect);
			::SetWindowPos( this->rootWnd, HWND_TOP, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW);
			return;
		}
		
	//----------------- public interface
	public:
		
		// Constructor/Destructor
		SplitPane( CallBackListener* cbListener = NULL, bool tabOnTop = false)
			: currentPane( NULL)
			, rootWnd( NULL)
			, dragContext( NULL)
			, cbListener( cbListener)
			, tabOnTop( tabOnTop)
		{}
		
		~SplitPane() {
			
			this->removeAll();
			
			if ( NULL != this->m_hWnd)
				this->DestroyWindow();
		}

		
		// CallBackListener interface
		void clientActivate(  HWND childWnd, HWND clientViewWnd) {
			
			this->setCurrentPane( childWnd);
			if ( NULL != this->cbListener)
				this->cbListener->clientActivate( this->m_hWnd, clientViewWnd);
			return;
		}
		
		void clientDblClick(  HWND childWnd, HWND clientViewWnd) {
			
			if ( NULL != this->cbListener)
				this->cbListener->clientDblClick( this->m_hWnd, clientViewWnd);
			return;
		}
		
		void clientCloseClick(  HWND childWnd, HWND clientViewWnd) {
			
			if ( NULL != this->cbListener)
				this->cbListener->clientCloseClick( this->m_hWnd, clientViewWnd);
			return;
		}
		
		void dragStart( HWND srcPane, HWND clientViewWnd, long x, long y, DWORD keysPressed) {
			
			ATLASSERT( NULL == this->dragContext);
			this->dragContext = new DragContext();
		}
		
		void dragOver( HWND srcPane, HWND clientViewWnd, long x, long y, DWORD keysPressed) {
			
			ATLASSERT( NULL != this->dragContext);
			
			Pane* targetPane = this->getPane( x, y);
			if ( NULL != targetPane) {
				
				CPoint hitPoint( x, y);
				this->dragContext->tabPaneHitTest = targetPane->hitTest( &hitPoint);
				if ( this->dragContext->tabPaneHitTest != Pane::TabPaneHitTest_Unknown) {
					
					// determine a source pane
					CAtlMap< HWND, Pane*>::CPair* sourcePanePair = this->paneMap.Lookup( srcPane);
					if ( NULL != sourcePanePair) {
						
						Pane* sourcePane;
						sourcePane = sourcePanePair->m_value;
						
						if ( sourcePane != targetPane || sourcePane->clientCount() > 1) {
							
							// draw hit area only if there is more than one tab in the source tab
							// or if the target pane is not the same as the source tab.
							CRect rect;
							targetPane->getTabPageRect( &rect);
							
							switch ( this->dragContext->tabPaneHitTest) {
							case Pane::TabPaneHitTest_Top:    rect.bottom /= 2;           break;
							case Pane::TabPaneHitTest_Right:  rect.left = rect.right / 2; break;
							case Pane::TabPaneHitTest_Left:   rect.right /= 2;            break;
							case Pane::TabPaneHitTest_Bottom: rect.top = rect.bottom / 2; break;
							}
							
							// Draw a track rectangle
							this->dragContext->drawTrackRectangle( targetPane->m_hWnd, &rect);
						}
					}
				}
			} else
				this->dragContext->clearTrackRectangle();
		}
		
		void dragDrop( HWND srcPane, HWND clientViewWnd, long x, long y, DWORD keysPressed) {
			
			ATLASSERT( NULL != this->dragContext);
			
			Pane* sourcePane;
			Pane* targetPane;
			this->dragContext->clearTrackRectangle();
			
			switch( this->dragContext->tabPaneHitTest) {
			case Pane::TabPaneHitTest_Unknown:
				
				break;
				
			case Pane::TabPaneHitTest_TabArea:
				
				targetPane = this->getPane( x, y);
				sourcePane = this->paneMap.Lookup( srcPane)->m_value;
				if ( NULL != targetPane && NULL != sourcePane && targetPane != sourcePane)
					this->moveCurrentTab( sourcePane, targetPane);
				break;
				
			default:
				
				targetPane = this->getPane( x, y);
				sourcePane = this->paneMap.Lookup( srcPane)->m_value;
				if ( NULL != targetPane && NULL != sourcePane)
					this->splitWithCurrentTab( sourcePane, targetPane, this->dragContext->tabPaneHitTest);
			}
			
			// Remove drag context
			delete this->dragContext;
			this->dragContext = NULL;
		}
		
		void dragCancel( HWND srcPane, HWND clientViewWnd) {
			
			ATLASSERT( NULL != this->dragContext);
			
			delete this->dragContext;
			this->dragContext = NULL;
		}
		
		// public methods
		enum TargetArea {
			  targetLeft
			, targetTop
			, targetRight
			, targetBottom
		};
		
		void splitClientView( HWND sourceWnd, HWND targetWnd, TargetArea targetArea) {
			
			ATLASSERT( ::IsWindow( sourceWnd));
			ATLASSERT( ::IsWindow( targetWnd));
			
			Pane* sourcePane = this->lookUpPane( sourceWnd);
			Pane* targetPane = this->lookUpPane( targetWnd);
			
			ATLASSERT( NULL != sourcePane);
			ATLASSERT( NULL != targetPane);
			
			Pane::TabPaneHitTest tabPaneHitTest;
			switch ( targetArea) {
			case targetLeft:   tabPaneHitTest = Pane::TabPaneHitTest_Left;   break;
			case targetTop:    tabPaneHitTest = Pane::TabPaneHitTest_Top;    break;
			case targetRight:  tabPaneHitTest = Pane::TabPaneHitTest_Right;  break;
			case targetBottom: tabPaneHitTest = Pane::TabPaneHitTest_Bottom; break;
			default:
				ATLASSERT( FALSE);
			}
			
			this->setFocusTo( sourceWnd);
			this->splitWithCurrentTab( sourcePane, targetPane, tabPaneHitTest);

⌨️ 快捷键说明

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