
#include "stdafx.h"
#include "mainfrm.h"
#include "FileView.h"
#include "Resource.h"
#include "AKAssms.h"

#include "CWnd_Ext.h"
#include "P2Pwin32.h"
#include "P2Pmsg_Ext.h"
#include "CString_Ext.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define MSG_SQLselect                   _T("SQLselect")
#define MSG_SQLselectServerProperty     _T("SQLselectServerProperty")
#define MSG_SQLselectDatabaseItem       _T("SQLselectDatabaseItem")
#define MSG_SQLselectTableListItem      _T("SQLselectTableListItem")
#define MSG_SQLselectColumnListItem     _T("SQLselectColumnListItem")
#define MSG_SQLselectViewListItem       _T("SQLselectViewListItem")
#define MSG_SQLselectViewColumnListItem _T("SQLselectViewColumnListItem")
#define MSG_SQLselectStoredProcListItem _T("SQLselectStoredProcListItem")
#define MSG_SQLselectFunctionListItem   _T("SQLselectFunctionListItem")

static bool s_bSelectTop1000Rows = false;

/////////////////////////////////////////////////////////////////////////////
// CFileView

CFileView::CFileView()
{
   AllocConsole();
//Redirect unbuffered STDOUT to the console
   HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
   int SystemOutput = _open_osfhandle(intptr_t(ConsoleOutput), _O_TEXT);
   FILE *COutputHandle = _fdopen(SystemOutput, "w" );
   *stdout = *COutputHandle;
   setvbuf(stdout, NULL, _IONBF, 0);
}

CFileView::~CFileView()
{
    CWnd_BCastCancel ( this );
}

///////////////////////////////////////////////////////////////////////
//  Operations

void
CFileView::ClearViewContents ( )
{
    P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();
    if ( pMgr == 0 )
      return;
    m_wndP2PmsgTreeCtrl.RecyleThisObject ( );
    pMgr -> Truncate ( );
    SetWindowText ( _T("SQL Server Explorer") );

    P3PmsgNode oSQLserver = pMgr->DeclareNode ( _T("SQLserver"), P3PmsgData() ).r_Object();
    oSQLserver.DeclareNode ( "Databases", (INT32)0 ).r_Attr().DeclareField(_T("$Databases"),0);
    oSQLserver.DeclareNode ( "Security",  (INT32)0 );
    oSQLserver.DeclareNode ( "Server Objects", (INT32)0 );
    oSQLserver.DeclareNode ( "Replication", (INT32)0 );
    oSQLserver.DeclareNode ( "Management", (INT32)0 );
    m_nP2PosDatabases = oSQLserver.SelectNode("Databases").GetP2Pos();
}

void
CFileView::RefreshView ( )
{
    // To be sure, to be sure
    // NOTES: Under some circumstances P2PmsgMgr may not exist
    P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();
    m_wndP2PmsgTreeCtrl.RecyleThisObject ( );

    // Docking control labelling
    CString strTitle ( _T("SQL Server Explorer") );
    SetWindowText ( strTitle );

    // Explorer labelling
    CString strSQLserverLabel;
    if ( pMgr->r_Attr().Exists(_T("!Servername")) )
      strSQLserverLabel = pMgr->r_Attr().SelectItem(_T("!Servername")).c_str();
    strSQLserverLabel += _T(" (SQL Server ");
    if ( pMgr->r_Attr().Exists(_T("!ProductVersion")) )
      strSQLserverLabel += pMgr->r_Attr().SelectItem(_T("!ProductVersion")).c_str();
    strSQLserverLabel += _T(" - ");
    if ( pMgr->r_Attr().Exists(_T("!Username")) )
      strSQLserverLabel += pMgr->r_Attr().SelectItem(_T("!Username")).c_str();
    strSQLserverLabel += _T(")");
    pMgr -> c_name (strSQLserverLabel);

    // Delegations
    // NOTES: Unless SQLserver node exists nothing can be displayed
    P3PmsgNode oSQLserver = pMgr -> SelectNode(_T("SQLserver")).r_Object();
    m_wndP2PmsgTreeCtrl.Connect ( pMgr, oSQLserver.GetP2Pos(), m_hWnd );
    m_wndP2PmsgTreeCtrl.Expand ( TVI_ROOT, TVE_EXPAND );
}

void
CFileView::PostSQLSelect ( LPCTSTR lpszMsgReply,  LPCTSTR lpszSQLstmt
                         , P3PmsgField *pMsgReplyTag )
{
    // P2PeerHubODBC request
    P2PeerMsgSP spMsgSQL = new P2PeerMsg ( GetP2PaddrHub(), _T("AKAssms")
                                         , MSG_SQLselect
                                         , (void *)0, 0 );
    spMsgSQL -> r_datn().AddField ("SQLstmt"
                                  , DataBSTR16(lpszSQLstmt) );
    spMsgSQL -> r_datn().AddField ("MsgReply"
                                  , DataBSTR16(lpszMsgReply) );
    if ( pMsgReplyTag )
      spMsgSQL -> r_datn() += *pMsgReplyTag;
    AssignOwnership ( spMsgSQL );
    PostP2PeerMsg   ( spMsgSQL.Dereference() );
}

void
CFileView::QueryVisuals ( HTREEITEM hItem, BOOL bEoD )
{
    if ( hItem == 0 )
      return;
    CString strItemextra = _T(" (expanding...)");
    CString strItemtext  = m_wndP2PmsgTreeCtrl.GetItemText ( hItem );

    int idx = strItemtext.Find ( strItemextra );
    if ( idx > 0 )
      strItemtext = strItemtext.Left ( idx );
    if ( bEoD )
      strItemtext += strItemextra;
    m_wndP2PmsgTreeCtrl.SetItemText ( hItem, strItemtext );
}


///////////////////////////////////////////////////////////////////////
//  P2PeerMsg Handlers
//  NOTES: SQL server interaction handlers
//       : If there is a desire to optimise the message map
//         subjectively place frequent messages at the top and less
//         frequent messages at the bottom of the map
//
BEGIN_P2PeerMsg_MAP(CFileView, P2PeerTarget)
    ON_P2PeerMsg(MSG_SQLselectServerProperty,On_SQLselectServerProperty)

    // Database exploration
    ON_P2PeerMsg_CATCH(MSG_SQLselect,On_SQLselectCatch)
    ON_P2PeerMsg(MSG_SQLselectDatabaseItem,On_SQLselectDatabaseItem)
    ON_P2PeerMsg(MSG_SQLselectTableListItem,On_SQLselectTableListItem)
    ON_P2PeerMsg(MSG_SQLselectColumnListItem,On_SQLselectColumnListItem)
    ON_P2PeerMsg(MSG_SQLselectViewListItem,On_SQLselectViewListItem)
    ON_P2PeerMsg(MSG_SQLselectViewColumnListItem,On_SQLselectViewColumnListItem)
    ON_P2PeerMsg(MSG_SQLselectStoredProcListItem,On_SQLselectStoredProcListItem)
    ON_P2PeerMsg(MSG_SQLselectFunctionListItem,On_SQLselectFunctionListItem)
END_P2PeerMsg_MAP()

//
//  MSG_ContentRange message exception handler
//  NOTES: Removal of "Content-Range" handle effectively cancels
//         sequence and recovers resources
//
//  Parameters:  P2PeerMsg *pMsg
//               Exception message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectCatch ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
pMsg->Print(stdout);
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}

//
//  MSG_SQLselectServerProperty selection handler
//  NOTES: Processes selection of certain server properties
//
//  Parameters:  P2PeerMsg *pMsg
//               Selection response message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectServerProperty  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
pMsg->r_datn().Print(stdout,1,1);
      P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode oNodeSQL = pMsg->r_datn().SelectObject("SQL");
        if ( oNodeSQL.Exists("ProductVersion") )
          pMgr->r_Attr().DeclareField(_T("!ProductVersion"),oNodeSQL.SelectItem(_T("ProductVersion")).r_data());

        RefreshView ( );
      }

      // Handled
     return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}

//
//  MSG_SQLselectDatabaseItem selection handler
//  NOTES: Populate tree with details and recursively request list
//         of table items for database
//
//  Parameters:  P2PeerMsg *pMsg
//               Reflection message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectDatabaseItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
//pMsg->r_datn().Print(stdout,1,1);
      P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();
      P3PmsgNode oDatabases = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode oNodeSQL = pMsg->r_datn().SelectObject("SQL");
        LPCTSTR    lpszDatabaseName = oNodeSQL["name"].r_data().c_str();
        P3PmsgNode oNodeDBs = pMgr -> P2Pos2NodeHdl ( m_nP2PosDatabases );
        if ( oNodeSQL.SelectItem(_T("dbid")).c_short() <= 4 )
          oNodeDBs = oNodeDBs.SelectObject(_T("System Databases"));
        oNodeDBs.DeclareNode ( lpszDatabaseName, 0 );
        P3PmsgNode oNodeDB  = oNodeDBs.SelectObject ( lpszDatabaseName );
                   oNodeDB.r_Attr().DeclareField ( _T("$Database"), 0 );

        // Confirm subordinate nodes
        P3PmsgData oData(0);           // Flag not populated
        oNodeDB.DeclareNode ( "Tables", oData ).r_Attr().DeclareField(_T("$Tables"),0);
        oNodeDB.DeclareNode ( "Views", oData ).r_Attr().DeclareField(_T("$Views"),0);
        oNodeDB.DeclareNode ( "Synonyms", oData );
        oNodeDB.DeclareNode ( "Programmability", oData );
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Stored Procedures",0).r_Attr().DeclareField("$StoredProcs",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Functions",0).r_Attr().DeclareField("$Functions",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Database Triggers",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Assemblies",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Types",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Rules",0);
        oNodeDB.SelectNode  ( "Programmability" ).DeclareNode ( "Defaults",0);
        oNodeDB.DeclareNode ( "Service Broker", oData );
        oNodeDB.DeclareNode ( "Storage", oData );
        oNodeDB.DeclareNode ( "Security", oData );
      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oDatabases.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
     return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}
void
CFileView::QueryDatabases ( P3PmsgNode& oDatabases )
{
    // Select available database list
    LPCTSTR lpszSQLstmt = _T("SELECT * FROM master.dbo.sysdatabases ORDER by name;");
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oDatabases.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectDatabaseItem, lpszSQLstmt, &oMsgReplyTag );

    // Preparation
    oDatabases.DeclareNode ("System Databases",0);
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oDatabases.GetP2Pos() );
    QueryVisuals ( hItem, TRUE );      // (expanding...) feedback

    // State management
    oDatabases.r_Attr().SelectItem(_T("$Databases")).c_int() = 1;
}

//
//  MSG_SQLselectTableListItem selection handler
//  NOTES: Populate tree with details and recursively requested list
//         of tables for database
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectTableListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr    = theApp.GetP2PmsgMgr();
      P3PmsgNode oTables = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
        //P3PmsgNode  oNodeDB     = oNodeDBs.SelectNode(lpszDatabaseName).r_Object();
        P3PmsgNode  oNodeTables = oTables.ROBJ; //oNodeDB.SelectObject(_T("Views"));
        if ( oNodeSQL.SelectItem("is_ms_shipped").r_data().c_bool() )
          oNodeTables = oNodeTables.SelectObject ("System Tables");
        LPCTSTR  lpszTablename = oNodeSQL.SelectItem (_T("AKAssms_TablePath")).c_str();
        P3PmsgNode  oNodeTable = oNodeTables.PushBack ( P3PmsgNode(P3PmsgField(lpszTablename,0)) );
        //P3PmsgNode  oNodeView  = oNodeViews.SelectNode( lpszViewname );
                    oNodeTable.ATTR.DeclareField ( _T("$Table"), 0 );
                    oNodeTable.ATTR += oNodeSQL;
      }
//      if ( pMsg->r_datn().Exists("SQL") )
//      {
//        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
//oNodeSQL.Print(stdout,1);
//        P3PmsgNode    oNodeDBs      = pMgr -> P2Pos2NodeHdl ( m_nP2PosDatabases );
//        LPCTSTR    lpszDatabaseName = oNodeSQL.SelectItem ( _T("TABLE_CATALOG") ).c_str();
//        P3PmsgNode    oNodeDB       = P3Pmsg_FindChildWithAttr(oNodeDBs,_T("$Database"),lpszDatabaseName);
//        if ( oNodeDB.r_Object() )
//        {
//          P3PmsgNode  oNodeTables = oNodeDB.SelectObject(_T("Tables"));
//          LPCTSTR  lpszTablename  = oNodeSQL.SelectItem ( _T("TABLE_NAME") ).c_str();
//          oNodeTables.DeclareNode ( lpszTablename, 0 );
//          P3PmsgNode  oNodeTable  = oNodeTables.SelectObject( lpszTablename );
//                      oNodeTable.r_Attr().DeclareField ( _T("$Table"), 0 );
//                      oNodeTable.r_Attr() += oNodeSQL;
//        }
//      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oTables.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}
void
CFileView::QueryTables ( P3PmsgNode& oTables )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oTables.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();

    // Request all table names for database
    //    P2PeerMsgSP spMsgSQL = new P2PeerMsg ( GetP2PaddrHub(), _T("AKAssms")
    //                                         , MSG_SQLselect
    //                                         , (void *)0, 0 );
    CString strSQLstmt;
    //strSQLstmt.Format ( _T("SELECT * FROM %s.information_schema.tables ORDER BY TABLE_NAME;")
    //                  , lpszDatabaseName );
    strSQLstmt.Format ( _T("SELECT  *, SCHEMA_NAME(A.schema_id) + '.' + A.name as AKAssms_TablePath ")
                                 _T(", '%s' as AKAssms_DBname ")
                        _T("FROM %s.sys.all_objects A, %s.INFORMATION_SCHEMA.SCHEMATA B ")
                        _T("WHERE A.type = 'U' ")
                        _T("AND SCHEMA_NAME(A.schema_id) = B.schema_name ")
                        _T("ORDER BY SCHEMA_NAME(A.schema_id) + '*' + A.name;")
                      , lpszDatabaseName, lpszDatabaseName, lpszDatabaseName );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oTables.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectTableListItem, strSQLstmt, &oMsgReplyTag );

    // Visuals
    oTables.DeclareNode ("System Tables",0);
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oTables.GetP2Pos() );
    QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
}
void
CFileView::QueryTable ( P3PmsgNode& oTable )
{
    // Populate subordinate nodes
    P3PmsgData oData;
    oTable.DeclareNode ( "Columns", oData ).r_Attr().DeclareField(_T("$Columns"),0);
    oTable.DeclareNode ( "Keys", oData );
    oTable.DeclareNode ( "Constraints", oData );
    oTable.DeclareNode ( "Triggers", oData );
    oTable.DeclareNode ( "Indexes", oData );
    oTable.DeclareNode ( "Storage", oData );
    oTable.DeclareNode ( "Statistics", oData );
    // Visuals
    if ( s_bSelectTop1000Rows )
      return;
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oTable.GetP2Pos() );
    if ( hItem )
      m_wndP2PmsgTreeCtrl.Expand ( hItem, TVE_EXPAND );
    QueryVisuals ( hItem, FALSE );      // remove (expanding...) feedback
}

//
//  MSG_SQLselectColumnListItem selection handler
//  NOTES: Populate tree with details and recursively request list
//         of column items for table
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectColumnListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr    = theApp.GetP2PmsgMgr();
      P3PmsgNode oColumn = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      CString strTemp;
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");

        CString strColumnDetails = oNodeSQL["name"].r_data().c_str();
        strColumnDetails += _T(" (");
        if ( oNodeSQL["AKAssms_DataType"].r_data().c_stricmp(_T("nvarchar")) == 0 )
          strTemp.Format ( _T("nvarchar(%i)"), oNodeSQL["max_length"].c_short() );
        else
          strTemp = oNodeSQL["AKAssms_DataType"].r_data().c_str();
        strColumnDetails += strTemp;
        strColumnDetails += _T(", ");
        if ( oNodeSQL["is_nullable"].r_data().c_bool() == 0 )
          strColumnDetails += _T("not null)");
        else
          strColumnDetails += _T("null)"); 

        oColumn.DeclareNode ( strColumnDetails, 0 );
      }

      // Selection special 
      else if ( s_bSelectTop1000Rows )
      {
        s_bSelectTop1000Rows = false;
        PostMessage ( WM_COMMAND, ID_TABLE_SELECTTOP1000ROWS, 0 );
      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oColumn.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}

void
CFileView::QueryColumns ( P3PmsgNode& oColumns )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oColumns.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();
    P3PmsgNode oTable  = P3Pmsg_FindParentWithAttr (oColumns.r_Object(),_T("$Table"));
    LPCTSTR lpszTablename    = oTable.c_name();
oTable.Print(stdout,1);
    // Request all column names for view
    // NOTES: Responses will subsequently generate table queries etc
    CString strSQLstmt;
    //strSQLstmt.Format ( _T("SELECT * from %s.INFORMATION_SCHEMA.COLUMNS IC where TABLE_NAME = '%s';")
    strSQLstmt.Format ( _T("SELECT *, B.name as AKAssms_DataType ")
                        _T("FROM [%s].[sys].[all_columns] A, [%s].[sys].[types] B ")
                        _T("WHERE object_id = %i and B.system_type_id = A.system_type_id " )
                        _T("ORDER BY column_id" )
                      , lpszDatabaseName, lpszDatabaseName
                      , oTable.ATTR["SQL"].SelectItem("object_id").c_int() );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oColumns.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectColumnListItem, strSQLstmt, &oMsgReplyTag );

    // Visuals
    if ( !s_bSelectTop1000Rows )
    {
      HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oColumns.GetP2Pos() );
      QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
    }
}

//
//  MSG_SQLselectViewListItem selection handler
//  NOTES: Populate tree with details and recursively requested list
//         of Views for database
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectViewListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr   = theApp.GetP2PmsgMgr();
      P3PmsgNode oViews = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
        //P3PmsgNode  oNodeDB     = oNodeDBs.SelectNode(lpszDatabaseName).r_Object();
        P3PmsgNode  oNodeViews = oViews.ROBJ; //oNodeDB.SelectObject(_T("Views"));
        if ( oNodeSQL.SelectItem("is_ms_shipped").r_data().c_bool() )
          oNodeViews = oNodeViews.SelectObject ("System Views");
        LPCTSTR  lpszViewname  = oNodeSQL.SelectItem (_T("AKAssms_VName")).c_str();
        P3PmsgNode  oNodeView  = oNodeViews.PushBack ( P3PmsgNode(P3PmsgField(lpszViewname,0)) );
        //P3PmsgNode  oNodeView  = oNodeViews.SelectNode( lpszViewname );
                    oNodeView.ATTR.DeclareField ( _T("$View"), 0 );
                    oNodeView.ATTR += oNodeSQL;
      }
      //if ( pMsg->r_datn().Exists("SQL") )
      //{
      //  P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
      //  P3PmsgNode    oNodeDBs      = pMgr -> P2Pos2NodeHdl ( m_nP2PosDatabases );
      //  LPCTSTR    lpszDatabaseName = oNodeSQL.SelectItem ( _T("TABLE_CATALOG") ).c_str();
      //  P3PmsgNode    oNodeDB       = P3Pmsg_FindChildWithAttr(oNodeDBs,_T("$Database"),lpszDatabaseName);
      //  if ( oNodeDB.r_Object() )
      //  {
      //    //P3PmsgNode  oNodeDB     = oNodeDBs.SelectNode(lpszDatabaseName).r_Object();
      //    P3PmsgNode  oNodeViews = oNodeDB.SelectObject(_T("Views"));
      //    LPCTSTR  lpszViewname  = oNodeSQL.SelectItem (_T("TABLE_NAME")).c_str();
      //    oNodeViews.DeclareNode ( lpszViewname, 0 );
      //    P3PmsgNode  oNodeView  = oNodeViews.SelectObject( lpszViewname );
      //                oNodeView.r_Attr().DeclareField ( _T("$View"), 0 );
      //                oNodeView.r_Attr() += oNodeSQL;
      //  }
      //}

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oViews.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}
void
CFileView::QueryViews ( P3PmsgNode& oViews )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oViews.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();
    ASSERT(oViews.GetCount()<=0);

    // Request list of all views for database
    CString strSQLstmt;
    //strSQLstmt.Format ( _T("SELECT * FROM %s.information_schema.views ORDER BY TABLE_NAME;")
    //strSQLstmt.Format ( _T("SELECT *, '%s' as AKAssms_DBname FROM %s.sys.all_views ORDER BY name;")
    strSQLstmt.Format ( _T("SELECT  *, SCHEMA_NAME(A.schema_id) + '.' + A.name as AKAssms_VName ")
                                 _T(", '%s' as AKAssms_DBname ")
                        _T("FROM %s.sys.all_views A, %s.INFORMATION_SCHEMA.SCHEMATA B ")
                        _T("WHERE A.type = 'V' ")
                        _T("AND SCHEMA_NAME(A.schema_id) = B.schema_name ")
                        _T("ORDER BY SCHEMA_NAME(A.schema_id) + '*' + A.name;")
                      , lpszDatabaseName, lpszDatabaseName, lpszDatabaseName );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oViews.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectViewListItem, strSQLstmt, &oMsgReplyTag );

    // Visuals
    oViews.DeclareNode ("System Views",0);
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oViews.GetP2Pos() );
    QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
}
void
CFileView::QueryView ( P3PmsgNode& oView )
{
    // Populate subordinate nodes
    P3PmsgData oData;
    oView.DeclareNode ( "Columns", oData ).r_Attr().DeclareField(_T("$VColumns"),0);
    oView.DeclareNode ( "Triggers", oData );
    oView.DeclareNode ( "Indexes", oData );
    oView.DeclareNode ( "Statistics", oData );
    // Visuals
    if ( s_bSelectTop1000Rows )
      return;
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oView.GetP2Pos() );
    QueryVisuals ( hItem, FALSE );      // remove (expanding...) feedback
    if ( hItem )
      m_wndP2PmsgTreeCtrl.Expand ( hItem, TVE_EXPAND );
}

//
//  MSG_SQLselectViewColumnListItem selection handler
//  NOTES: Populate tree with details and recursively request list
//         of column items for View
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectViewColumnListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr     = theApp.GetP2PmsgMgr();
      P3PmsgNode oVColumn = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      CString strTemp;
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");

        CString strColumnDetails = oNodeSQL["name"].r_data().c_str();
        strColumnDetails += _T(" (");
        if ( oNodeSQL["AKAssms_DataType"].r_data().c_stricmp(_T("nvarchar")) == 0 )
          strTemp.Format ( _T("nvarchar(%i)"), oNodeSQL["max_length"].c_short() );
        else
          strTemp = oNodeSQL["AKAssms_DataType"].r_data().c_str();
        strColumnDetails += strTemp;
        strColumnDetails += _T(", ");
        if ( oNodeSQL["is_nullable"].r_data().c_bool() == 0 )
          strColumnDetails += _T("not null)");
        else
          strColumnDetails += _T("null)"); 

        oVColumn.DeclareNode ( strColumnDetails, 0 );
      }

      // Selection special 
      else if ( s_bSelectTop1000Rows )
      {
        s_bSelectTop1000Rows = false;
        PostMessage ( WM_COMMAND, ID_VIEW_SELECTTOP1000ROWS, 0 );
      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oVColumn.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}
void
CFileView::QueryVColumns ( P3PmsgNode& oVColumns )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oVColumns.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();
    P3PmsgNode oView   = P3Pmsg_FindParentWithAttr (oVColumns.r_Object(),_T("$View"));
    LPCTSTR lpszViewname     = oView.c_name();
oView.Print(stdout,1);
    // Request all column names for view
    // NOTES: Responses will subsequently generate table queries etc
    CString strSQLstmt;
    //strSQLstmt.Format ( _T("SELECT * from %s.INFORMATION_SCHEMA.COLUMNS IC where TABLE_NAME = '%s';")
    strSQLstmt.Format ( _T("SELECT *, B.name as AKAssms_DataType ")
                        _T("FROM [%s].[sys].[all_columns] A, [%s].[sys].[types] B ")
                        _T("WHERE object_id = %i and B.system_type_id = A.system_type_id " )
                        _T("ORDER BY column_id" )
                      , lpszDatabaseName, lpszDatabaseName
                      , oView.ATTR["SQL"].SelectItem("object_id").c_int() );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oVColumns.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectViewColumnListItem, strSQLstmt, &oMsgReplyTag );

    // Visuals
    if ( !s_bSelectTop1000Rows )
    {
      HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oVColumns.GetP2Pos() );
      QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
    }
}

//
//  MSG_SQLselectStoredProcListItem selection handler
//  NOTES: Populate tree with details and recursively requested list
//         of Stored Procedures for database
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectStoredProcListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();
      P3PmsgNode oProcList = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
        P3PmsgNode    oNodeDBs      = pMgr -> P2Pos2NodeHdl ( m_nP2PosDatabases );
        LPCTSTR    lpszDatabaseName = oNodeSQL.SelectItem ( _T("AKAssms_DBname") ).c_str();
        if ( oNodeDBs.Exists(lpszDatabaseName) )
        {
          P3PmsgNode  oNodeDB     = oNodeDBs.SelectNode(lpszDatabaseName).r_Object();
          P3PmsgNode  oNodeSPs    = oNodeDB.SelectObject(_T("Programmability.Stored Procedures"));
          LPCTSTR  lpszSPname     = oNodeSQL.SelectItem (_T("name") ).c_str();
          if ( oNodeSQL.SelectItem("is_ms_shipped").r_data().c_bool() )
            oNodeSPs = oNodeSPs.SelectObject ("System Stored Procedures");
//else oNodeSQL.Print(stdout,0,0);
          oNodeSPs.DeclareNode ( lpszSPname, 0 );
          P3PmsgNode  oNodeSP     = oNodeSPs.SelectObject( lpszSPname );
                      oNodeSP.r_Attr().DeclareField ( _T("$SP"), 0 );
                      oNodeSP.r_Attr() += oNodeSQL;
         }
      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oProcList.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}

void
CFileView::QueryStoredProcs ( P3PmsgNode& oStoredProcs )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oStoredProcs.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();

    // NOTES: Request all stored procedures for database
    CString strSQLstmt;
    //strSQLstmt.Format ( _T("SELECT *, '%s' as AKAssms_DBname FROM %s.dbo.sysobjects WHERE (type = 'P');")
    strSQLstmt.Format ( _T("SELECT *, '%s' as AKAssms_DBname FROM %s.sys.all_objects WHERE (type = 'P');")
                      , lpszDatabaseName, lpszDatabaseName );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oStoredProcs.GetP2Pos()) );
    PostSQLSelect (MSG_SQLselectStoredProcListItem, strSQLstmt, &oMsgReplyTag );

    // Preparation
    oStoredProcs.DeclareNode ("System Stored Procedures",0);
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oStoredProcs.GetP2Pos() );
    QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
}

//
//  MSG_SQLselectFunctionListItem selection handler
//  NOTES: Populate tree with details and recursively requested list
//         of Functions for database
//
//  Parameters:  P2PeerMsg *pMsg
//               Selected item message
//
//  Returns:     msgRESULT
//               Completion summary
//
msgRESULT
CFileView::On_SQLselectFunctionListItem  ( P2PeerMsg *pMsg )
{
    // Because this is all problematic, we
    try
    {
      // Confirm thread context
      // NOTES: Always process in CWinApp thread context, for this to all
      //        work CMainFrame must support WM_APP_P2PeerTarget message handler
      if ( !P2PeerContext(AfxGetApp()->m_nThreadID) )
        return P2PeerContextSwap ( theApp.GetMainWnd()->m_hWnd
                                 , WM_APP_P2PeerTarget );
      P2PmsgMgr *pMgr = theApp.GetP2PmsgMgr();
      P3PmsgNode oFunction = pMgr->P2Pos2NodeHdl ( pMsg->r_datn().SelectItem(_T("MsgReplyTag")).c_uint() );

      // Instanciate Root.Databases.Items
      if ( pMsg->r_datn().Exists("SQL") )
      {
        P3PmsgNode    oNodeSQL      = pMsg->r_datn().SelectObject("SQL");
oNodeSQL.Print(stdout,1,1);
        P3PmsgNode    oNodeDBs      = pMgr -> P2Pos2NodeHdl ( m_nP2PosDatabases );
        LPCTSTR    lpszDatabaseName = oNodeSQL.SelectItem ( _T("AKAssms_DBname") ).c_str();
        if ( oNodeDBs.Exists(lpszDatabaseName) )
        {
          P3PmsgNode  oNodeDB     = oNodeDBs.SelectNode(lpszDatabaseName).r_Object();
          P3PmsgNode  oNodeFUNCs  = oNodeDB.SelectObject(_T("Programmability.Functions"));
          bool bIs_MS_Shipped = oNodeSQL.SelectItem("is_ms_shipped").r_data().c_bool();
          if ( bIs_MS_Shipped )
          {
            oNodeFUNCs = oNodeFUNCs.SelectObject ("System Functions");
            if ( oNodeSQL[_T("type")].r_data().c_stricmp("AF") == 0 )
              oNodeFUNCs = oNodeFUNCs.SelectObject ("Aggregate Functions");
          }
          LPCTSTR  lpszFuncname     = oNodeSQL.SelectItem (_T("name") ).c_str();
          oNodeFUNCs.DeclareNode ( lpszFuncname, 0 );
          P3PmsgNode  oNodeFUNC   = oNodeFUNCs.SelectObject( lpszFuncname );
                      oNodeFUNC.r_Attr().DeclareField ( _T("$FUNC"), 0 );
                      oNodeFUNC.r_Attr() += oNodeSQL;
        }
      }

      // Last record in series
      else
      {
        HTREEITEM hItemParent = m_wndP2PmsgTreeCtrl.IsItem(oFunction.GetP2Pos() );
        if ( hItemParent )
          m_wndP2PmsgTreeCtrl.Expand ( hItemParent, TVE_EXPAND );
        QueryVisuals ( hItemParent, FALSE );     // remove (expanding...) feedback
      }

      // Handled
      return msgHANDLED;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel

    // Tidy up and
    return msgHANDLED;
}

void
CFileView::QueryFunctions ( P3PmsgNode& oFunctions )
{
    P3PmsgNode oNodeDB = P3Pmsg_FindParentWithAttr (oFunctions.r_Object(),_T("$Database"));
    LPCTSTR lpszDatabaseName = oNodeDB.c_name();

    // Request all functions for database
    CString strSQLstmt;
    strSQLstmt.Format ( _T("SELECT *, '%s' as AKAssms_DBname FROM %s.sys.all_objects WHERE type_desc LIKE '%%FUNC%%';")
    //strSQLstmt.Format ( _T("SELECT *, '%s' as AKAssms_DBname FROM %s.sys.system_objects WHERE type_desc LIKE '%%FUNC%%';")
                      , lpszDatabaseName, lpszDatabaseName );
    P3PmsgField oMsgReplyTag ( _T("MsgReplyTag"), P3PmsgData(oFunctions.GetP2Pos()) );
    PostSQLSelect ( MSG_SQLselectFunctionListItem, strSQLstmt, &oMsgReplyTag );

    // Preparation
    oFunctions.DeclareNode ("Table-valued Functions",0);
    oFunctions.DeclareNode ("Scalar-valued Functions",0);
    oFunctions.DeclareNode ("Aggregate Functions",0);
    P3PmsgNode oSysFuncs = oFunctions.DeclareNode ("System Functions",0).r_Object();
    oSysFuncs.DeclareNode  ("Aggregate Functions",0);
    oSysFuncs.DeclareNode  ("Configuration Functions",0);
    oSysFuncs.DeclareNode  ("Cursor Functions",0);
    oSysFuncs.DeclareNode  ("Date and Time Functions",0);
    oSysFuncs.DeclareNode  ("Mathematical Functions",0);
    oSysFuncs.DeclareNode  ("Metadata Functions",0);
    oSysFuncs.DeclareNode  ("Other Functions",0);
    oSysFuncs.DeclareNode  ("Heirarchy Id Functions",0);
    oSysFuncs.DeclareNode  ("Rowset Functions",0);
    oSysFuncs.DeclareNode  ("Security Functions",0);
    oSysFuncs.DeclareNode  ("String Functions",0);
    oSysFuncs.DeclareNode  ("System Statistical Functions",0);
    oSysFuncs.DeclareNode  ("Test and Image Functions",0);

    // Visuals
    HTREEITEM hItem = m_wndP2PmsgTreeCtrl.IsItem ( oFunctions.GetP2Pos() );
    QueryVisuals ( hItem, TRUE );      // (expanding...) feedback
}

/////////////////////////////////////////////////////////////////////////////
// CWorkspaceBar message handlers

int CFileView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
		return -1;

	CRect rectDummy;
	rectDummy.SetRectEmpty();

	// Create view:
	//const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
	//if (!m_wndFileView.Create(dwViewStyle, rectDummy, this, 4))
	//{
	//	TRACE0("Failed to create file view\n");
	//	return -1;      // fail to create
	//}
    // Create view:
    const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_EDITLABELS;
    if ( !m_wndP2PmsgTreeCtrl.Create(dwViewStyle,rectDummy,this,4) )
    {
      TRACE0("Failed to create file view\n");
      return -1;      // fail to create
    }
    m_wndP2PmsgTreeCtrl.Connect ( 0, 0, 0 );

	// Load view images:
	m_FileViewImages.Create(IDB_FILE_VIEW, 16, 0, RGB(255, 0, 255));
	m_wndP2PmsgTreeCtrl.SetImageList(&m_FileViewImages, TVSIL_NORMAL);

	m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_EXPLORER);
	m_wndToolBar.LoadToolBar(IDR_EXPLORER, 0, 0, TRUE /* Is locked */);

	OnChangeVisualStyle();

	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);

	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM | CBRS_BORDER_LEFT | CBRS_BORDER_RIGHT));

	m_wndToolBar.SetOwner(this);

	// All commands will be routed via this control , not via the parent frame:
	m_wndToolBar.SetRouteCommandsViaFrame(FALSE);

	  // Fill in some static tree view data (dummy code, nothing magic here)
	  //FillFileView();
	  AdjustLayout();

    // REgister for SQL-Server connections and disconnections
    CWnd_BCastRegister ( this, WM_APP_CONNECT_SQLSERVER,    TRUE );
    CWnd_BCastRegister ( this, WM_APP_DISCONNECT_SQLSERVER, TRUE );
    return 0;
}

void CFileView::OnSize(UINT nType, int cx, int cy)
{
	CDockablePane::OnSize(nType, cx, cy);
	AdjustLayout();
}

void CFileView::FillFileView()
{
	/*HTREEITEM hRoot = m_wndFileView.InsertItem(_T("FakeApp files"), 0, 0);
	m_wndFileView.SetItemState(hRoot, TVIS_BOLD, TVIS_BOLD);

	HTREEITEM hSrc = m_wndFileView.InsertItem(_T("FakeApp Source Files"), 0, 0, hRoot);

	m_wndFileView.InsertItem(_T("FakeApp.cpp"), 1, 1, hSrc);
	m_wndFileView.InsertItem(_T("FakeApp.rc"), 1, 1, hSrc);
	m_wndFileView.InsertItem(_T("FakeAppDoc.cpp"), 1, 1, hSrc);
	m_wndFileView.InsertItem(_T("FakeAppView.cpp"), 1, 1, hSrc);
	m_wndFileView.InsertItem(_T("MainFrm.cpp"), 1, 1, hSrc);
	m_wndFileView.InsertItem(_T("StdAfx.cpp"), 1, 1, hSrc);

	HTREEITEM hInc = m_wndFileView.InsertItem(_T("FakeApp Header Files"), 0, 0, hRoot);

	m_wndFileView.InsertItem(_T("FakeApp.h"), 2, 2, hInc);
	m_wndFileView.InsertItem(_T("FakeAppDoc.h"), 2, 2, hInc);
	m_wndFileView.InsertItem(_T("FakeAppView.h"), 2, 2, hInc);
	m_wndFileView.InsertItem(_T("Resource.h"), 2, 2, hInc);
	m_wndFileView.InsertItem(_T("MainFrm.h"), 2, 2, hInc);
	m_wndFileView.InsertItem(_T("StdAfx.h"), 2, 2, hInc);

	HTREEITEM hRes = m_wndFileView.InsertItem(_T("FakeApp Resource Files"), 0, 0, hRoot);

	m_wndFileView.InsertItem(_T("FakeApp.ico"), 2, 2, hRes);
	m_wndFileView.InsertItem(_T("FakeApp.rc2"), 2, 2, hRes);
	m_wndFileView.InsertItem(_T("FakeAppDoc.ico"), 2, 2, hRes);
	m_wndFileView.InsertItem(_T("FakeToolbar.bmp"), 2, 2, hRes);

	m_wndFileView.Expand(hRoot, TVE_EXPAND);
	m_wndFileView.Expand(hSrc, TVE_EXPAND);
	m_wndFileView.Expand(hInc, TVE_EXPAND);*/
}

void CFileView::OnContextMenu(CWnd* pWnd, CPoint oCPoint)
{
	  CTreeCtrl* pWndTree = (CTreeCtrl *)&m_wndP2PmsgTreeCtrl;
	  ASSERT_VALID(pWndTree);

	if (pWnd != pWndTree)
	{
		CDockablePane::OnContextMenu(pWnd, oCPoint);
		return;
	}

    // Popups for this object
    CMenu  oCMenuPopups;
    oCMenuPopups.LoadMenu ( IDR_POPUP_EXPLORER );
    CMenu *pCMenu = 0;

    // According to CTreeCtrl context
  	if ( oCPoint != CPoint(-1,-1) )
	  {
		  // Select clicked item:
		  CPoint ptTree = oCPoint;
		  pWndTree -> ScreenToClient ( &ptTree );

		  UINT flags = 0;
		  HTREEITEM hTreeItem = pWndTree->HitTest(ptTree, &flags);
		  if ( hTreeItem != NULL )
			  pWndTree->SelectItem(hTreeItem);
      P3PmsgAttr oAttr = m_wndP2PmsgTreeCtrl.GetItemAttr(hTreeItem).r_Object();

      if ( oAttr.Exists(_T("$Database")) )
        pCMenu = oCMenuPopups.GetSubMenu ( 1 );
      else if ( oAttr.Exists(_T("$Table")) )
        pCMenu = oCMenuPopups.GetSubMenu ( 2 );
      else if ( oAttr.Exists(_T("$View")) )
        pCMenu = oCMenuPopups.GetSubMenu ( 3 );
    }

    // Environmental and implementation
    pWndTree -> SetFocus();
    if ( pCMenu )
	    theApp.GetContextMenuManager()
        -> ShowPopupMenu ( pCMenu->m_hMenu, oCPoint.x, oCPoint.y, this, TRUE );

	//pWndTree->SetFocus();
	//theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EXPLORER, point.x, point.y, this, TRUE);
}

void CFileView::AdjustLayout()
{
	if (GetSafeHwnd() == NULL)
	{
		return;
	}

	CRect rectClient;
	GetClientRect(rectClient);

	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;

	m_wndToolBar.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
	m_wndP2PmsgTreeCtrl.SetWindowPos(NULL, rectClient.left + 1, rectClient.top + cyTlb + 1, rectClient.Width() - 2, rectClient.Height() - cyTlb - 2, SWP_NOACTIVATE | SWP_NOZORDER);
}

void CFileView::OnProperties()
{
	AfxMessageBox(_T("Properties...."));

}

void CFileView::OnFileOpen()
{
	// TODO: Add your command handler code here
}

void CFileView::OnFileOpenWith()
{
	// TODO: Add your command handler code here
}

void CFileView::OnDummyCompile()
{
	// TODO: Add your command handler code here
}

void CFileView::OnEditCut()
{
	// TODO: Add your command handler code here
}

void CFileView::OnEditCopy()
{
	// TODO: Add your command handler code here
}

void CFileView::OnEditClear()
{
	// TODO: Add your command handler code here
}

void CFileView::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	CRect rectTree;
	m_wndP2PmsgTreeCtrl.GetWindowRect(rectTree);
	ScreenToClient(rectTree);

	rectTree.InflateRect(1, 1);
	dc.Draw3dRect(rectTree, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW));
}

void CFileView::OnSetFocus(CWnd* pOldWnd)
{
	CDockablePane::OnSetFocus(pOldWnd);

	m_wndP2PmsgTreeCtrl.SetFocus();
}

void CFileView::OnChangeVisualStyle()
{
	m_wndToolBar.CleanUpLockedImages();
	m_wndToolBar.LoadBitmap(theApp.m_bHiColorIcons ? IDB_EXPLORER_24 : IDR_EXPLORER, 0, 0, TRUE /* Locked */);

	m_FileViewImages.DeleteImageList();

	UINT uiBmpId = theApp.m_bHiColorIcons ? IDB_FILE_VIEW_24 : IDB_FILE_VIEW;

	CBitmap bmp;
	if (!bmp.LoadBitmap(uiBmpId))
	{
		TRACE(_T("Can't load bitmap: %x\n"), uiBmpId);
		ASSERT(FALSE);
		return;
	}

	BITMAP bmpObj;
	bmp.GetBitmap(&bmpObj);

	UINT nFlags = ILC_MASK;

	nFlags |= (theApp.m_bHiColorIcons) ? ILC_COLOR24 : ILC_COLOR4;

	m_FileViewImages.Create(16, bmpObj.bmHeight, nFlags, 0, 0);
	m_FileViewImages.Add(&bmp, RGB(255, 0, 255));

	m_wndP2PmsgTreeCtrl.SetImageList(&m_FileViewImages, TVSIL_NORMAL);
}

///////////////////////////////////////////////////////////////////////////////
//  MFC message map
BEGIN_MESSAGE_MAP(CFileView, CDockablePane)
	  ON_WM_CREATE()
	  ON_WM_SIZE()
	  ON_WM_CONTEXTMENU()
    // Control notifications
    //ON_NOTIFY ( TVN_ITEMEXPANDED, 4, OnTvnItemExpanding)
    ON_NOTIFY ( TVN_ITEMEXPANDING, 4, OnTvnItemExpanding )
    ON_NOTIFY ( TVN_GETDISPINFO, 4, OnTvnGetDispInfo )
    // Application messages
    ON_MESSAGE(WM_APP_CONNECT_SQLSERVER,OnConnectSQLserver)
    ON_MESSAGE(WM_APP_DISCONNECT_SQLSERVER,OnDisconnectSQLserver)

	ON_COMMAND(ID_PROPERTIES, OnProperties)
	ON_COMMAND(ID_OPEN, OnFileOpen)
	ON_COMMAND(ID_OPEN_WITH, OnFileOpenWith)
	ON_COMMAND(ID_DUMMY_COMPILE, OnDummyCompile)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
	ON_WM_PAINT()
	ON_WM_SETFOCUS()
    ON_COMMAND(ID_TABLE_SELECTTOP1000ROWS, &CFileView::OnTableSelectTop1000rows)
    ON_UPDATE_COMMAND_UI(ID_TABLE_SELECTTOP1000ROWS, &CFileView::OnUpdateTableSelectTop1000rows)
    ON_COMMAND(ID_VIEW_SELECTTOP1000ROWS, &CFileView::OnViewSelectTop1000rows)
    ON_COMMAND(ID_ITEM_REFRESH, &CFileView::OnItemRefresh)
    ON_WM_NOTIFYFORMAT()
END_MESSAGE_MAP()

///////////////////////////////////////////////////////////////////////
//  Application defined messages

//
//  WM_APP_CONNECT_SQLSERVER application  notification
//
//  Parameters:  WPARAM wParam
//               Spare
//
//               LPARAM lParam
//               Spare
LRESULT
CFileView::OnConnectSQLserver ( WPARAM wParam, LPARAM lParam )
{
    // Request version
    // NOTES: Asynchronously processed and triggers subsequent explorer update
    P2PeerMsgSP spMsgSQL = new P2PeerMsg ( GetP2PaddrHub(), _T("AKAssms")
                                         , MSG_SQLselect
                                         , (void *)0, 0 );
    LPCTSTR lpszSQLstmt = _T("SELECT SERVERPROPERTY('productversion') as ProductVersion");
    spMsgSQL -> r_datn().AddField ("SQLstmt"
                                  , DataBSTR16(lpszSQLstmt) );
    LPCTSTR lpszMsgReply = MSG_SQLselectServerProperty;
    spMsgSQL -> r_datn().AddField ("MsgReply"
                                  , DataBSTR16(lpszMsgReply) );
    AssignOwnership ( spMsgSQL );
    PostP2PeerMsg   ( spMsgSQL.Dereference() );

    // Drop existing contents
    ClearViewContents ( );
    RefreshView ( );

    // Tidy up and 
    return TRUE;
}

//
//  WM_APP_DISCONNECT_SQLSERVER application notification
//
//  Parameters:  WPARAM wParam
//               Spare
//
//               LPARAM lParam
//               Spare
LRESULT
CFileView::OnDisconnectSQLserver ( WPARAM wParam, LPARAM lParam )
{

    // Tidy up and 
    RefreshView ( );
    return TRUE;
}

//
//  TVN_ITEMEXPANDING notification
//  NOTES: Handled AFTER equivalent child notification.  Hence item
//         will have expanded before item queried for content
//
void
CFileView::OnTvnItemExpanding ( NMHDR *pNMHDR, LRESULT *pResult )
{
    // Expanding state only or interest
    LPNMTREEVIEW  pNMTreeView =  reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
   *pResult = FALSE;
    if ( pNMTreeView->action != TVE_EXPAND )
      return;                          // Only query upon expansion
    TVITEM       *pTVITEM     = &pNMTreeView -> itemNew;
    P2Pos       posParent     =  pTVITEM -> lParam;
    HTREEITEM     hItemParent =  pTVITEM -> hItem;

    P2PmsgMgr       *pP2PmsgMgr  = theApp.GetP2PmsgMgr();

    // P2PmsgNode
    if ( pP2PmsgMgr->IsNode(posParent) )
    {
      P3PmsgNode   oNode       = m_wndP2PmsgTreeCtrl.GetItemNode(hItemParent).r_Object();
      P3PmsgObject oObjectNode = oNode.r_Object();
      P3PmsgAttr   oAttr       = oNode.r_Attr().r_Object();

      if ( oAttr.Exists(_T("$Databases"))                  &&
           oAttr.SelectItem(_T("$Databases")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$Databases")).c_int() = 91;
        QueryDatabases ( oNode );
      }
      else if ( oAttr.Exists(_T("$Columns"))                  &&
                oAttr.SelectItem(_T("$Columns")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$Columns")).c_int() = 1;
        QueryColumns ( oNode );
      }
      else if ( oAttr.Exists(_T("$VColumns"))                  &&
                oAttr.SelectItem(_T("$VColumns")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$VColumns")).c_int() = 1;
        QueryVColumns ( oNode );
      }
      else if ( oAttr.Exists(_T("$StoredProcs"))                  &&
                oAttr.SelectItem(_T("$StoredProcs")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$StoredProcs")).c_int() = 91;
        QueryStoredProcs ( oNode );
      }
      else if ( oAttr.Exists(_T("$Functions"))                  &&
                oAttr.SelectItem(_T("$Functions")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$Functions")).c_int() = 91;
        QueryFunctions ( oNode );
      }
      else if ( oAttr.Exists(_T("$Table"))                  &&
                oAttr.SelectItem(_T("$Table")).c_int() == 0    )
      {
        oAttr.SelectItem (_T("$Table")).c_int() = 91;
        QueryTable ( oNode );
      }
      else if ( oAttr.Exists(_T("$Tables"))                  &&
                oAttr.SelectItem(_T("$Tables")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$Tables")).c_int() = 91;
        QueryTables ( oNode );
      }
      else if ( oAttr.Exists(_T("$Views"))                  &&
                oAttr.SelectItem(_T("$Views")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$Views")).c_int() = 1;
        QueryViews ( oNode );
      }
      else if ( oAttr.Exists(_T("$View"))                  &&
                oAttr.SelectItem(_T("$View")).c_int() == 0    )
      {
        oAttr.SelectItem(_T("$View")).c_int() = 1;
        QueryView ( oNode );
      }
    }
}

//
//  TVN_GETDISPINFO notification
//  NOTES: Handled AFTER equivalent child notification.  Hence control
//         will have set default values prior to this handler
//
void
CFileView::OnTvnGetDispInfo ( NMHDR *pNMHDR, LRESULT *pResult )
{
    // Locals
    LPNMTVDISPINFO   pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    TVITEM          *pTVITEM     = &pTVDispInfo -> item;
    HTREEITEM        hItem       =  pTVDispInfo -> item.hItem;
    P2Pos          posP2Pobject  =  pTVDispInfo -> item.lParam;
    P2PmsgMgr       *pP2PmsgMgr  = theApp.GetP2PmsgMgr();
    int              iImage      = 4;
    int              iImageSelected = 0;
    int              cChildren   = pTVITEM->cChildren;

    // P2PmsgNode
    if ( pP2PmsgMgr->IsNode(posP2Pobject)  )
    {
      P3PmsgNode   oNode       = m_wndP2PmsgTreeCtrl.GetItemNode(hItem).r_Object();
      P3PmsgObject oObjectNode = m_wndP2PmsgTreeCtrl.GetItemNode(hItem).r_Object();
      P3PmsgAttr   oAttr       = m_wndP2PmsgTreeCtrl.GetItemAttr(hItem).r_Object();
      if ( oAttr.Exists(_T("$Columns")) )
      {
        if ( oAttr.SelectItem(_T("$Columns")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$VColumns")) )
      {
        if ( oAttr.SelectItem(_T("$VColumns")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$Table")) )
      {
        if ( oAttr.SelectItem(_T("$Table")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$Tables")) )
      {
        if ( oAttr.SelectItem(_T("$Tables")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$Views")) )
      {
        if ( oAttr.SelectItem(_T("$Views")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$View")) )
      {
        if ( oAttr.SelectItem(_T("$View")).c_int() == 0 )
          cChildren = 1;
      }
      else if ( oAttr.Exists(_T("$Database")) )
      {
        oAttr.SelectItem(_T("$Database")).c_int() = 91;
        iImage         = 3;
        iImageSelected = 3;
      }
      else if ( oAttr.Exists(_T("$Databases")) )
      {
        if ( oAttr.SelectItem(_T("$Databases")).c_int() == 0 )
          cChildren = 1;
      }
      else if (  oAttr.Exists(_T("$StoredProcs")) )
      {
        if ( oAttr.SelectItem(_T("$StoredProcs")).c_int() == 0 )
          cChildren = 1;
      }
      else if (  oAttr.Exists(_T("$Functions")) )
      {
        if ( oAttr.SelectItem(_T("$Functions")).c_int() == 0 )
          cChildren = 1;
      }
    }

    // P2PmsgField
    else if ( pP2PmsgMgr->IsField(posP2Pobject) )
    {
      iImage = 1;
    }

    // Tidy up, and
    if ( (pTVITEM->mask&TVIF_IMAGE) == TVIF_IMAGE )
      pTVITEM -> iImage = iImage;
    if ( (pTVITEM->mask&TVIF_SELECTEDIMAGE) == TVIF_SELECTEDIMAGE )
      pTVITEM -> iSelectedImage = iImageSelected;
    if ( (pTVITEM->mask&TVIF_CHILDREN) == TVIF_CHILDREN )
      pTVITEM -> cChildren = cChildren;
    *pResult = TRUE;
}

//
//  ID_TABLESELECTTOP1000ROWS handlers
//
void
CFileView::OnTableSelectTop1000rows()
{
    // Problematic
    try
    {
      // Identify selected table
      HTREEITEM hTreeItem = m_wndP2PmsgTreeCtrl.GetSelectedItem ( );
      if ( hTreeItem == NULL )
        return;
      P3PmsgNode oTable = m_wndP2PmsgTreeCtrl.GetItemNode(hTreeItem).r_Object();
      P3PmsgAttr oAttr  = m_wndP2PmsgTreeCtrl.GetItemAttr(hTreeItem).r_Object();
      if ( !oAttr.Exists(_T("$Table")) )
        return;
      s_bSelectTop1000Rows = true;
      if ( oTable.GetCount() <= 0 )
        QueryTable ( oTable );
      if ( oTable.SelectNode(_T("Columns")).GetCount() <= 0 )
      {
        QueryColumns ( oTable.SelectNode(_T("Columns")) );
        return;
      }

      // Application level usually responsible for new document creation
      P2Pos nPosTable = oTable.GetP2Pos();
      theApp.PostThreadMessage ( WM_APP_TABLE_TOP_1000_ROWS, nPosTable, 0 );
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel
    s_bSelectTop1000Rows = false;
}
void
CFileView::OnUpdateTableSelectTop1000rows(CCmdUI *pCmdUI)
{
    // TODO: Add your command update UI handler code here
}

//
//  ID_VIEWSELECTTOP1000ROWS handlers
//
void
CFileView::OnViewSelectTop1000rows()
{
    // Problematic
    try
    {
      // Identify selected table
      HTREEITEM hTreeItem = m_wndP2PmsgTreeCtrl.GetSelectedItem ( );
      if ( hTreeItem == NULL )
        return;
      P3PmsgNode oView = m_wndP2PmsgTreeCtrl.GetItemNode(hTreeItem).r_Object();
      P3PmsgAttr oAttr = m_wndP2PmsgTreeCtrl.GetItemAttr(hTreeItem).r_Object();
      if ( !oAttr.Exists(_T("$View")) )
        return;
      s_bSelectTop1000Rows = true;
      if ( oView.GetCount() <= 0 )
        QueryView ( oView );
      if ( oView.SelectNode(_T("Columns")).GetCount() <= 0 )
      {
        QueryVColumns ( oView.SelectNode(_T("Columns")) );
        return;
      }

      // Application level usually responsible for new document creation
      P2Pos nPosView = oView.GetP2Pos();
      theApp.PostThreadMessage ( WM_APP_VIEW_TOP_1000_ROWS, nPosView, 0 );
      return;
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel
    s_bSelectTop1000Rows = false;
}

//
//  ID_ITEM_REFRESH handler
//  NOTES: Refreshes subordinate contents of tree
//
void
CFileView::OnItemRefresh ( )
{
    // Problematic
    try
    {
      // Identify selected table
      HTREEITEM hTreeItem = m_wndP2PmsgTreeCtrl.GetSelectedItem ( );
      if ( hTreeItem == NULL )
        return;
      P3PmsgNode oNode = m_wndP2PmsgTreeCtrl.GetItemNode(hTreeItem).r_Object();
      P3PmsgAttr oAttr = oNode.r_Attr().r_Object();

      if ( oAttr.Exists(_T("$Databases")) )
      {
        oAttr.SelectItem(_T("$Databases")).c_int() = 0;
        oNode.Truncate  ( );
        QueryDatabases  ( oNode );
      }
      else if ( oAttr.Exists(_T("$Columns")) )
      {
        oAttr.SelectItem(_T("$Columns")).c_int() = 0;
        oNode.Truncate  ( );
        QueryColumns    ( oNode );
      }
      else if ( oAttr.Exists(_T("$VColumns")) )
      {
        oAttr.SelectItem(_T("$VColumns")).c_int() = 0;
        oNode.Truncate  ( );
        QueryVColumns   ( oNode );
      }
      else if (  oAttr.Exists(_T("$StoredProcs")) )
      {
        oAttr.SelectItem(_T("$StoredProcs")).c_int() = 0;
        oNode.Truncate  ( );
        QueryStoredProcs( oNode );
      }
      else if (  oAttr.Exists(_T("$Functions")) )
      {
        oAttr.SelectItem(_T("$Functions")).c_int() = 0;
        oNode.Truncate  ( );
        QueryFunctions ( oNode );
      }
      else if ( oAttr.Exists(_T("$Table")) )
      {
        oAttr.SelectItem(_T("$Table")).c_int() = 0;
        oNode.Truncate  ( );
        QueryTable ( oNode );
      }
      else if ( oAttr.Exists(_T("$Tables")) )
      {
        oAttr.SelectItem(_T("$Tables")).c_int() = 0;
        oNode.Truncate  ( );
        QueryTables ( oNode );
      }
      else if ( oAttr.Exists(_T("$Views")) )
      {
        oAttr.SelectItem(_T("$Views")).c_int() = 0;
        oNode.Truncate  ( );
        QueryViews ( oNode );
      }
      else if ( oAttr.Exists(_T("$View")) )
      {
        oAttr.SelectItem(_T("$View")).c_int() = 0;
        oNode.Truncate  ( );
        QueryView ( oNode );
      }
    }

    // Exceptions
    catch_pP2Pevent_Cancel
    catch_pCException_Cancel
    catch_ALL_Cancel
}

UINT CFileView::OnNotifyFormat(CWnd *pWnd, UINT nCommand)
{
    // TODO: Add your message handler code here and/or call default

    return __super::OnNotifyFormat(pWnd, nCommand);
}
