Re: Explorer Style
Al wrote:
Thanks for all the help and the sample code. Sample code helps me to
understand what is going on. Thanks again, its time to experiment!
Here, this may save you some time. It is a splitter that can be created
independently of the frame. Just ditch the AfxSaveWinPos and
AfxGetWinPos stuff and I think it should pretty much work.
..h
#pragma once
// ............................................................
class CSplitterView : public CView
{
protected:
friend CSplitterView* CreateSplitter( CWnd*, long, long, CDocument*,
LPCTSTR );
CSplitterView( );
DECLARE_DYNCREATE( CSplitterView )
// the splitter window
CSplitterWnd splitter;
// The splitter name is optional
CString strSplitterName;
// keep pane pos from 'MoveFrameView
long rowMoveFrameView;
long colMoveFrameView;
bool Create( CFrameWnd* pFrame, long row, long col, LPCTSTR inName= NULL )
{
SetName( inName );
return !!splitter.CreateStatic( pFrame, row, col );
}
void SetName( LPCTSTR inName ) { strSplitterName= inName; }
protected:
//Used to see if all views have been created and set windows pos
void CheckAndSetPos( );
//Used on destruction to restore origanal view to frame.
CView* RestoreFrameView( );
public:
CView* MoveFrameView( long row, long col );
CView* CreateView( long row, long col, CRuntimeClass* rtView,
CDocument* pDoc= NULL );
CSplitterWnd* GetSplitterWnd( ) { return &splitter; }
public:
//virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
CCreateContext* pContext = NULL);
virtual void OnInitialUpdate( );
virtual BOOL DestroyWindow ( );
protected:
virtual ~CSplitterView( );
virtual void OnDraw( CDC* /*pDC*/ ) { } // overridden to draw this
view
#ifdef _DEBUG
virtual void AssertValid( ) const;
virtual void Dump( CDumpContext& dc ) const;
#endif
protected:
DECLARE_MESSAGE_MAP( )
//afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
afx_msg void OnSize( UINT nType, int cx, int cy );
afx_msg void OnDestroy( );
};
CSplitterView* CreateSplitter( CWnd* pFrame, long rows, long cols,
LPCTSTR inName= NULL );
..cpp
#include "stdafx.h"
#include <afxpriv.h>
#include ".\splitvw.h"
// ...................................................................
CSplitterView* CreateSplitter( CWnd* pWnd, long rows, long cols,
CDocument* pDoc, LPCTSTR inName )
{
CFrameWnd* pFrame= DYNAMIC_DOWNCAST( CFrameWnd, pWnd );
ASSERT( pFrame );
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS( CSplitterView );
context.m_pCurrentDoc = pDoc;
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = NULL;
CSplitterView* pView= DYNAMIC_DOWNCAST( CSplitterView,
pFrame->CreateView( &context ) );
ASSERT( pView );
//Now create the CSplitterWnd window
pView->Create( pFrame, rows, cols, inName );
return pView;
}
// ...................................................................
IMPLEMENT_DYNCREATE(CSplitterView, CView)
BEGIN_MESSAGE_MAP( CSplitterView, CView )
//ON_WM_CREATE( )
ON_WM_SIZE( )
ON_WM_DESTROY( )
END_MESSAGE_MAP( )
CSplitterView::CSplitterView( )
:rowMoveFrameView( -1 )
,colMoveFrameView( -1 )
{
}
CSplitterView::~CSplitterView( )
{
}
void CSplitterView::OnDestroy( )
{
if( ! strSplitterName.IsEmpty( ) )
AfxSaveWinPos( &splitter );
splitter.DestroyWindow( );
CView::OnDestroy( );
}
BOOL CSplitterView::DestroyWindow( )
{
CView* pView= NULL;
if( rowMoveFrameView != -1 && colMoveFrameView != -1 )
{
// This view doesn't belong to us
pView= RestoreFrameView( );
SetParent( NULL );
}
if( ! CView::DestroyWindow( ) )
return FALSE;
if( pView )
{
AfxSaveWinPos( pView );
pView->GetParentFrame( )->RecalcLayout( );
}
return TRUE;
}
CView* CSplitterView::CreateView( long row, long col, CRuntimeClass*
rtView, CDocument* pDoc )
{
ASSERT( splitter.GetSafeHwnd( ) ); //use CSplitterView::Create and set
row, col.
CCreateContext context;
context.m_pNewViewClass = rtView;
context.m_pCurrentDoc = pDoc;
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = NULL;
if( ! splitter.CreateView( row, col, rtView, CSize( 0 ), &context ) )
return NULL;
CWnd* pWnd= splitter.GetDlgItem( splitter.IdFromRowCol( row, col ) );
CView* pView= DYNAMIC_DOWNCAST( CView, pWnd );
ASSERT_VALID( pView );
pView->SendMessage( WM_INITIALUPDATE );
CheckAndSetPos( );
return pView;
}
CView* CSplitterView::MoveFrameView( long row, long col )
{
CFrameWnd* pFrame= DYNAMIC_DOWNCAST( CFrameWnd, GetParent( ) );
ASSERT( pFrame );
CView* pView= pFrame->GetActiveView( );
ASSERT( pView );
//Won't hurt if window pos was never initialized.
AfxSaveWinPos( pView );
pView->SetParent( &splitter );
pFrame->SetActiveView( this );
pView->SetDlgCtrlID( splitter.IdFromRowCol( row, col ) );
CheckAndSetPos( );
rowMoveFrameView= row;
colMoveFrameView= col;
return pView;
}
CView* CSplitterView::RestoreFrameView( )
{
if( rowMoveFrameView == -1 || colMoveFrameView == -1 )
return NULL;
CWnd* pWnd= splitter.GetPane( rowMoveFrameView, colMoveFrameView );
CView* pView= DYNAMIC_DOWNCAST( CView, pWnd );
ASSERT_VALID( pView );
pView->SetParent( GetParentFrame( ) );
GetParentFrame( )->SetActiveView( pView );
return pView;
}
void CSplitterView::CheckAndSetPos( )
{
if( strSplitterName.IsEmpty( ) )
return;
bool bAll= true;
for( long i= 0; i < splitter.GetRowCount( ); ++i )
for( long j= 0; j < splitter.GetColumnCount( ); ++j )
{
CWnd* pWnd= splitter.GetDlgItem( splitter.IdFromRowCol( i, j ) );
if( ! pWnd )
{
bAll= false;
break;
}
}
if( bAll )
{
AfxGetWinPos( strSplitterName, &splitter );
splitter.RecalcLayout( );
}
}
void CSplitterView::OnSize( UINT nType, int cx, int cy )
{
//for now.....
if( ! GetSafeHwnd( ) || ! splitter.GetSafeHwnd( ) )
return;
splitter.MoveWindow( 0, 0, cx, cy );
////We just want to set the X column upon creation of the view. This
way the user can
////move the splitter bar to how they like it and still resize the
frame window
////without it snapping back:
//if(m_bShouldSetXColumn)
// m_wndSplitter.SetColumnInfo(0, cx/3, 0);
splitter.RecalcLayout( );
}
void CSplitterView::OnInitialUpdate( )
{
TRACE("in CSplitterView::OnInitialUpdate()\n");
}
// ..........
#ifdef _DEBUG
void CSplitterView::AssertValid( ) const
{
CView::AssertValid( );
}
void CSplitterView::Dump( CDumpContext& dc ) const
{
CView::Dump( dc );
}
#endif //_DEBUG