517 lines
13 KiB
C++
517 lines
13 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
FTMan
|
||
|
|
||
|
File Name:
|
||
|
|
||
|
MainFrm.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementation of the CMainFrame class. It is the MFC main frame class for this application
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Cristian Teodorescu October 20, 1998
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include "Item.h"
|
||
|
#include "FTListVw.h"
|
||
|
#include "FTTreeVw.h"
|
||
|
#include "MainFrm.h"
|
||
|
#include "Resource.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
// Range limits for OnViewStyle and OnUpdateViewStyle
|
||
|
#define AFX_ID_VIEW_MINIMUM ID_VIEW_SMALLICON
|
||
|
#define AFX_ID_VIEW_MAXIMUM ID_VIEW_BYNAME
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMainFrame
|
||
|
|
||
|
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
|
||
|
//{{AFX_MSG_MAP(CMainFrame)
|
||
|
ON_WM_CREATE()
|
||
|
ON_COMMAND(ID_VIEW_TOGGLE, OnViewToggle)
|
||
|
ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh)
|
||
|
ON_WM_ACTIVATEAPP()
|
||
|
ON_WM_DESTROY()
|
||
|
ON_WM_TIMER()
|
||
|
//}}AFX_MSG_MAP
|
||
|
ON_UPDATE_COMMAND_UI_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnUpdateViewStyles)
|
||
|
ON_COMMAND_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnViewStyle)
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
static UINT indicators[] =
|
||
|
{
|
||
|
ID_INDICATOR_NAME, // Name of the tree selected item
|
||
|
ID_INDICATOR_TYPE, // Type of the tree selected item
|
||
|
ID_INDICATOR_DISKS, // Disks set of the tree selected item
|
||
|
ID_INDICATOR_SIZE, // Size of the tree selected item
|
||
|
ID_INDICATOR_NOTHING, // Just an empty indicator to let some space between the first 4 indicators and the last one
|
||
|
ID_SEPARATOR, // status line indicator
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMainFrame construction/destruction
|
||
|
|
||
|
CMainFrame::CMainFrame() : m_bEnableAutoRefresh(FALSE), m_bAutoRefreshRequested(FALSE), m_unTimer(0)
|
||
|
{
|
||
|
// TODO: add member initialization code here
|
||
|
|
||
|
}
|
||
|
|
||
|
CMainFrame::~CMainFrame()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||
|
{
|
||
|
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
|
||
|
return -1;
|
||
|
|
||
|
/*
|
||
|
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
|
||
|
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
|
||
|
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
|
||
|
*/
|
||
|
if (!m_wndToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP
|
||
|
| CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
|
||
|
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
|
||
|
{
|
||
|
TRACE0(_T("Failed to create toolbar\n"));
|
||
|
return -1; // fail to create
|
||
|
}
|
||
|
m_wndToolBar.GetToolBarCtrl().ModifyStyle( 0, TBSTYLE_FLAT );
|
||
|
|
||
|
if (!m_wndStatusBar.Create(this) ||
|
||
|
!m_wndStatusBar.SetIndicators(indicators,
|
||
|
sizeof(indicators)/sizeof(UINT)))
|
||
|
{
|
||
|
TRACE0(_T("Failed to create status bar\n"));
|
||
|
return -1; // fail to create
|
||
|
}
|
||
|
// Try to compute the optimal size for the status bar indicators ( depending on the application font )
|
||
|
|
||
|
int nAveCharWidth = 0;
|
||
|
CDC* pDC = m_wndStatusBar.GetDC();
|
||
|
if( pDC )
|
||
|
{
|
||
|
TEXTMETRIC textmetrics;
|
||
|
if( pDC->GetTextMetrics(&textmetrics) )
|
||
|
nAveCharWidth = textmetrics.tmAveCharWidth;
|
||
|
m_wndStatusBar.ReleaseDC( pDC );
|
||
|
}
|
||
|
|
||
|
m_wndStatusBar.SetPaneInfo( 0, m_wndStatusBar.GetItemID(0), 0, nAveCharWidth ? (16 * nAveCharWidth) : 130 );
|
||
|
m_wndStatusBar.SetPaneInfo( 1, m_wndStatusBar.GetItemID(1), 0, nAveCharWidth ? (22 * nAveCharWidth) : 150 );
|
||
|
m_wndStatusBar.SetPaneInfo( 2, m_wndStatusBar.GetItemID(2), 0, nAveCharWidth ? (8 * nAveCharWidth) : 50 );
|
||
|
m_wndStatusBar.SetPaneInfo( 3, m_wndStatusBar.GetItemID(3), 0, nAveCharWidth ? (8 * nAveCharWidth) : 60 );
|
||
|
m_wndStatusBar.SetPaneInfo( 4, m_wndStatusBar.GetItemID(4), SBPS_NOBORDERS, nAveCharWidth ? (2 * nAveCharWidth) : 15 );
|
||
|
m_wndStatusBar.SetPaneStyle( 5, SBPS_NOBORDERS | SBPS_STRETCH );
|
||
|
|
||
|
// TODO: Delete these three lines if you don't want the toolbar to
|
||
|
// be dockable
|
||
|
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
|
||
|
EnableDocking(CBRS_ALIGN_ANY);
|
||
|
DockControlBar(&m_wndToolBar);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
|
||
|
CCreateContext* pContext)
|
||
|
{
|
||
|
// create splitter window
|
||
|
if (!m_wndSplitter.CreateStatic(this, 1, 2))
|
||
|
return FALSE;
|
||
|
|
||
|
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CFTTreeView), CSize(200, 100), pContext) ||
|
||
|
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CFTListView), CSize(100, 100), pContext))
|
||
|
{
|
||
|
m_wndSplitter.DestroyWindow();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Create timer
|
||
|
m_unTimer = SetTimer( ID_TIMER_EVENT, TIMER_ELAPSE, NULL );
|
||
|
if( !m_unTimer )
|
||
|
TRACE( _T("Failure installing timer\n") );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
|
||
|
{
|
||
|
if( !CFrameWnd::PreCreateWindow(cs) )
|
||
|
return FALSE;
|
||
|
// TODO: Modify the Window class or styles here by modifying
|
||
|
// the CREATESTRUCT cs
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Public method: RefreshAll
|
||
|
|
||
|
Purpose: Refreshes the content of both views by keeping ( when possible ) the expanded and
|
||
|
selected items.
|
||
|
It is also possible to change the selected items and to add some expanded items
|
||
|
|
||
|
Parameters: [IN] CItemIDSet *psetAddTreeExpandedItems
|
||
|
Items to add to the currently expanded items set
|
||
|
[IN] CItemIDSet *psetTreeSelectedItems
|
||
|
Items to select in the tree ( the currently selected items are neglected )
|
||
|
[IN] CItemIDSet *psetListSelectedItems
|
||
|
Items to select in the list ( the currently selected items are neglected )
|
||
|
|
||
|
Return value: TRUE if the refresh operation succeeded
|
||
|
*/
|
||
|
|
||
|
BOOL CMainFrame::RefreshAll(
|
||
|
CItemIDSet* psetAddTreeExpandedItems /* =NULL */ ,
|
||
|
CItemIDSet* psetTreeSelectedItems /* =NULL */,
|
||
|
CItemIDSet* psetListSelectedItems /* =NULL */ )
|
||
|
{
|
||
|
CWaitCursor wc;
|
||
|
TREE_SNAPSHOT snapshotTree;
|
||
|
LIST_SNAPSHOT snapshotList;
|
||
|
BOOL bResult;
|
||
|
CAutoRefresh ar(FALSE);
|
||
|
|
||
|
DisplayStatusBarMessage( IDS_STATUS_REFRESH );
|
||
|
|
||
|
CFTTreeView* pTreeView = GetLeftPane();
|
||
|
CFTListView* pListView = GetRightPane();
|
||
|
|
||
|
// Get the snapshots of the tree and list views and do some changes ( if needed )
|
||
|
pTreeView->GetSnapshot(snapshotTree);
|
||
|
if( psetAddTreeExpandedItems )
|
||
|
snapshotTree.setExpandedItems += *psetAddTreeExpandedItems;
|
||
|
if( psetTreeSelectedItems )
|
||
|
snapshotTree.setSelectedItems = *psetTreeSelectedItems;
|
||
|
|
||
|
pListView->GetSnapshot( snapshotList );
|
||
|
if( psetListSelectedItems )
|
||
|
snapshotList.setSelectedItems = *psetListSelectedItems;
|
||
|
|
||
|
// Refresh the tree view
|
||
|
bResult = pTreeView->Refresh(snapshotTree);
|
||
|
|
||
|
// Set the snapshot pf the list view
|
||
|
pListView->SetSnapshot( snapshotList );
|
||
|
|
||
|
// All previous requests for auto refresh should be neglected now
|
||
|
m_bAutoRefreshRequested = FALSE;
|
||
|
|
||
|
DisplayStatusBarMessage( AFX_IDS_IDLEMESSAGE );
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMainFrame diagnostics
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
void CMainFrame::AssertValid() const
|
||
|
{
|
||
|
CFrameWnd::AssertValid();
|
||
|
}
|
||
|
|
||
|
void CMainFrame::Dump(CDumpContext& dc) const
|
||
|
{
|
||
|
CFrameWnd::Dump(dc);
|
||
|
}
|
||
|
|
||
|
#endif //_DEBUG
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CMainFrame message handlers
|
||
|
|
||
|
CFTTreeView* CMainFrame::GetLeftPane()
|
||
|
{
|
||
|
CWnd* pWnd = m_wndSplitter.GetPane(0, 0);
|
||
|
CFTTreeView* pView = DYNAMIC_DOWNCAST(CFTTreeView, pWnd);
|
||
|
return pView;
|
||
|
}
|
||
|
|
||
|
CFTListView* CMainFrame::GetRightPane()
|
||
|
{
|
||
|
CWnd* pWnd = m_wndSplitter.GetPane(0, 1);
|
||
|
CFTListView* pView = DYNAMIC_DOWNCAST(CFTListView, pWnd);
|
||
|
return pView;
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnUpdateViewStyles(CCmdUI* pCmdUI)
|
||
|
{
|
||
|
// TODO: customize or extend this code to handle choices on the
|
||
|
// View menu.
|
||
|
|
||
|
CFTListView* pView = GetRightPane();
|
||
|
|
||
|
// if the right-hand pane hasn't been created or isn't a view,
|
||
|
// disable commands in our range
|
||
|
|
||
|
if (pView == NULL)
|
||
|
pCmdUI->Enable(FALSE);
|
||
|
else
|
||
|
{
|
||
|
DWORD dwStyle = pView->GetStyle() & LVS_TYPEMASK;
|
||
|
|
||
|
// if the command is ID_VIEW_LINEUP, only enable command
|
||
|
// when we're in LVS_ICON or LVS_SMALLICON mode
|
||
|
|
||
|
if (pCmdUI->m_nID == ID_VIEW_LINEUP)
|
||
|
{
|
||
|
if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON)
|
||
|
pCmdUI->Enable();
|
||
|
else
|
||
|
pCmdUI->Enable(FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// otherwise, use dots to reflect the style of the view
|
||
|
pCmdUI->Enable();
|
||
|
BOOL bChecked = FALSE;
|
||
|
|
||
|
switch (pCmdUI->m_nID)
|
||
|
{
|
||
|
case ID_VIEW_DETAILS:
|
||
|
bChecked = (dwStyle == LVS_REPORT);
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_SMALLICON:
|
||
|
bChecked = (dwStyle == LVS_SMALLICON);
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_LARGEICON:
|
||
|
bChecked = (dwStyle == LVS_ICON);
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_LIST:
|
||
|
bChecked = (dwStyle == LVS_LIST);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
bChecked = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pCmdUI->SetRadio(bChecked ? 1 : 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CMainFrame::OnViewStyle(UINT nCommandID)
|
||
|
{
|
||
|
// TODO: customize or extend this code to handle choices on the
|
||
|
// View menu.
|
||
|
CFTListView* pView = GetRightPane();
|
||
|
|
||
|
// if the right-hand pane has been created and is a CFTListView,
|
||
|
// process the menu commands...
|
||
|
if (pView != NULL)
|
||
|
{
|
||
|
DWORD dwStyle = -1;
|
||
|
BOOL bExtendedNames = TRUE;
|
||
|
|
||
|
switch (nCommandID)
|
||
|
{
|
||
|
case ID_VIEW_LINEUP:
|
||
|
{
|
||
|
// ask the list control to snap to grid
|
||
|
CListCtrl& refListCtrl = pView->GetListCtrl();
|
||
|
refListCtrl.Arrange(LVA_SNAPTOGRID);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// other commands change the style on the list control
|
||
|
case ID_VIEW_DETAILS:
|
||
|
dwStyle = LVS_REPORT;
|
||
|
bExtendedNames = FALSE;
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_SMALLICON:
|
||
|
dwStyle = LVS_SMALLICON;
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_LARGEICON:
|
||
|
dwStyle = LVS_ICON;
|
||
|
break;
|
||
|
|
||
|
case ID_VIEW_LIST:
|
||
|
dwStyle = LVS_LIST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// change the style; window will repaint automatically
|
||
|
if (dwStyle != -1)
|
||
|
{
|
||
|
pView->ModifyStyle(LVS_TYPEMASK, dwStyle);
|
||
|
pView->DisplayItemsExtendedNames( bExtendedNames );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnViewToggle()
|
||
|
{
|
||
|
// TODO: Add your command handler code here
|
||
|
int nRow,nCol;
|
||
|
if( !m_wndSplitter.GetActivePane(&nRow,&nCol) )
|
||
|
return;
|
||
|
ASSERT( nRow == 0 );
|
||
|
ASSERT( nCol <= 1 );
|
||
|
m_wndSplitter.SetActivePane(0,1-nCol, NULL);
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnViewRefresh()
|
||
|
{
|
||
|
RefreshAll( NULL, NULL, NULL );
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnActivateApp(BOOL bActive, HTASK hTask)
|
||
|
{
|
||
|
CFrameWnd::OnActivateApp(bActive, hTask);
|
||
|
|
||
|
// TODO: Add your message handler code here
|
||
|
|
||
|
if( bActive )
|
||
|
{
|
||
|
if( m_bEnableAutoRefresh )
|
||
|
{
|
||
|
TRACE( _T("OnActivateApp AutoRefresh\n") );
|
||
|
RefreshAll();
|
||
|
}
|
||
|
else
|
||
|
m_bAutoRefreshRequested = TRUE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnDestroy()
|
||
|
{
|
||
|
if( m_unTimer )
|
||
|
KillTimer( m_unTimer );
|
||
|
|
||
|
CFrameWnd::OnDestroy();
|
||
|
|
||
|
// TODO: Add your message handler code here
|
||
|
|
||
|
}
|
||
|
|
||
|
void CMainFrame::OnTimer(UINT nIDEvent)
|
||
|
{
|
||
|
// TODO: Add your message handler code here and/or call default
|
||
|
if( ( nIDEvent == ID_TIMER_EVENT ) && m_bEnableAutoRefresh && ( GetActiveWindow() == this ) )
|
||
|
{
|
||
|
//TRACE("OnTimer\n");
|
||
|
CFTTreeView* pTreeView = GetLeftPane();
|
||
|
pTreeView->RefreshOnTimer();
|
||
|
}
|
||
|
|
||
|
CFrameWnd::OnTimer(nIDEvent);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Global functions related to the main frame
|
||
|
|
||
|
/*
|
||
|
Global function: RefreshAll
|
||
|
|
||
|
Purpose: Refreshes the content of both views of the mainframe by keeping ( when possible )
|
||
|
the expanded and selected items.
|
||
|
It is also possible to change the selected items and to add some expanded items
|
||
|
|
||
|
Parameters: [IN] CItemIDSet *psetAddTreeExpandedItems
|
||
|
Items to add to the currently expanded items set
|
||
|
[IN] CItemIDSet *psetTreeSelectedItems
|
||
|
Items to select in the tree ( the currently selected items are neglected )
|
||
|
[IN] CItemIDSet *psetListSelectedItems
|
||
|
Items to select in the list ( the currently selected items are neglected )
|
||
|
|
||
|
Return value: TRUE if the refresh operation succeeded
|
||
|
*/
|
||
|
|
||
|
BOOL AfxRefreshAll(
|
||
|
CItemIDSet* psetAddTreeExpandedItems /* =NULL */ ,
|
||
|
CItemIDSet* psetTreeSelectedItems /* =NULL */,
|
||
|
CItemIDSet* psetListSelectedItems /* =NULL */ )
|
||
|
{
|
||
|
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
|
||
|
ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMainFrame)));
|
||
|
|
||
|
return pFrame->RefreshAll( psetAddTreeExpandedItems, psetTreeSelectedItems, psetListSelectedItems );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Global function: AfxEnableAutoRefresh()
|
||
|
|
||
|
Purpose: Enables / Disables the auto refresh of both views of the mainframe on WM_ACTIVATEAPP
|
||
|
|
||
|
Parameters: [IN] BOOL bEnable
|
||
|
Specifies whether the auto-refresh is to be enabled or disabled
|
||
|
|
||
|
|
||
|
Return value: The previous status of the auto-refresh flag
|
||
|
*/
|
||
|
|
||
|
BOOL AfxEnableAutoRefresh( BOOL bEnable /* =TRUE */ )
|
||
|
{
|
||
|
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
|
||
|
ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMainFrame)));
|
||
|
|
||
|
BOOL bPrevious = pFrame->m_bEnableAutoRefresh;
|
||
|
|
||
|
// If the flag is enabling and an auto-refresh request came while it was disabled then proceed with auto-refresh
|
||
|
if( bEnable && !bPrevious && pFrame->m_bAutoRefreshRequested)
|
||
|
{
|
||
|
TRACE( _T("Late OnActivateApp AutoRefresh\n") );
|
||
|
AfxRefreshAll();
|
||
|
}
|
||
|
else if ( !bEnable && bPrevious )
|
||
|
pFrame->m_bAutoRefreshRequested = FALSE;
|
||
|
|
||
|
pFrame->m_bEnableAutoRefresh = bEnable;
|
||
|
|
||
|
return bPrevious;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
|
||
|
{
|
||
|
// TODO: Add your specialized code here and/or call the base class
|
||
|
switch( nID )
|
||
|
{
|
||
|
case ID_VIEW_UP:
|
||
|
case ID_INDICATOR_NAME:
|
||
|
case ID_INDICATOR_TYPE:
|
||
|
case ID_INDICATOR_DISKS:
|
||
|
case ID_INDICATOR_SIZE:
|
||
|
case ID_INDICATOR_NOTHING:
|
||
|
CFTTreeView* pTreeView = GetLeftPane();
|
||
|
return pTreeView->OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
|
||
|
|
||
|
}
|
||
|
|
||
|
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
|
||
|
}
|