You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
13250 lines
382 KiB
13250 lines
382 KiB
// AMCView.cpp : implementation of the CAMCView class
|
|
//
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
//
|
|
// File: amcview.cpp
|
|
//
|
|
// Contents: Base view implementation for all console views
|
|
// Also include splitter window implementation (Horizontal Splitter)
|
|
//
|
|
// History: 01-Jan-96 TRomano Created
|
|
// 16-Jul-96 WayneSc Added code to switch views and split them
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// NOTE:
|
|
// MMC starting from version 1.1 had a code which allowed to copy the view
|
|
// settings from one view to another and thus the created view would look
|
|
// the same. AMCDoc was used as temporary storage for those settings.
|
|
// But the code was NEVER used; hence was not tested and not up-to-date.
|
|
// Switching to XML persistence would require essential changes to that code,
|
|
// and at this time we cannot afford using it.
|
|
// If in the future we decide to support the feature, someone needs to look at
|
|
// MMC 1.2 sources and bring the code back. Today the code is removed from
|
|
// active sources.
|
|
// audriusz. 3/29/2000
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "AMC.h"
|
|
#include "Mainfrm.h"
|
|
#include "HtmlHelp.h"
|
|
|
|
#include "websnk.h"
|
|
#include "WebCtrl.h" // AMC Private implementation of the web view control
|
|
#include "CClvCtl.h" // List view control
|
|
#include "ocxview.h"
|
|
#include "histlist.h" // history list
|
|
|
|
#include "AMCDoc.h" // AMC Console Document
|
|
#include "AMCView.h"
|
|
#include "childfrm.h"
|
|
|
|
#include "TreeCtrl.h" // AMC Implementation of the Tree Control
|
|
#include "TaskHost.h"
|
|
|
|
#include "util.h" // GUIDFromString, GUIDToString
|
|
#include "AMCPriv.h"
|
|
#include "guidhelp.h" // ExtractObjectTypeGUID
|
|
#include "amcmsgid.h"
|
|
#include "cclvctl.h"
|
|
#include "vwtrack.h"
|
|
#include "cmenuinfo.h"
|
|
|
|
#ifdef IMPLEMENT_LIST_SAVE // See nodemgr.idl (t-dmarm)
|
|
#include "svfildlg.h" // Save File Dialog
|
|
#endif
|
|
|
|
#include "macros.h"
|
|
#include <mapi.h>
|
|
#include <mbstring.h> // for _mbslen
|
|
|
|
#include "favorite.h"
|
|
#include "favui.h"
|
|
|
|
#include "ftab.h"
|
|
|
|
#include "toolbar.h"
|
|
#include "menubtns.h" // UpdateFavorites menu.
|
|
#include "stdbar.h" // Standard toolbar.
|
|
#include "variant.h"
|
|
#include "rsltitem.h"
|
|
#include "scriptevents.h" // for IMenuItemEvents
|
|
|
|
extern "C" UINT dbg_count = 0;
|
|
|
|
enum
|
|
{
|
|
ITEM_IS_PARENT_OF_ROOT,
|
|
ITEM_NOT_IN_VIEW,
|
|
ITEM_IS_IN_VIEW,
|
|
};
|
|
|
|
enum EIndex
|
|
{
|
|
INDEX_INVALID = -1,
|
|
INDEX_BACKGROUND = -2,
|
|
INDEX_MULTISELECTION = -3,
|
|
INDEX_OCXPANE = -4,
|
|
INDEX_WEBPANE = -5,
|
|
};
|
|
|
|
enum ScopeFolderItems
|
|
{
|
|
SFI_TREE_TAB = 1,
|
|
SFI_FAVORITES_TAB = 2
|
|
};
|
|
|
|
|
|
const UINT CAMCView::m_nShowWebContextMenuMsg = ::RegisterWindowMessage (_T("CAMCView::ShowWebContextMenu"));
|
|
const UINT CAMCView::m_nProcessMultiSelectionChangesMsg = ::RegisterWindowMessage (_T("CAMCView::OnProcessMultiSelectionChanges"));
|
|
const UINT CAMCView::m_nJiggleListViewFocusMsg = ::RegisterWindowMessage (_T("CAMCView::JiggleListViewFocus"));
|
|
const UINT CAMCView::m_nDeferRecalcLayoutMsg = ::RegisterWindowMessage (_T("CAMCView::DeferRecalcLayout"));
|
|
|
|
|
|
void CALLBACK TrackerCallback(TRACKER_INFO& info, bool bAcceptChange, bool bSyncLayout);
|
|
void GetFullPath(CAMCTreeView &ctc, HTREEITEM hti, CString &strPath);
|
|
BOOL PtInWindow(CWnd* pWnd, CPoint pt);
|
|
|
|
|
|
#ifdef DBG
|
|
CTraceTag tagLayout (_T("CAMCView"), _T("Layout"));
|
|
CTraceTag tagSplitterTracking (_T("CAMCView"), _T("Splitter tracking"));
|
|
CTraceTag tagListSelection (_T("Result list"), _T("Selection"));
|
|
CTraceTag tagViewActivation (_T("View Activation"), _T("View Activation"));
|
|
#endif
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScNotifySelect
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScNotifySelect (
|
|
INodeCallback* pCallback,
|
|
HNODE hNode,
|
|
bool fMultiSelect,
|
|
bool fSelect,
|
|
SELECTIONINFO* pSelInfo)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScNotifySelect"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pCallback);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// pSelInfo can be NULL only for multi-select.
|
|
if (!pSelInfo && !fMultiSelect)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
#ifdef DBG
|
|
Trace (tagListSelection, _T("%s (fSelect=%s, pwnd=0x%08x)"),
|
|
(fMultiSelect) ? _T("NCLBK_MULTI_SELECT") : _T("NCLBK_SELECT"),
|
|
(fSelect) ? _T("true") : _T("false"),
|
|
static_cast<CWnd *>(this));
|
|
#endif
|
|
|
|
// we want this error (not a failure to broadcast the event) to be returned,
|
|
// so cache it and assign before return
|
|
SC sc_notify = (pCallback->Notify (hNode, fMultiSelect ? NCLBK_MULTI_SELECT :NCLBK_SELECT,
|
|
fSelect, reinterpret_cast<LPARAM>(pSelInfo)));
|
|
|
|
// fire event whenever the selection changes, but not if
|
|
// its a background hit or loss of focus
|
|
if(fMultiSelect ||
|
|
(pSelInfo->m_bBackground == FALSE && (fSelect == TRUE || pSelInfo->m_bDueToFocusChange == FALSE)))
|
|
{
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnResultSelectionChange, this);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
|
|
sc = sc_notify;
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* GetAMCView
|
|
*
|
|
* Returns the CAMCView window for any child of CChildFrame.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CAMCView* GetAMCView (CWnd* pwnd)
|
|
{
|
|
/*
|
|
* get the input window's parent frame window
|
|
*/
|
|
CWnd* pFrame = pwnd->GetParentFrame();
|
|
|
|
/*
|
|
* if we couldn't find a parent frame, or that parent frame isn't
|
|
* of type CChildFrame, fail
|
|
*/
|
|
if ((pFrame == NULL) || !pFrame->IsKindOf (RUNTIME_CLASS (CChildFrame)))
|
|
return (NULL);
|
|
|
|
/*
|
|
* get the first view of the frame window
|
|
*/
|
|
CWnd* pView = pFrame->GetDlgItem (AFX_IDW_PANE_FIRST);
|
|
|
|
/*
|
|
* if we can't find a window with the right ID, or the one we find
|
|
* isn't of type CAMCView, fail
|
|
*/
|
|
if ((pView == NULL) || !pView->IsKindOf (RUNTIME_CLASS (CAMCView)))
|
|
return (NULL);
|
|
|
|
return (dynamic_cast<CAMCView*>(pView));
|
|
}
|
|
|
|
|
|
//############################################################################
|
|
//############################################################################
|
|
//
|
|
// Implementation of class CMMCView
|
|
//
|
|
//############################################################################
|
|
//############################################################################
|
|
/*+-------------------------------------------------------------------------*
|
|
* class CMMCView
|
|
*
|
|
*
|
|
* PURPOSE: The COM 0bject that exposes the View interface.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
class CMMCView :
|
|
public CTiedComObject<CAMCView>,
|
|
public CMMCIDispatchImpl<View>
|
|
{
|
|
typedef CAMCView CMyTiedObject;
|
|
|
|
public:
|
|
BEGIN_MMC_COM_MAP(CMMCView)
|
|
END_MMC_COM_MAP()
|
|
|
|
public:
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// Item and item collection related methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
|
|
MMC_METHOD1(get_ActiveScopeNode, PPNODE);
|
|
MMC_METHOD1(put_ActiveScopeNode, PNODE);
|
|
MMC_METHOD1(get_Selection, PPNODES);
|
|
MMC_METHOD1(get_ListItems, PPNODES);
|
|
MMC_METHOD2(SnapinScopeObject, VARIANT, PPDISPATCH);
|
|
MMC_METHOD1(SnapinSelectionObject, PPDISPATCH);
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
|
|
MMC_METHOD2(Is, PVIEW, VARIANT_BOOL *);
|
|
MMC_METHOD1(get_Document, PPDOCUMENT);
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// Selection changing methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
MMC_METHOD0(SelectAll);
|
|
MMC_METHOD1(Select, PNODE);
|
|
MMC_METHOD1(Deselect, PNODE);
|
|
MMC_METHOD2(IsSelected, PNODE, PBOOL);
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// Verb and selection related methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
MMC_METHOD1(DisplayScopeNodePropertySheet, VARIANT);
|
|
MMC_METHOD0(DisplaySelectionPropertySheet);
|
|
MMC_METHOD1(CopyScopeNode, VARIANT);
|
|
MMC_METHOD0(CopySelection);
|
|
MMC_METHOD1(DeleteScopeNode, VARIANT);
|
|
MMC_METHOD0(DeleteSelection);
|
|
MMC_METHOD2(RenameScopeNode, BSTR, VARIANT);
|
|
MMC_METHOD1(RenameSelectedItem, BSTR);
|
|
MMC_METHOD2(get_ScopeNodeContextMenu,VARIANT, PPCONTEXTMENU);
|
|
MMC_METHOD1(get_SelectionContextMenu,PPCONTEXTMENU);
|
|
MMC_METHOD1(RefreshScopeNode, VARIANT);
|
|
MMC_METHOD0(RefreshSelection);
|
|
MMC_METHOD1(ExecuteSelectionMenuItem, BSTR /*MenuItemPath*/);
|
|
MMC_METHOD2(ExecuteScopeNodeMenuItem, BSTR /*MenuItemPath*/, VARIANT /*varScopeNode = ActiveScopeNode */);
|
|
MMC_METHOD4(ExecuteShellCommand, BSTR /*Command*/, BSTR /*Directory*/, BSTR /*Parameters*/, BSTR /*WindowState*/);
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// Frame and view related methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
|
|
MMC_METHOD1(get_Frame, PPFRAME);
|
|
MMC_METHOD0(Close);
|
|
MMC_METHOD1(get_ScopeTreeVisible, PBOOL);
|
|
MMC_METHOD1(put_ScopeTreeVisible, BOOL);
|
|
MMC_METHOD0(Back);
|
|
MMC_METHOD0(Forward);
|
|
MMC_METHOD1(put_StatusBarText, BSTR);
|
|
MMC_METHOD1(get_Memento, PBSTR);
|
|
MMC_METHOD1(ViewMemento, BSTR);
|
|
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// List related methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
|
|
MMC_METHOD1(get_Columns, PPCOLUMNS);
|
|
MMC_METHOD3(get_CellContents, PNODE, long, PBSTR);
|
|
MMC_METHOD2(ExportList, BSTR, ExportListOptions);
|
|
MMC_METHOD1(get_ListViewMode, PLISTVIEWMODE);
|
|
MMC_METHOD1(put_ListViewMode, ListViewMode);
|
|
|
|
//#######################################################################
|
|
//#######################################################################
|
|
//
|
|
// ActiveX control related methods
|
|
//
|
|
//#######################################################################
|
|
//#######################################################################
|
|
MMC_METHOD1(get_ControlObject, PPDISPATCH);
|
|
|
|
};
|
|
|
|
|
|
/*
|
|
* WM_APPCOMMAND is only defined in winuser.h if _WIN32_WINNT >= 0x0500.
|
|
* We need these definitions, but can't use _WIN32_WINNT==0x0500 (yet).
|
|
*/
|
|
|
|
#ifndef WM_APPCOMMAND
|
|
#define WM_APPCOMMAND 0x0319
|
|
#define APPCOMMAND_BROWSER_BACKWARD 1
|
|
#define APPCOMMAND_BROWSER_FORWARD 2
|
|
#define APPCOMMAND_BROWSER_REFRESH 3
|
|
|
|
#define FAPPCOMMAND_MOUSE 0x8000
|
|
#define FAPPCOMMAND_KEY 0
|
|
#define FAPPCOMMAND_OEM 0x1000
|
|
#define FAPPCOMMAND_MASK 0xF000
|
|
|
|
#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
|
|
#endif // WM_APPCOMMAND
|
|
|
|
|
|
|
|
//############################################################################
|
|
//############################################################################
|
|
//
|
|
// Implementation of class CAMCView
|
|
//
|
|
//############################################################################
|
|
//############################################################################
|
|
IMPLEMENT_DYNCREATE(CAMCView, CView);
|
|
|
|
BEGIN_MESSAGE_MAP(CAMCView, CView)
|
|
//{{AFX_MSG_MAP(CAMCView)
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_CREATE()
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_WM_DESTROY()
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_SNAPINMANAGER, OnUpdateFileSnapinmanager)
|
|
ON_WM_SHOWWINDOW()
|
|
ON_COMMAND(ID_MMC_NEXT_PANE, OnNextPane)
|
|
ON_COMMAND(ID_MMC_PREV_PANE, OnPrevPane)
|
|
ON_WM_SETCURSOR()
|
|
ON_COMMAND(ID_MMC_CONTEXTHELP, OnContextHelp)
|
|
ON_COMMAND(ID_HELP_SNAPINHELP, OnSnapInHelp)
|
|
ON_COMMAND(ID_SNAPIN_ABOUT, OnSnapinAbout)
|
|
ON_COMMAND(ID_HELP_HELPTOPICS, OnHelpTopics)
|
|
ON_WM_SIZE()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_PALETTECHANGED()
|
|
ON_WM_QUERYNEWPALETTE()
|
|
ON_WM_SYSCOLORCHANGE()
|
|
ON_WM_DRAWCLIPBOARD()
|
|
ON_WM_SETTINGCHANGE()
|
|
ON_WM_MENUSELECT()
|
|
//}}AFX_MSG_MAP
|
|
|
|
// keep this outside the AFX_MSG_MAP markers so ClassWizard doesn't munge it
|
|
ON_COMMAND_RANGE(ID_MMC_CUT, ID_MMC_PRINT, OnVerbAccelKey)
|
|
|
|
// WARNING: If your message handler has void return use ON_MESSAGE_VOID !!
|
|
ON_MESSAGE(MMC_MSG_CONNECT_TO_CIC, OnConnectToCIC)
|
|
ON_MESSAGE(MMC_MSG_CONNECT_TO_TPLV, OnConnectToTPLV)
|
|
ON_MESSAGE(MMC_MSG_GET_ICON_INFO, OnGetIconInfoForSelectedNode)
|
|
ON_MESSAGE(WM_APPCOMMAND, OnAppCommand)
|
|
|
|
ON_REGISTERED_MESSAGE (m_nShowWebContextMenuMsg, OnShowWebContextMenu)
|
|
ON_REGISTERED_MESSAGE (m_nProcessMultiSelectionChangesMsg, OnProcessMultiSelectionChanges)
|
|
ON_REGISTERED_MESSAGE (m_nJiggleListViewFocusMsg, OnJiggleListViewFocus)
|
|
ON_REGISTERED_MESSAGE (m_nDeferRecalcLayoutMsg, OnDeferRecalcLayout)
|
|
|
|
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
|
|
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
|
|
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
|
|
|
|
ON_NOTIFY(FTN_TABCHANGED, IDC_ResultTabCtrl, OnChangedResultTab)
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAMCView construction/destruction
|
|
|
|
const CSize CAMCView::m_sizEdge (GetSystemMetrics (SM_CXEDGE),
|
|
GetSystemMetrics (SM_CYEDGE));
|
|
|
|
const int CAMCView::m_cxSplitter = 3;
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::OnMenuSelect
|
|
//
|
|
// Synopsis: Handles WM_MENUSELECT for Favorites menu.
|
|
//
|
|
// Arguments: [nItemID] - the resource id of menu item.
|
|
// [nFlags] - MF_* flags
|
|
//
|
|
// Returns: none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void CAMCView::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnMenuSelect"));
|
|
|
|
CMainFrame* pFrame = AMCGetMainWnd();
|
|
sc = ScCheckPointers(pFrame, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
// Pass onto the mainframe.
|
|
return pFrame->OnMenuSelect(nItemID, nFlags, hSysMenu);
|
|
}
|
|
|
|
|
|
CAMCView::CAMCView() :
|
|
m_pResultFolderTabView(new CFolderTabView(this)) // dynamically allocated for decoupling
|
|
{
|
|
TRACE_CONSTRUCTOR(CAMCView);
|
|
|
|
// Init pointer members to NULL
|
|
m_nViewID = 0;
|
|
m_pTreeCtrl = NULL;
|
|
m_pListCtrl = NULL;
|
|
m_pWebViewCtrl = NULL;
|
|
m_pViewExtensionCtrl = NULL;
|
|
m_pOCXHostView = NULL;
|
|
m_nSelectNestLevel = 0;
|
|
|
|
// if the view is a listview, then this member define what the view
|
|
// mode is for all snapins with that view.
|
|
|
|
m_nViewMode = LVS_REPORT; // REVIEW: Must we persist this - ravi
|
|
|
|
// REVIEW consider moving the above initialzation to the InitSplitter
|
|
// CommonConstruct
|
|
// NOTE moved code from InitSplitter into the contructor and deleted InitSplitter
|
|
|
|
// Default values for view. User can set these values with SetPaneInfo;
|
|
m_PaneInfo[ePane_ScopeTree].pView = NULL;
|
|
m_PaneInfo[ePane_ScopeTree].cx = -1;
|
|
m_PaneInfo[ePane_ScopeTree].cxMin = 50;
|
|
|
|
m_PaneInfo[ePane_Results].pView = NULL;
|
|
m_PaneInfo[ePane_Results].cx = -1;
|
|
m_PaneInfo[ePane_Results].cxMin = 50;
|
|
|
|
m_pTracker = NULL;
|
|
|
|
m_rectResultFrame = g_rectEmpty;
|
|
m_rectVSplitter = g_rectEmpty;
|
|
|
|
// m_fDontPersistOCX = FALSE;
|
|
|
|
// root node for the view
|
|
m_hMTNode = 0;
|
|
|
|
// Bug 157408: remove the "Type" column for static nodes
|
|
// m_columnWidth[0] = 90;
|
|
// m_columnWidth[1] = 50;
|
|
m_columnWidth[0] = 200;
|
|
m_columnWidth[1] = 0;
|
|
|
|
m_iFocusedLV = -1;
|
|
m_bLVItemSelected = FALSE;
|
|
m_DefaultLVStyle = 0;
|
|
|
|
m_bProcessMultiSelectionChanges = false;
|
|
|
|
m_htiCut = NULL;
|
|
m_nReleaseViews = 0;
|
|
m_htiStartingSelectedNode = NULL;
|
|
m_bLastSelWasMultiSel = false;
|
|
m_eCurrentActivePane = eActivePaneNone;
|
|
|
|
m_fRootedAtNonPersistedDynamicNode = false;
|
|
m_fSnapinDisplayedHelp = false;
|
|
m_fActivatingSpecialResultPane = false;
|
|
m_bDirty = false;
|
|
m_fViewExtended = false;
|
|
|
|
m_pHistoryList = new CHistoryList (this);
|
|
m_ListPadNode = NULL;
|
|
|
|
/*
|
|
* Bug 103604: Mark this as an author mode view if it was created in
|
|
* author mode. If we're loading a user mode console file, it will
|
|
* have author mode views and possibly some views that were created
|
|
* in user mode, but this code will mark all of the views as non-author
|
|
* mode views. CAMCView::Persist will fix that.
|
|
*/
|
|
CAMCApp* pApp = AMCGetApp();
|
|
if (pApp != NULL)
|
|
m_bAuthorModeView = (pApp->GetMode() == eMode_Author);
|
|
else
|
|
m_bAuthorModeView = true;
|
|
}
|
|
|
|
CAMCView::~CAMCView()
|
|
{
|
|
TRACE_DESTRUCTOR(CAMCView);
|
|
|
|
// Delete all pointer members. (C++ checks to see if they are NULL before deleting)
|
|
// The standard ~CWnd destructor will call DestroyWindow()
|
|
|
|
// REVIEW set the pointers to NULL after deleting them
|
|
// Note Done
|
|
|
|
// CViews "delete this" in PostNcDestroy, no need to delete here
|
|
//delete m_pTreeCtrl;
|
|
m_pTreeCtrl = NULL;
|
|
|
|
m_pListCtrl->Release();
|
|
m_pListCtrl = NULL;
|
|
|
|
/*
|
|
* DONT_DELETE_VIEWS
|
|
*
|
|
* CViews "delete this" in PostNcDestroy, no need to delete
|
|
* here if the web view control is derived from CView. See
|
|
* AttachWebViewAsResultPane (search for "DONT_DELETE_VIEWS")
|
|
* for the ASSERTs that make sure this code is right.
|
|
*/
|
|
//delete m_pWebViewCtrl;
|
|
//m_pWebViewCtrl = NULL;
|
|
|
|
/*
|
|
* CViews "delete this" in PostNcDestroy, no need to delete here
|
|
*/
|
|
m_pOCXHostView = NULL;
|
|
m_pResultFolderTabView = NULL;
|
|
|
|
if (m_ViewData.m_spNodeManager != NULL)
|
|
m_ViewData.m_spNodeManager->CleanupViewData(
|
|
reinterpret_cast<LONG_PTR>(&m_ViewData));
|
|
|
|
ASSERT (m_ViewData.m_pMultiSelection == NULL);
|
|
|
|
delete m_pHistoryList;
|
|
|
|
// First destroy the IControlbarsCache as snapins call CAMCViewToolbars
|
|
// to cleanup toolbars before the CAMCViewToolbars itself gets destroyed.
|
|
m_ViewData.m_spControlbarsCache = NULL;
|
|
|
|
// (UI cleanup) release toolbars related to this view.
|
|
m_spAMCViewToolbars = NULL;
|
|
m_spStandardToolbar = std::auto_ptr<CStandardToolbar>(NULL);
|
|
|
|
//m_spStandardToolbar = NULL;
|
|
//m_spAMCViewToolbars = NULL;
|
|
}
|
|
|
|
|
|
|
|
//############################################################################
|
|
//############################################################################
|
|
//
|
|
// CAMCView: Object model methods - View Interface
|
|
//
|
|
//############################################################################
|
|
//############################################################################
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetOptionalScopeNodeParameter
|
|
*
|
|
* PURPOSE: Helper function - returns the scope node pointer, if supplied
|
|
* in the variant, or the Active Scope node pointer, if not
|
|
* supplied.
|
|
*
|
|
* PARAMETERS:
|
|
* VARIANT varScopeNode : The parameter, which can be empty. NOTE: This is a
|
|
* reference, so we don't need to call VariantClear on it.
|
|
* PPNODE ppNode :
|
|
* bool& bMatchedGivenNode: If true the returned ppNode corresponds to the given node
|
|
* applies only if given node is in bookmark format.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScGetOptionalScopeNodeParameter(VARIANT &varScopeNode, PPNODE ppNode, bool& bMatchedGivenNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetOptionalScopeNodeParameter"));
|
|
|
|
sc = ScCheckPointers(ppNode);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// init the out parameter
|
|
*ppNode = NULL;
|
|
bMatchedGivenNode = true;
|
|
|
|
// supply the optional parameter if it is missing
|
|
if(IsOptionalParamMissing(varScopeNode))
|
|
{
|
|
sc = Scget_ActiveScopeNode(ppNode);
|
|
return sc;
|
|
}
|
|
|
|
VARIANT* pvarTemp = ConvertByRefVariantToByValue(&varScopeNode);
|
|
sc = ScCheckPointers(pvarTemp,E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
bool bByReference = ( VT_BYREF == (V_VT(pvarTemp) & VT_BYREF) ); // value passed by reference
|
|
UINT uiVarType = (V_VT(pvarTemp) & VT_TYPEMASK); // get variable type (strip flags)
|
|
|
|
|
|
if(uiVarType == VT_DISPATCH) // do we have a dispatch interface.
|
|
{
|
|
IDispatchPtr spDispatch = NULL;
|
|
|
|
if(bByReference) // a reference, use ppDispVal
|
|
spDispatch = *(pvarTemp->ppdispVal);
|
|
else
|
|
spDispatch = pvarTemp->pdispVal; // passed by value, use pDispVal
|
|
|
|
sc = ScCheckPointers(spDispatch.GetInterfacePtr());
|
|
if(sc)
|
|
return sc;
|
|
|
|
// at this point spDispatch is correctly set. QI for Node from it.
|
|
|
|
NodePtr spNode = spDispatch;
|
|
if(spNode == NULL)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
*ppNode = spNode.Detach(); // keep the reference.
|
|
}
|
|
else if(uiVarType == VT_BSTR)
|
|
{
|
|
// Name: get string properly ( see if it's a reference )
|
|
LPOLESTR lpstrBookmark = bByReference ? *(pvarTemp->pbstrVal) : pvarTemp->bstrVal;
|
|
|
|
// get the bookmark
|
|
CBookmark bm;
|
|
sc = bm.ScLoadFromString(lpstrBookmark);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if(!bm.IsValid())
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
NodePtr spNode;
|
|
|
|
// Need a bool variable to find if exact match is found or not, cannot return
|
|
// MMC specific error codes from nodemgr to conui.
|
|
bMatchedGivenNode = false;
|
|
sc = pScopeTree->GetNodeFromBookmark( bm, this, ppNode, bMatchedGivenNode);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
else
|
|
return (sc = E_INVALIDARG);
|
|
|
|
|
|
// we should have a valid node at this point.
|
|
if(!ppNode)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_ActiveScopeNode
|
|
*
|
|
* PURPOSE: Implements get method for Wiew.ActiveScopeNode property
|
|
*
|
|
* PARAMETERS:
|
|
* PPNODE ppNode - resulting node
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_ActiveScopeNode( PPNODE ppNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ActiveScopeNode"));
|
|
|
|
// checking parameters
|
|
sc= ScCheckPointers(ppNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get selected node
|
|
HNODE hNode = GetSelectedNode();
|
|
sc= ScCheckPointers((LPVOID)hNode, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get node callback
|
|
INodeCallback* pNodeCallBack = GetNodeCallback();
|
|
sc= ScCheckPointers(pNodeCallBack, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// now get an HMTNODE
|
|
HMTNODE hmtNode = NULL;
|
|
sc = pNodeCallBack->GetMTNode(hNode, &hmtNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// geting pointer to scope tree
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc= ScCheckPointers(pScopeTree, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// map to PNODE
|
|
sc = pScopeTree->GetMMCNode(hmtNode, ppNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CExpandSyncModeLock
|
|
*
|
|
* PURPOSE: constructing the object of this class locks MMC in syncronous
|
|
* expansion mode (node expansion will send MMCN_EXPANDSYNC to snapin)
|
|
* destructor of the class restores the previous mode
|
|
*
|
|
\***************************************************************************/
|
|
class CExpandSyncModeLock
|
|
{
|
|
IScopeTreePtr m_spScopeTree;
|
|
bool m_fSyncExpandWasRequired;
|
|
public:
|
|
CExpandSyncModeLock( IScopeTree *pScopeTree ) : m_spScopeTree(pScopeTree),
|
|
m_fSyncExpandWasRequired(false)
|
|
{
|
|
ASSERT( m_spScopeTree != NULL );
|
|
if ( m_spScopeTree )
|
|
{
|
|
m_fSyncExpandWasRequired = (m_spScopeTree->IsSynchronousExpansionRequired() == S_OK);
|
|
m_spScopeTree->RequireSynchronousExpansion (true);
|
|
}
|
|
}
|
|
|
|
~CExpandSyncModeLock()
|
|
{
|
|
if ( m_spScopeTree )
|
|
{
|
|
m_spScopeTree->RequireSynchronousExpansion ( m_fSyncExpandWasRequired );
|
|
}
|
|
}
|
|
};
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scset_ActiveScopeNode
|
|
*
|
|
* PURPOSE: Implements set method for Wiew.ActiveScopeNode property
|
|
*
|
|
* PARAMETERS:
|
|
* PNODE pNode - node to activate
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scput_ActiveScopeNode( PNODE pNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_ActiveScopeNode"));
|
|
|
|
// checking parameters
|
|
sc= ScCheckPointers(pNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// geting pointer to scope tree
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc= ScCheckPointers(pScopeTree, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Converting PNODE to TNODEID
|
|
MTNODEID ID = 0;
|
|
sc = pScopeTree->GetNodeID(pNode, &ID);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// always require syncronous expansion for Object Model
|
|
// see bug #154694
|
|
CExpandSyncModeLock lock( pScopeTree );
|
|
|
|
// selecting the node
|
|
sc = ScSelectNode(ID);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::Scget_Selection
|
|
*
|
|
* PURPOSE: creates enumerator for Selected Nodes
|
|
*
|
|
* PARAMETERS:
|
|
* PPNODES ppNodes - resulting enumerator
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::Scget_Selection( PPNODES ppNodes )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_SelectedItems"));
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get enumerator from list control
|
|
sc = m_pListCtrl->Scget_SelectedItems(ppNodes);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::Scget_ListItems
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* PPNODES ppNodes - resulting enumerator
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::Scget_ListItems( PPNODES ppNodes )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ListItems"));
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get enumerator from list control
|
|
sc = m_pListCtrl->Scget_ListItems(ppNodes);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScSnapinScopeObject
|
|
//
|
|
// Synopsis: Get the IDispatch* from snapin for given ScopeNode object.
|
|
//
|
|
// Arguments: varScopeNode - Given ScopeNode object.
|
|
// ScopeNodeObject [out] - IDispatch for ScopeNode object.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSnapinScopeObject (VARIANT& varScopeNode, /*[out]*/PPDISPATCH ScopeNodeObject)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScSnapinScopeObject"));
|
|
sc = ScCheckPointers(ScopeNodeObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*ScopeNodeObject = NULL;
|
|
|
|
bool bMatchedGivenNode = false; // unused
|
|
NodePtr spNode = NULL;
|
|
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
|
|
if(sc)
|
|
return sc;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
|
|
sc = ScCheckPointers(spNode.GetInterfacePtr(), pNC, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = pNC->QueryCompDataDispatch(spNode, ScopeNodeObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScSnapinSelectionObject
|
|
//
|
|
// Synopsis: Get the IDispatch* from snapin for selected items in result pane.
|
|
//
|
|
// Arguments: SelectedObject [out] - IDispatch for Selected items object.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSnapinSelectionObject (PPDISPATCH SelectedObject)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScSnapinSelectionObject"));
|
|
sc = ScCheckPointers(SelectedObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*SelectedObject = NULL;
|
|
|
|
if (!HasList()) // not a list. Return error
|
|
return (sc = ScFromMMC(MMC_E_NOLIST));
|
|
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
sc = ScGetSelectedLVItem(lvData);
|
|
if (sc)
|
|
return sc;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
sc = ScCheckPointers(hNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
INodeCallback* pNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
sc = pNodeCallback->QueryComponentDispatch(hNode, lvData, SelectedObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScIs
|
|
*
|
|
* PURPOSE: compares two views if they are the same
|
|
*
|
|
* PARAMETERS:
|
|
* PVIEW pView - [in] another view
|
|
* VARIANT_BOOL * pbTheSame - [out] comparison result
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScIs (PVIEW pView, VARIANT_BOOL *pbTheSame)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScIs"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pView, pbTheSame);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*pbTheSame = CComPtr<View>(pView).IsEqualObject(m_spView)
|
|
? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScSelectAll
|
|
//
|
|
// Synopsis: Selects all items in the result pane
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSelectAll ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScSelectAll"));
|
|
|
|
if (! (GetListOptions() & RVTI_LIST_OPTIONS_MULTISELECT) )
|
|
return (sc = ScFromMMC(MMC_E_NO_MULTISELECT));
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// forward to list control
|
|
sc = m_pListCtrl->ScSelectAll();
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScSelect
|
|
*
|
|
* PURPOSE: selects item identified by node [implements View.Select()]
|
|
*
|
|
* PARAMETERS:
|
|
* PNODE pNode - node to select
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScSelect( PNODE pNode )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSelect"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// forward to list control
|
|
sc = m_pListCtrl->ScSelect( pNode );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScDeselect
|
|
*
|
|
* PURPOSE: deselects item identified by node [implements View.Deselect()]
|
|
*
|
|
* PARAMETERS:
|
|
* PNODE pNode - node to deselect
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScDeselect( PNODE pNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScDeselect"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// forward to list control
|
|
sc = m_pListCtrl->ScDeselect( pNode );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScIsSelected
|
|
*
|
|
* PURPOSE: checks the status of item identified by node [implements View.IsSelected]
|
|
*
|
|
* PARAMETERS:
|
|
* PNODE pNode - node to examine
|
|
* PBOOL pIsSelected - storage for result
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScIsSelected( PNODE pNode, PBOOL pIsSelected )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScIsSelected"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pNode, pIsSelected);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*pIsSelected = FALSE;
|
|
|
|
// check for list view control
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// forward to list control
|
|
sc = m_pListCtrl->ScIsSelected( pNode, pIsSelected );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScExecuteScopeItemVerb
|
|
//
|
|
// Synopsis: Get the context and pass it on to nodemgr to execute
|
|
// given verb.
|
|
//
|
|
// Arguments: [verb] - Verb to execute
|
|
// [varScopeNode] - Optional scope node (if not given,
|
|
// currently selected item will be used.)
|
|
// [bstrNewName] - valid for Rename else NULL.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScExecuteScopeItemVerb (MMC_CONSOLE_VERB verb, VARIANT& varScopeNode, BSTR bstrNewName)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScExecuteScopeItemVerb"));
|
|
|
|
NodePtr spNode = NULL;
|
|
bool bMatchedGivenNode = false;
|
|
// We should navigate to exact node to execute the verb.
|
|
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (! bMatchedGivenNode)
|
|
return (sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED));
|
|
|
|
HNODE hNode = NULL;
|
|
sc = ScGetHNodeFromPNode(spNode, hNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(spNode.GetInterfacePtr(), pNC);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = pNC->ExecuteScopeItemVerb(verb, hNode, bstrNewName);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScExecuteResultItemVerb
|
|
//
|
|
// Synopsis: Get the currently selected context and pass it on to
|
|
// nodemgr to execute given verb.
|
|
//
|
|
// Arguments: [verb] - Verb to execute
|
|
// [bstrNewName] - valid for Rename else NULL.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScExecuteResultItemVerb (MMC_CONSOLE_VERB verb, BSTR bstrNewName)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScExecuteResultItemVerb"));
|
|
|
|
if (!HasList()) // not a list. Return error
|
|
return (sc = ScFromMMC(MMC_E_NOLIST));
|
|
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
sc = ScGetSelectedLVItem(lvData);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (lvData == LVDATA_ERROR)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
sc = ScCheckPointers(hNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
INodeCallback* pNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
sc = pNodeCallback->ExecuteResultItemVerb( verb, hNode, lvData, bstrNewName);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScDisplayScopeNodePropertySheet
|
|
*
|
|
* PURPOSE: Displays the property sheet for a scope node.
|
|
*
|
|
* PARAMETERS:
|
|
* VARIANT varScopeNode :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScDisplayScopeNodePropertySheet(VARIANT& varScopeNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScDisplayPropertySheet"));
|
|
|
|
sc = ScExecuteScopeItemVerb(MMC_VERB_PROPERTIES, varScopeNode, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScDisplaySelectionPropertySheet
|
|
//
|
|
// Synopsis: Show the property sheet for selected result item(s).
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScDisplaySelectionPropertySheet ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScDisplaySelectionPropertySheet"));
|
|
|
|
sc = ScExecuteResultItemVerb(MMC_VERB_PROPERTIES, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScCopyScopeNode
|
|
//
|
|
// Synopsis: Copy the specified scope node (if given) or currently
|
|
// selected node to clipboard.
|
|
//
|
|
// Arguments: [varScopeNode] - given node.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScCopyScopeNode (VARIANT& varScopeNode)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScCopyScopeNode"));
|
|
|
|
sc = ScExecuteScopeItemVerb(MMC_VERB_COPY, varScopeNode, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScCopySelection
|
|
//
|
|
// Synopsis: Copy the selected result item(s) to clipboard.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScCopySelection ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScCopySelection"));
|
|
|
|
sc = ScExecuteResultItemVerb(MMC_VERB_COPY, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScDeleteScopeNode
|
|
//
|
|
// Synopsis: Deletes the specified scope node (if given) or currently
|
|
// selected node.
|
|
//
|
|
// Arguments: [varScopeNode] - node to delete
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScDeleteScopeNode (VARIANT& varScopeNode)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScDeleteScopeNode"));
|
|
|
|
sc = ScExecuteScopeItemVerb(MMC_VERB_DELETE, varScopeNode, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScDeleteSelection
|
|
//
|
|
// Synopsis: Deletes the selected item(s) in result pane.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScDeleteSelection ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScDeleteSelection"));
|
|
|
|
sc = ScExecuteResultItemVerb(MMC_VERB_DELETE, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScRenameScopeNode
|
|
//
|
|
// Synopsis: Rename the specified scope node (if given) or currently
|
|
// selected node with given new name.
|
|
//
|
|
// Arguments: [bstrNewName] - the new name
|
|
// [varScopeNode] - given node.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScRenameScopeNode (BSTR bstrNewName, VARIANT& varScopeNode)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScRenameScopeNode"));
|
|
|
|
sc = ScExecuteScopeItemVerb(MMC_VERB_RENAME, varScopeNode, bstrNewName);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScRenameSelectedItem
|
|
//
|
|
// Synopsis: Rename the selected result item with given new name.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScRenameSelectedItem (BSTR bstrNewName)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScRenameSelectedItem"));
|
|
|
|
sc = ScExecuteResultItemVerb(MMC_VERB_RENAME, bstrNewName);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScRefreshScopeNode
|
|
//
|
|
// Synopsis: Refresh the specified scope node (if given) or currently
|
|
// selected node.
|
|
//
|
|
// Arguments: [varScopeNode] - given node.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScRefreshScopeNode (VARIANT& varScopeNode)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScRefreshScopeNode"));
|
|
|
|
sc = ScExecuteScopeItemVerb(MMC_VERB_REFRESH, varScopeNode, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScRefreshSelection
|
|
//
|
|
// Synopsis: Refresh the selected result item(s).
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScRefreshSelection ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScRefreshSelection"));
|
|
|
|
sc = ScExecuteResultItemVerb(MMC_VERB_REFRESH, NULL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_ScopeNodeContextMenu
|
|
*
|
|
* PURPOSE: Creates a context menu for a scope node and returns it.
|
|
*
|
|
* PARAMETERS:
|
|
* VARIANT varScopeNode :
|
|
* PPCONTEXTMENU ppContextMenu :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_ScopeNodeContextMenu(VARIANT& varScopeNode, PPCONTEXTMENU ppContextMenu, bool bMatchGivenNode /* = false*/)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ContextMenu"));
|
|
|
|
NodePtr spNode;
|
|
// See if context menu for exactly the given node is asked for.
|
|
bool bMatchedGivenNode = false;
|
|
sc = ScGetOptionalScopeNodeParameter(varScopeNode, &spNode, bMatchedGivenNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if ( (bMatchGivenNode) && (!bMatchedGivenNode) )
|
|
return ScFromMMC(IDS_NODE_NOT_FOUND);
|
|
|
|
if(sc)
|
|
return sc;
|
|
|
|
INodeCallback* spNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers(spNode, ppContextMenu, spNodeCallback, GetTreeCtrl());
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
*ppContextMenu = NULL; // initialize output.
|
|
|
|
HNODE hNode = NULL;
|
|
sc = ScGetHNodeFromPNode(spNode, hNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// tell the node callback to add menu items for the scope node.
|
|
sc = spNodeCallback->CreateContextMenu(spNode, hNode, ppContextMenu);
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_SelectionContextMenu
|
|
*
|
|
* PURPOSE: Creates a context menu for the current selection and returns it.
|
|
*
|
|
* PARAMETERS:
|
|
* PPCONTEXTMENU ppContextMenu : [OUT]: The context menu object
|
|
*
|
|
* RETURNS:
|
|
* SC : error if no list exists, or there is nothing selected.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_SelectionContextMenu( PPCONTEXTMENU ppContextMenu)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_SelectionContextMenu"));
|
|
|
|
sc = ScCheckPointers(ppContextMenu);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (!HasListOrListPad()) // not a list. Return error
|
|
return (sc = ScFromMMC(MMC_E_NOLIST));
|
|
|
|
INodeCallback* pNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers(pNodeCallback);
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
CContextMenuInfo contextInfo; // the structure to pass to nodemgr
|
|
|
|
// common entries
|
|
contextInfo.m_pConsoleView = this;
|
|
|
|
// always use the temp verbs - cannot depend on what the active pane is
|
|
contextInfo.m_dwFlags = CMINFO_USE_TEMP_VERB;
|
|
|
|
int iIndex = -1;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
ASSERT(hNode != NULL);
|
|
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
if(0 == cSel)
|
|
{
|
|
// no items selected, bail
|
|
return (sc = ScFromMMC(MMC_E_NO_SELECTED_ITEMS));
|
|
}
|
|
else if(1 == cSel)
|
|
{
|
|
// single selection
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
iIndex = _GetLVSelectedItemData(&lvData);
|
|
ASSERT(iIndex != -1);
|
|
ASSERT(lvData != LVDATA_ERROR);
|
|
|
|
if (IsVirtualList())
|
|
{
|
|
// virtual list item in the result pane
|
|
contextInfo.m_eDataObjectType = CCT_RESULT;
|
|
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
|
|
contextInfo.m_bBackground = false;
|
|
contextInfo.m_bMultiSelect = false;
|
|
contextInfo.m_resultItemParam = iIndex;
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
}
|
|
else
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle (lvData);
|
|
if(!pri)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
if (pri->IsScopeItem())
|
|
{
|
|
// scope item in the result pane
|
|
contextInfo.m_eDataObjectType = CCT_SCOPE;
|
|
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
|
|
contextInfo.m_bBackground = FALSE;
|
|
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
|
|
contextInfo.m_resultItemParam = NULL;
|
|
contextInfo.m_bMultiSelect = FALSE;
|
|
contextInfo.m_bScopeAllowed = TRUE;
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
|
|
// change the scope node on which the menu is to be displayed
|
|
hNode = pri->GetScopeNode();
|
|
}
|
|
else
|
|
{
|
|
// single result item in the result pane
|
|
contextInfo.m_eDataObjectType = CCT_RESULT;
|
|
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
|
|
contextInfo.m_bBackground = false;
|
|
contextInfo.m_bMultiSelect = false;
|
|
contextInfo.m_resultItemParam = lvData;
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// multiselection
|
|
iIndex = INDEX_MULTISELECTION; // => MultiSelect
|
|
|
|
contextInfo.m_eDataObjectType = CCT_RESULT;
|
|
contextInfo.m_eContextMenuType = MMC_CONTEXT_MENU_DEFAULT;
|
|
contextInfo.m_bBackground = false;
|
|
contextInfo.m_bMultiSelect = true;
|
|
contextInfo.m_resultItemParam = LVDATA_MULTISELECT;
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
}
|
|
|
|
sc = pNodeCallback->CreateSelectionContextMenu(hNode, &contextInfo, ppContextMenu);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScExecuteMenuItem
|
|
*
|
|
* PURPOSE: Executes the specified context menu item on the specified context menu
|
|
*
|
|
* PARAMETERS:
|
|
* PCONTEXTMENU pContextMenu :
|
|
* BSTR MenuItemPath : Either the language-independent path or the
|
|
* language-dependent path.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScExecuteMenuItem(PCONTEXTMENU pContextMenu, BSTR MenuItemPath)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteMenuItem"));
|
|
|
|
sc = ScCheckPointers(MenuItemPath);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = ScCheckPointers(pContextMenu, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// execute the menu item, if found.
|
|
MenuItemPtr spMenuItem;
|
|
sc = pContextMenu->get_Item(CComVariant(MenuItemPath), &spMenuItem);
|
|
if(sc.IsError() || sc == SC(S_FALSE)) // error or no item
|
|
return (sc = E_INVALIDARG); // did not find the menu item.
|
|
|
|
// recheck the pointer
|
|
sc = ScCheckPointers(spMenuItem, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// found - execute it
|
|
sc = spMenuItem->Execute();
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScExecuteSelectionMenuItem
|
|
*
|
|
* PURPOSE: Executes a context menu item on the selection.
|
|
*
|
|
* PARAMETERS:
|
|
* BSTR MenuItemPath : Either the language-independent path or the
|
|
* language-dependent path of the menu item.
|
|
|
|
*
|
|
* NOTE: This is an aggregate or utility function - it only uses other
|
|
* object model functions
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScExecuteSelectionMenuItem(BSTR MenuItemPath)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteSelectionMenuItem"));
|
|
|
|
// get the context menu object
|
|
ContextMenuPtr spContextMenu;
|
|
sc = Scget_SelectionContextMenu(&spContextMenu);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = ScExecuteMenuItem(spContextMenu, MenuItemPath);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScExecuteScopeNodeMenuItem
|
|
*
|
|
* PURPOSE: Executes a context menu item on the specified scope node. The parameter
|
|
* is the language independent path of the menu item
|
|
*
|
|
* PARAMETERS:
|
|
* BSTR MenuItemLanguageIndependentPath :
|
|
*
|
|
* NOTE: This is an aggregate or utility function - it only uses other
|
|
* object model functions
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScExecuteScopeNodeMenuItem(BSTR MenuItemPath, VARIANT &varScopeNode /* = ActiveScopeNode */)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteScopeNodeMenuItem"));
|
|
|
|
// get the context menu object for exactly the given node.
|
|
ContextMenuPtr spContextMenu;
|
|
sc = Scget_ScopeNodeContextMenu(varScopeNode, &spContextMenu, /*bMatchGivenNode = */ true);
|
|
|
|
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
|
|
{
|
|
sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED);
|
|
return sc;
|
|
}
|
|
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = ScExecuteMenuItem(spContextMenu, MenuItemPath);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScExecuteShellCommand
|
|
*
|
|
* PURPOSE: Executes a shell command with the specified parameters in the
|
|
* specified directory with the correct window size
|
|
*
|
|
* PARAMETERS:
|
|
* BSTR Command :
|
|
* BSTR Directory :
|
|
* BSTR Parameters :
|
|
* BSTR WindowState :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScExecuteShellCommand(BSTR Command, BSTR Directory, BSTR Parameters, BSTR WindowState)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScExecuteShellCommand"));
|
|
|
|
sc = ScCheckPointers(Command, Directory, Parameters, WindowState);
|
|
if(sc)
|
|
return sc;
|
|
|
|
INodeCallback *pNodeCallback = GetNodeCallback();
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
|
|
sc = ScCheckPointers(pNodeCallback, hNodeSel, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = pNodeCallback->ExecuteShellCommand(hNodeSel, Command, Directory, Parameters, WindowState);
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_ListViewMode
|
|
*
|
|
* PURPOSE: Returns the list view mode, if available.
|
|
*
|
|
* PARAMETERS:
|
|
* ListViewMode * pMode :
|
|
*
|
|
* RETURNS:
|
|
* STDMETHODIMP
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_ListViewMode(PLISTVIEWMODE pMode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ListViewMode"));
|
|
|
|
// check parameter
|
|
if(!pMode)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
return sc;
|
|
}
|
|
|
|
if (!HasList())
|
|
return (ScFromMMC(MMC_E_NOLIST));
|
|
|
|
int mode = 0;
|
|
|
|
// translate it into an automation friendly enum
|
|
switch(GetViewMode())
|
|
{
|
|
default:
|
|
ASSERT( 0 && "Should not come here");
|
|
// fall thru.
|
|
|
|
case LVS_LIST:
|
|
*pMode = ListMode_List;
|
|
break;
|
|
|
|
case LVS_ICON:
|
|
*pMode = ListMode_Large_Icons;
|
|
break;
|
|
|
|
case LVS_SMALLICON:
|
|
*pMode = ListMode_Small_Icons;
|
|
break;
|
|
|
|
case LVS_REPORT:
|
|
*pMode = ListMode_Detail;
|
|
break;
|
|
|
|
case MMCLV_VIEWSTYLE_FILTERED:
|
|
*pMode = ListMode_Filtered;
|
|
break;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_ListViewMode
|
|
*
|
|
* PURPOSE: Sets the list mode to the specified mode.
|
|
*
|
|
* PARAMETERS:
|
|
* ListViewMode mode :
|
|
*
|
|
* RETURNS:
|
|
* STDMETHODIMP
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scput_ListViewMode(ListViewMode mode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_ListViewMode"));
|
|
|
|
int nMode;
|
|
|
|
if (!HasList())
|
|
return (ScFromMMC(MMC_E_NOLIST));
|
|
|
|
switch (mode)
|
|
{
|
|
default:
|
|
sc = E_INVALIDARG;
|
|
return sc;
|
|
|
|
case ListMode_List:
|
|
nMode = LVS_LIST;
|
|
break;
|
|
case ListMode_Detail:
|
|
nMode = LVS_REPORT;
|
|
break;
|
|
case ListMode_Large_Icons:
|
|
nMode = LVS_ICON;
|
|
break;
|
|
case ListMode_Small_Icons:
|
|
nMode = LVS_SMALLICON;
|
|
break;
|
|
|
|
case ListMode_Filtered:
|
|
nMode = MMCLV_VIEWSTYLE_FILTERED;
|
|
break;
|
|
}
|
|
|
|
sc = ScChangeViewMode(nMode);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScBack
|
|
*
|
|
* PURPOSE: Invokes the Back command on the view.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScBack()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScBack"));
|
|
|
|
sc = ScWebCommand(CConsoleView::eWeb_Back);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScForward
|
|
*
|
|
* PURPOSE: Invokes the Forward command on the view.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScForward()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScForward"));
|
|
|
|
sc = ScWebCommand(CConsoleView::eWeb_Forward);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_StatusBarText
|
|
*
|
|
* PURPOSE: Sets the status bar text for the view
|
|
*
|
|
* PARAMETERS:
|
|
* BSTR StatusBarText :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scput_StatusBarText(BSTR StatusBarText)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_StatusBarText"));
|
|
|
|
// check the in parameter
|
|
sc = ScCheckPointers(StatusBarText);
|
|
if(sc)
|
|
return sc;
|
|
|
|
CConsoleStatusBar *pStatusBar = m_ViewData.GetStatusBar();
|
|
sc = ScCheckPointers(pStatusBar, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
USES_CONVERSION;
|
|
// set the status text
|
|
sc = pStatusBar->ScSetStatusText(OLE2T(StatusBarText));
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_Memento
|
|
*
|
|
* PURPOSE: Returns the XML version of the memento for the current view.
|
|
*
|
|
* PARAMETERS:
|
|
* PBSTR Memento : [out]: The memento
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_Memento(PBSTR Memento)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Memento"));
|
|
|
|
sc = ScCheckPointers(Memento);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// initialize the out parameter
|
|
*Memento = NULL;
|
|
|
|
CMemento memento;
|
|
sc = ScInitializeMemento(memento);
|
|
if(sc)
|
|
return sc;
|
|
|
|
std::wstring xml_contents;
|
|
sc = memento.ScSaveToString(&xml_contents);
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
// store the result
|
|
CComBSTR bstrBuff(xml_contents.c_str());
|
|
*Memento = bstrBuff.Detach();
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScViewMemento
|
|
*
|
|
* PURPOSE: Sets the view from the specified XML memento.
|
|
*
|
|
* PARAMETERS:
|
|
* BSTR Memento :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScViewMemento(BSTR Memento)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScViewMemento"));
|
|
|
|
sc = ScCheckPointers(Memento);
|
|
if(sc)
|
|
return sc;
|
|
|
|
CMemento memento;
|
|
sc = memento.ScLoadFromString(Memento);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = ScViewMemento(&memento);
|
|
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
|
|
return (sc = ScFromMMC(IDS_ACTION_COULD_NOTBE_COMPLETED));
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::Scget_CellContents
|
|
//
|
|
// Synopsis: Given row & column, get the text.
|
|
//
|
|
// Arguments: Node: - the row
|
|
// [Column] - 1 based column index
|
|
// [pbstrCellContents] - return value, contents of cell.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::Scget_CellContents (PNODE Node, long Column, PBSTR pbstrCellContents)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::Scget_CellContents"));
|
|
sc = ScCheckPointers(Node, pbstrCellContents);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*pbstrCellContents = NULL;
|
|
|
|
if (!HasList())
|
|
return (ScFromMMC(MMC_E_NOLIST));
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// No need to check if we are in REPORT mode as columns exist
|
|
// even in other modes (small icon....).
|
|
|
|
int iItem = -1;
|
|
sc = m_pListCtrl->ScFindResultItem( Node, iItem );
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Script uses 1- based index for columns & rows.
|
|
// ColCount are total # of cols.
|
|
if (m_pListCtrl->GetColCount() < Column)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
|
|
|
|
CString strData = ctlList.GetItemText(iItem, Column-1 /*convert to zero-based*/);
|
|
*pbstrCellContents = strData.AllocSysString();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScExportList
|
|
//
|
|
// Synopsis: Export the list view data to given file with given options.
|
|
//
|
|
// Arguments: [bstrFile] - File to save to.
|
|
// [exportoptions] - (Unicode, tab/comma delimited & selected rows only).
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScExportList (BSTR bstrFile, ExportListOptions exportoptions)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScExportList"));
|
|
|
|
if (SysStringLen(bstrFile) < 1)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
if (!HasList())
|
|
return (ScFromMMC(MMC_E_NOLIST));
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
bool bUnicode = (exportoptions & ExportListOptions_Unicode);
|
|
bool bTabDelimited = (exportoptions & ExportListOptions_TabDelimited);
|
|
bool bSelectedRowsOnly = (exportoptions & ExportListOptions_SelectedItemsOnly);
|
|
|
|
USES_CONVERSION;
|
|
LPCTSTR lpszFileName = OLE2T(bstrFile);
|
|
|
|
sc = ScWriteExportListData(lpszFileName, bUnicode,
|
|
bTabDelimited, bSelectedRowsOnly,
|
|
false /*bShowErrorDialogs*/);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScClose
|
|
*
|
|
* PURPOSE: Implements Wiew.Close method
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScClose()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScClose"));
|
|
|
|
// get the frame and the document
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
CAMCDoc* pDoc = CAMCDoc::GetDocument();
|
|
sc= ScCheckPointers(pDoc, pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// count the views
|
|
int cViews = 0;
|
|
CAMCViewPosition pos = pDoc->GetFirstAMCViewPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CAMCView* pView = pDoc->GetNextAMCView(pos);
|
|
|
|
if ((pView != NULL) && ++cViews >= 2)
|
|
break;
|
|
}
|
|
|
|
// prevent closing the document this way !!!
|
|
if (cViews == 1)
|
|
{
|
|
sc.FromMMC(IDS_CloseDocNotLastView);
|
|
return sc;
|
|
}
|
|
|
|
// if not closing last view, then give it
|
|
// a chance to clean up first.
|
|
// (if whole doc is closing CAMCDoc will handle
|
|
// closing all the views.)
|
|
|
|
/*
|
|
* Don't allow the user to close the last persisted view.
|
|
*/
|
|
if (IsPersisted() && (pDoc->GetNumberOfPersistedViews() == 1))
|
|
{
|
|
sc.FromMMC(IDS_CantCloseLastPersistableView);
|
|
return sc;
|
|
}
|
|
|
|
// checkings done, do close
|
|
// do it indirectly so that it won't hurt the view extension it it
|
|
// tries to close itself
|
|
pFrame->PostMessage(WM_CLOSE);
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_ScopeTreeVisible
|
|
*
|
|
* PURPOSE: Implements get method for Wiew.ScopeTreeVisible property
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_ScopeTreeVisible( PBOOL pbVisible )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ScopeTreeVisible"));
|
|
|
|
// parameter check...
|
|
sc = ScCheckPointers(pbVisible);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*pbVisible = IsScopePaneVisible();
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_ScopeTreeVisible
|
|
*
|
|
* PURPOSE: Implements set method for Wiew.ScopeTreeVisible property
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scput_ScopeTreeVisible( BOOL bVisible )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_ScopeTreeVisible"));
|
|
|
|
// show/hide the scope pane
|
|
sc = ScShowScopePane (bVisible);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScFindResultItemForScopeNode
|
|
*
|
|
* PURPOSE: - Calculates result item representing the scope node in the list
|
|
*
|
|
* PARAMETERS:
|
|
* PNODE pNode - node to search
|
|
* HRESULTITEM &itm - resulting item
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScFindResultItemForScopeNode( PNODE pNode, HRESULTITEM &itm )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScFindResultItemForScopeNode"));
|
|
|
|
// initialization
|
|
itm = NULL;
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(pNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get/check for list view and tree controls and callback
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc = ScCheckPointers( pScopeTree, m_pTreeCtrl, m_spNodeCallback, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// retrieve MTNode
|
|
HMTNODE hMTNode = NULL;
|
|
sc = pScopeTree->GetHMTNode(pNode, &hMTNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get the pointer to the map
|
|
CTreeViewMap *pTreeMap = m_pTreeCtrl->GetTreeViewMap();
|
|
sc = ScCheckPointers(pTreeMap, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// find the tree item for the node
|
|
HTREEITEM htiNode = NULL;
|
|
sc = pTreeMap->ScGetHTreeItemFromHMTNode(hMTNode, &htiNode);
|
|
if (sc)
|
|
return sc = ScFromMMC(MMC_E_RESULT_ITEM_NOT_FOUND);
|
|
|
|
// try to match the node to the child of selected one
|
|
HTREEITEM htiParent = m_pTreeCtrl->GetParentItem(htiNode);
|
|
if (htiParent == NULL || htiParent != m_pTreeCtrl->GetSelectedItem())
|
|
return sc = ScFromMMC(MMC_E_RESULT_ITEM_NOT_FOUND);
|
|
|
|
// the node shold be in the ListView, lets find if!
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(htiNode);
|
|
|
|
// get result item id
|
|
sc = m_spNodeCallback->GetResultItem (hNode, &itm);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScGetScopeNodeForItem
|
|
*
|
|
* PURPOSE: Returns Node (Scope Node) for specified item index
|
|
*
|
|
* PARAMETERS:
|
|
* int nItem - node index to retrieve
|
|
* PPNODE ppNode - result storage
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScGetScopeNode( HNODE hNode, PPNODE ppNode )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CCCListViewCtrl::ScGetScopeNodeForItem"));
|
|
|
|
// check the parameters
|
|
sc = ScCheckPointers(ppNode);
|
|
if (sc)
|
|
return sc;
|
|
// initialize the result
|
|
*ppNode = NULL;
|
|
|
|
|
|
// get/check required pointers
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc = ScCheckPointers(pScopeTree, m_spNodeCallback, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// find MTNode
|
|
HMTNODE hmtNode;
|
|
sc = m_spNodeCallback->GetMTNode(hNode, &hmtNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// request the object!
|
|
sc = pScopeTree->GetMMCNode(hmtNode, ppNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::Scget_Columns
|
|
*
|
|
* PURPOSE: create new or return pointer to existing Columns object
|
|
*
|
|
* PARAMETERS:
|
|
* PPCOLUMNS ppColumns - resulting (AddRef'ed) pointer
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::Scget_Columns(PPCOLUMNS ppColumns)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Columns"));
|
|
|
|
// Check received parameters
|
|
sc = ScCheckPointers(ppColumns);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// initialize
|
|
*ppColumns = NULL;
|
|
|
|
// Check the pointer to LV
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// forward the request to LV
|
|
sc = m_pListCtrl->Scget_Columns(ppColumns);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScGetSelectedLVItem
|
|
//
|
|
// Synopsis: Return the LVItem cookie.
|
|
//
|
|
// Arguments: LPARAM - the LVDATA retval.
|
|
//
|
|
// Returns: SC - Fails if no selected item in LV.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScGetSelectedLVItem(LPARAM& lvData)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScGetSelectedLVItem"));
|
|
|
|
lvData = LVDATA_ERROR;
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
if(0 == cSel)
|
|
{
|
|
// no items selected, bail
|
|
return (sc = ScFromMMC(MMC_E_NO_SELECTED_ITEMS));
|
|
}
|
|
else if(1 == cSel)
|
|
{
|
|
// single selection
|
|
int iIndex = _GetLVSelectedItemData(&lvData);
|
|
|
|
if (iIndex == -1 || lvData == LVDATA_ERROR)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
if (IsVirtualList())
|
|
{
|
|
// virtual list item in the result pane
|
|
lvData = iIndex;
|
|
}
|
|
}
|
|
else if (cSel > 1)
|
|
{
|
|
// multiselection
|
|
lvData = LVDATA_MULTISELECT;
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScGetHNodeFromPNode
|
|
//
|
|
// Synopsis: Takes in PNODE and returns corresponding hNode
|
|
//
|
|
// Arguments: [PNODE] - Given pnode.
|
|
// [HNODE] - ret val.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScGetHNodeFromPNode (const PNODE& pNode, HNODE& hNode)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScGetHNodeFromPNode"));
|
|
hNode = NULL;
|
|
|
|
CAMCTreeView* pAMCTreeView = GetTreeCtrl();
|
|
sc = ScCheckPointers(pAMCTreeView, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CTreeViewMap *pTreeMap = pAMCTreeView->GetTreeViewMap();
|
|
IScopeTree *pScopeTree = GetScopeTree();
|
|
sc = ScCheckPointers(pTreeMap, pScopeTree, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
HMTNODE hMTNode = NULL;
|
|
sc = pScopeTree->GetHMTNode(pNode, &hMTNode);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = pTreeMap->ScGetHNodeFromHMTNode(hMTNode, &hNode);
|
|
if(sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetMMCView
|
|
*
|
|
* PURPOSE: Creates, AddRef's, and returns a pointer to the tied COM object.
|
|
*
|
|
* PARAMETERS:
|
|
* View ** ppView :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScGetMMCView(View **ppView)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetMMCView"));
|
|
|
|
sc = ScCheckPointers(ppView);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// init out parameter
|
|
*ppView = NULL;
|
|
|
|
// create a CMMCView if needed.
|
|
sc = CTiedComObjectCreator<CMMCView>::ScCreateAndConnect(*this, m_spView);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if(m_spView == NULL)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
|
|
// addref the pointer for the client.
|
|
m_spView->AddRef();
|
|
*ppView = m_spView;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::IsDirty
|
|
*
|
|
* PURPOSE: Determines whether or not CAMCView is in a dirty state
|
|
*
|
|
* RETURNS:
|
|
* bool
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
bool CAMCView::IsDirty()
|
|
{
|
|
bool bRet = m_bDirty;
|
|
|
|
if (!m_bDirty && !m_fRootedAtNonPersistedDynamicNode)
|
|
bRet = HasNodeSelChanged();
|
|
|
|
TraceDirtyFlag(TEXT("CAMCView"), bRet);
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAMCView drawing
|
|
|
|
void CAMCView::OnDraw(CDC* pDC)
|
|
{
|
|
if (IsScopePaneVisible())
|
|
{
|
|
pDC->FillRect (m_rectVSplitter, AMCGetSysColorBrush (COLOR_3DFACE));
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAMCView printing
|
|
|
|
BOOL CAMCView::OnPreparePrinting(CPrintInfo* pInfo)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnPreparePrinting);
|
|
|
|
// default preparation
|
|
return DoPreparePrinting(pInfo);
|
|
}
|
|
|
|
void CAMCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnBeginPrinting);
|
|
|
|
}
|
|
|
|
void CAMCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnEndPrinting);
|
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAMCView diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CAMCView::AssertValid() const
|
|
{
|
|
CView::AssertValid();
|
|
}
|
|
|
|
void CAMCView::Dump(CDumpContext& dc) const
|
|
{
|
|
CView::Dump(dc);
|
|
}
|
|
|
|
CAMCDoc* CAMCView::GetDocument() // non-debug version is inline
|
|
{
|
|
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAMCDoc)));
|
|
return (CAMCDoc*)m_pDocument;
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAMCView message handlers
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: PreCreateWindow
|
|
//
|
|
// Synopsis: Create new window class (CAMCView) - WS_EX_CLIENTEDGE
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOL CAMCView::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
cs.style |= WS_CLIPCHILDREN;
|
|
cs.style &= ~WS_BORDER;
|
|
|
|
// give base class a chance to do own job
|
|
BOOL bOK = (CView::PreCreateWindow(cs));
|
|
|
|
// register view class
|
|
LPCTSTR pszViewClassName = g_szAMCViewWndClassName;
|
|
|
|
// try to register window class which does not cause the repaint
|
|
// on resizing (do it only once)
|
|
static bool bClassRegistered = false;
|
|
if ( !bClassRegistered )
|
|
{
|
|
WNDCLASS wc;
|
|
if (::GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wc))
|
|
{
|
|
// Clear the H and V REDRAW flags
|
|
wc.style &= ~(CS_HREDRAW | CS_VREDRAW);
|
|
wc.lpszClassName = pszViewClassName;
|
|
// Register this new class;
|
|
bClassRegistered = AfxRegisterClass(&wc);
|
|
}
|
|
}
|
|
|
|
// change window class to one which does not cause the repaint
|
|
// on resizing if we successfully registered such
|
|
if ( bClassRegistered )
|
|
cs.lpszClass = pszViewClassName;
|
|
|
|
return bOK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: OnCreate
|
|
//
|
|
// Synopsis: Create Window, and Tree control / Default List control
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int CAMCView::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::OnCreate"));
|
|
|
|
if (CView::OnCreate(lpCreateStruct) == -1)
|
|
{
|
|
sc = E_FAIL;
|
|
return -1;
|
|
}
|
|
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
ASSERT(NULL != pFrame);
|
|
if (pFrame)
|
|
pFrame->SetAMCView(this);
|
|
|
|
m_ViewData.SetStatusBar (dynamic_cast<CConsoleStatusBar*>(pFrame));
|
|
m_ViewData.SetConsoleView (this);
|
|
|
|
m_RightDescCtrl.Create (NULL, WS_CHILD, g_rectEmpty, this, IDC_RightDescBar);
|
|
|
|
ASSERT (m_pDocument != NULL);
|
|
ASSERT (m_pDocument == CAMCDoc::GetDocument());
|
|
ASSERT_KINDOF (CAMCDoc, m_pDocument);
|
|
CAMCDoc* pAMCDoc = reinterpret_cast<CAMCDoc *>(m_pDocument);
|
|
|
|
CCreateContext* pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;
|
|
ASSERT (pContext != NULL);
|
|
|
|
// Set window options
|
|
m_ViewData.m_lWindowOptions = pAMCDoc->GetNewWindowOptions();
|
|
|
|
/*
|
|
* If the scope pane is suppressed, clear the scope-visible flag.
|
|
* It's not necessary to call ScShowScopePane here because none of
|
|
* the windows have been created yet. We just need to keep our
|
|
* interal accounting correct.
|
|
*/
|
|
if (m_ViewData.m_lWindowOptions & MMC_NW_OPTION_NOSCOPEPANE)
|
|
SetScopePaneVisible (false);
|
|
|
|
// Create tree ctrl.
|
|
if (!CreateView (IDC_TreeView) || (!m_pTreeCtrl) )
|
|
{
|
|
sc = E_FAIL;
|
|
return -1;
|
|
}
|
|
|
|
SetPane(ePane_ScopeTree, m_pTreeCtrl, uiClientEdge);
|
|
|
|
if (!AreStdToolbarsAllowed())
|
|
m_ViewData.m_dwToolbarsDisplayed &= ~(STD_MENUS | STD_BUTTONS);
|
|
|
|
// Create default list control
|
|
if (!CreateListCtrl (IDC_ListView, pContext))
|
|
{
|
|
sc = E_FAIL;
|
|
return -1;
|
|
}
|
|
|
|
// Create the folder tab control
|
|
if (!CreateFolderCtrls ())
|
|
{
|
|
sc = E_FAIL;
|
|
return -1;
|
|
}
|
|
|
|
// initialize the result pane to the list view
|
|
{
|
|
CResultViewType rvt;
|
|
|
|
sc = ScSetResultPane(NULL /*HNODE*/, rvt, MMCLV_VIEWSTYLE_REPORT /*viewMode*/, false /*bUsingHistory*/);
|
|
if(sc)
|
|
return -1;
|
|
}
|
|
|
|
sc = ScCreateToolbarObjects();
|
|
if (sc)
|
|
return -1;
|
|
|
|
//
|
|
// Set m_ViewData.
|
|
//
|
|
|
|
m_ViewData.m_nViewID = 0;// Set in OnInitialUpdate
|
|
|
|
VERIFY ((m_ViewData.m_spNodeManager = m_pTreeCtrl->m_spNodeManager) != NULL);
|
|
VERIFY ((m_ViewData.m_spResultData = m_pTreeCtrl->m_spResultData) != NULL);
|
|
VERIFY ((m_ViewData.m_spRsltImageList = m_pTreeCtrl->m_spRsltImageList) != NULL);
|
|
VERIFY ( m_ViewData.m_hwndView = m_hWnd);
|
|
VERIFY ( m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND());
|
|
VERIFY ( m_ViewData.m_pConsoleData = GetDocument()->GetConsoleData());
|
|
|
|
m_ViewData.m_pMultiSelection = NULL;
|
|
|
|
if(pFrame)
|
|
{
|
|
// add the MDIClient window's taskbar as an observer
|
|
CMDIFrameWnd * pFrameWnd = pFrame->GetMDIFrame();
|
|
CWnd *pWnd = NULL;
|
|
if(pFrameWnd)
|
|
pWnd = pFrameWnd->GetWindow(GW_CHILD); // get the first child of the frame.
|
|
}
|
|
|
|
// add AMCDoc as an observer for this source (object)
|
|
CAMCApp *pCAMCApp = AMCGetApp();
|
|
if ( pCAMCApp )
|
|
AddObserver(*static_cast<CAMCViewObserver *>(pCAMCApp));
|
|
|
|
// fire the view creation event to all observers.
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnViewCreated, this);
|
|
if(sc)
|
|
sc.TraceAndClear();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::CreateFolderCtrls
|
|
*
|
|
* PURPOSE: Creates the tabbed folder controls for the scope and result panes.
|
|
*
|
|
* RETURNS:
|
|
* bool
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
bool
|
|
CAMCView::CreateFolderCtrls()
|
|
{
|
|
if (!m_pResultFolderTabView->Create (WS_CHILD|WS_VISIBLE, g_rectEmpty, this, IDC_ResultTabCtrl))
|
|
return false;
|
|
|
|
// add the views to the framework
|
|
GetDocument()->AddView(m_pResultFolderTabView);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CreateView
|
|
*
|
|
* This was copied largely from CFrameWnd::CreateView. We need to duplicate
|
|
* it here so common control-based views are initially created with the
|
|
* correct parent. A common control caches its original parent, so
|
|
* using CFrameWnd::CreateView (which will create the view with the frame
|
|
* as its parent) then reparenting to CAMCView will result in the common
|
|
* control caching the wrong parent.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CView* CAMCView::CreateView (CCreateContext* pContext, int nID, DWORD dwStyle)
|
|
{
|
|
ASSERT(m_hWnd != NULL);
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
ASSERT(pContext != NULL);
|
|
ASSERT(pContext->m_pNewViewClass != NULL);
|
|
|
|
CView* pView = (CView*)pContext->m_pNewViewClass->CreateObject();
|
|
if (pView == NULL)
|
|
{
|
|
TRACE1("Warning: Dynamic create of view type %hs failed.\n",
|
|
pContext->m_pNewViewClass->m_lpszClassName);
|
|
return NULL;
|
|
}
|
|
ASSERT_KINDOF(CView, pView);
|
|
|
|
// views are always created with a border!
|
|
if (!pView->Create (NULL, NULL, AFX_WS_DEFAULT_VIEW | dwStyle,
|
|
g_rectEmpty, this, nID, pContext))
|
|
{
|
|
TRACE0("Warning: could not create view for frame.\n");
|
|
return NULL; // can't continue without a view
|
|
}
|
|
|
|
return pView;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CreateView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
bool CAMCView::CreateView (int nID)
|
|
{
|
|
struct CreateViewData
|
|
{
|
|
int nID;
|
|
CRuntimeClass* pClass;
|
|
CView** ppView;
|
|
DWORD dwStyle;
|
|
};
|
|
|
|
CreateViewData rgCreateViewData[] =
|
|
{
|
|
{ IDC_TreeView,
|
|
RUNTIME_CLASS(CAMCTreeView),
|
|
(CView**)&m_pTreeCtrl,
|
|
0 },
|
|
|
|
{ IDC_OCXHostView,
|
|
RUNTIME_CLASS(COCXHostView),
|
|
(CView**)&m_pOCXHostView,
|
|
0 },
|
|
|
|
{ IDC_WebViewCtrl,
|
|
RUNTIME_CLASS(CAMCWebViewCtrl),
|
|
(CView**)&m_pWebViewCtrl,
|
|
CAMCWebViewCtrl::WS_HISTORY | CAMCWebViewCtrl::WS_SINKEVENTS},
|
|
|
|
{ IDC_ViewExtensionView,
|
|
RUNTIME_CLASS(CAMCWebViewCtrl),
|
|
(CView**)&m_pViewExtensionCtrl,
|
|
WS_CLIPSIBLINGS },
|
|
};
|
|
|
|
for (int i = 0; i < countof (rgCreateViewData); i++)
|
|
{
|
|
if (rgCreateViewData[i].nID == nID)
|
|
{
|
|
CCreateContext ctxt;
|
|
ZeroMemory (&ctxt, sizeof (ctxt));
|
|
ctxt.m_pCurrentDoc = GetDocument();
|
|
ctxt.m_pNewViewClass = rgCreateViewData[i].pClass;
|
|
|
|
CView*& pView = *rgCreateViewData[i].ppView;
|
|
ASSERT (pView == NULL);
|
|
pView = CreateView (&ctxt, nID, rgCreateViewData[i].dwStyle);
|
|
ASSERT ((pView != NULL) && "Check the debug output window");
|
|
|
|
// Add observers only to tree, ocx and web hosts. Do not add to view extension host
|
|
// as we do not care about its activation/deactivations.
|
|
switch (nID)
|
|
{
|
|
case IDC_TreeView:
|
|
// set the view and the description bar as observers of the tree view control
|
|
m_pTreeCtrl->AddObserver(static_cast<CTreeViewObserver &>(*this));
|
|
m_pTreeCtrl->AddObserver(static_cast<CTreeViewObserver &>(m_RightDescCtrl));
|
|
break;
|
|
|
|
case IDC_OCXHostView:
|
|
m_pOCXHostView->AddObserver(static_cast<COCXHostActivationObserver &>(*this));
|
|
break;
|
|
|
|
case IDC_WebViewCtrl:
|
|
m_pWebViewCtrl->AddObserver(static_cast<COCXHostActivationObserver &>(*this));
|
|
break;
|
|
}
|
|
|
|
return (pView != NULL);
|
|
}
|
|
}
|
|
|
|
ASSERT (false && "Missing an entry in rgCreateViewData");
|
|
return (false);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::GetActiveView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CAMCView* CAMCView::GetActiveView()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScChangeViewMode
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScChangeViewMode (int nNewMode)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::OnViewModeChange"));
|
|
|
|
// if switching from a custom view, force a reselect
|
|
if (!HasListOrListPad())
|
|
{
|
|
NavState state = m_pHistoryList->GetNavigateState();
|
|
m_pHistoryList->SetNavigateState (MMC_HISTORY_BUSY);
|
|
PrivateChangeListViewMode(nNewMode);
|
|
m_pHistoryList->SetNavigateState (state);
|
|
sc = m_pTreeCtrl->ScReselect();
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
else
|
|
{
|
|
int nCurMode = m_pListCtrl->GetViewMode();
|
|
|
|
if ( (nNewMode == MMCLV_VIEWSTYLE_FILTERED) &&
|
|
(!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED)) )
|
|
return (sc = E_INVALIDARG);
|
|
|
|
PrivateChangeListViewMode(nNewMode);
|
|
|
|
// if filter state change, notify the snap-in
|
|
if ( ((nCurMode == MMCLV_VIEWSTYLE_FILTERED) != (nNewMode == MMCLV_VIEWSTYLE_FILTERED))
|
|
&& (GetListOptions() & RVTI_LIST_OPTIONS_FILTERED))
|
|
{
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
ASSERT(hNodeSel != NULL);
|
|
m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTER_CHANGE,
|
|
(nNewMode == MMCLV_VIEWSTYLE_FILTERED) ? MFCC_ENABLE : MFCC_DISABLE, 0);
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ViewMmento
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScViewMemento(CMemento* pMemento)
|
|
{
|
|
DECLARE_SC (sc, TEXT("CAMCView::ScViewMemento"));
|
|
sc = ScCheckPointers(pMemento);
|
|
if (sc)
|
|
return sc;
|
|
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
MTNODEID NodeId = 0;
|
|
|
|
CBookmark& bm = pMemento->GetBookmark();
|
|
ASSERT(bm.IsValid());
|
|
|
|
// We want to display message if exact favorite item cannot be selected.
|
|
bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark.
|
|
sc = pScopeTree->GetNodeIDFromBookmark( bm, &NodeId, bExactMatchFound);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (! bExactMatchFound)
|
|
return ScFromMMC(IDS_NODE_NOT_FOUND); // do not trace
|
|
|
|
INodeCallback *pNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers(pNodeCallback, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// set the persisted information to the saved settings.
|
|
sc = pNodeCallback->SetViewSettings(GetViewID(),
|
|
reinterpret_cast<HBOOKMARK>(&bm),
|
|
reinterpret_cast<HVIEWSETTINGS>(&pMemento->GetViewSettings()));
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScSelectNode(NodeId, /*bSelectExactNode*/ true);
|
|
if (sc == ScFromMMC(IDS_NODE_NOT_FOUND))
|
|
{
|
|
SC scNoTrace = sc;
|
|
sc.Clear();
|
|
return scNoTrace;
|
|
}
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnSetFocus
|
|
*
|
|
* WM_SETFOCUS handler for CAMCView.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::OnSetFocus(CWnd* pOldWnd)
|
|
{
|
|
/*
|
|
* try to deflect the activation to a child view; if we couldn't just punt
|
|
*/
|
|
if (!DeflectActivation (true, NULL))
|
|
CView::OnSetFocus(pOldWnd);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnActivateView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
|
|
{
|
|
/*
|
|
* try to deflect the activation to a child view; if we couldn't just punt
|
|
*/
|
|
if (!DeflectActivation (bActivate, pDeactiveView))
|
|
CView::OnActivateView (bActivate, pActivateView, pDeactiveView);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::DeflectActivation
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
bool CAMCView::DeflectActivation (BOOL fActivate, CView* pDeactivatingView)
|
|
{
|
|
if (fActivate)
|
|
{
|
|
CFrameWnd* pFrame = GetParentFrame();
|
|
if (pFrame == NULL)
|
|
return (false);
|
|
|
|
/*
|
|
* first try to put the focus back on the deactivating view
|
|
*/
|
|
if (pDeactivatingView == NULL)
|
|
pDeactivatingView = pFrame->GetActiveView();
|
|
|
|
if ((pDeactivatingView != NULL) && (pDeactivatingView != this))
|
|
{
|
|
pFrame->SetActiveView (pDeactivatingView);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* otherwise, deflect the activation to the scope view, if it's there
|
|
*/
|
|
CView* pScopeView = NULL;
|
|
|
|
if (IsScopePaneVisible() && ((pScopeView = GetPaneView(ePane_ScopeTree)) != NULL))
|
|
{
|
|
if (IsWindow (pScopeView->GetSafeHwnd()))
|
|
{
|
|
pFrame->SetActiveView (pScopeView);
|
|
return (true);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* finally, no scope view, try the result view
|
|
*/
|
|
CView* pResultView = GetResultView();
|
|
|
|
if (pResultView != NULL)
|
|
{
|
|
pFrame->SetActiveView(pResultView);
|
|
return (true);
|
|
}
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: OnLButtonDown
|
|
//
|
|
// Synopsis: If mouse down in splitter area initiate view tracker to move
|
|
// the splitter. (TrackerCallback function handles completion)
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CAMCView::OnLButtonDown(UINT nFlags, CPoint pt)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnLButtonDown);
|
|
|
|
// click in splitter bar?
|
|
if (!m_rectVSplitter.PtInRect(pt))
|
|
return;
|
|
|
|
// setup tracker information
|
|
TRACKER_INFO trkinfo;
|
|
|
|
// range is client area
|
|
GetClientRect(trkinfo.rectArea);
|
|
|
|
// bound by min size of panes
|
|
trkinfo.rectBounds = trkinfo.rectArea;
|
|
trkinfo.rectBounds.left += m_PaneInfo[ePane_ScopeTree].cxMin;
|
|
trkinfo.rectBounds.right -= m_PaneInfo[ePane_Results].cxMin;
|
|
|
|
// Current tracker is splitter rect
|
|
trkinfo.rectTracker = trkinfo.rectArea;
|
|
trkinfo.rectTracker.left = m_PaneInfo[ePane_ScopeTree].cx;
|
|
trkinfo.rectTracker.right = trkinfo.rectTracker.left + m_cxSplitter;
|
|
|
|
// Don't allow either pane to be hidden by dragging the splitter
|
|
trkinfo.bAllowLeftHide = FALSE;
|
|
trkinfo.bAllowRightHide = FALSE;
|
|
|
|
// back ptr and completion callback
|
|
trkinfo.pView = this;
|
|
trkinfo.pCallback = TrackerCallback;
|
|
|
|
// initiate tracking
|
|
CViewTracker::StartTracking (&trkinfo);
|
|
}
|
|
|
|
|
|
void CAMCView::AdjustTracker (int cx, int cy)
|
|
{ // if user resizes window so that splitter becomes hidden,
|
|
// move it like Explorer does.
|
|
|
|
if (!IsScopePaneVisible())
|
|
return;
|
|
|
|
// extra adjustment
|
|
cx -= BORDERPADDING + 1;
|
|
|
|
if (cx <= m_PaneInfo[ePane_ScopeTree].cx + m_cxSplitter)
|
|
{
|
|
int offset = m_PaneInfo[ePane_ScopeTree].cx + m_cxSplitter - cx;
|
|
|
|
m_PaneInfo[ePane_ScopeTree].cx -= offset;
|
|
m_PaneInfo[ePane_Results].cx -= offset;
|
|
|
|
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
|
|
}
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScAddDefaultColumns
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScAddDefaultColumns()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAddDefaultColumns"));
|
|
|
|
IHeaderCtrlPtr spHeaderCtrl = m_ViewData.m_spNodeManager;
|
|
|
|
sc = ScCheckPointers(spHeaderCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
SetUsingDefColumns(TRUE);
|
|
|
|
const int INDEX_MAX = 2;
|
|
|
|
CString str[INDEX_MAX];
|
|
|
|
LoadString(str[0], IDS_NAME);
|
|
LoadString(str[1], IDS_TYPE);
|
|
|
|
int iMax = 0;
|
|
int nMax = str[0].GetLength();
|
|
int nTemp = 0;
|
|
|
|
for (int i=1; i < INDEX_MAX; i++)
|
|
{
|
|
nTemp = str[i].GetLength();
|
|
|
|
if (nTemp > nMax)
|
|
{
|
|
nMax = nTemp;
|
|
iMax = i;
|
|
}
|
|
}
|
|
|
|
int cchName = nMax + 1;
|
|
LPOLESTR pszName = new OLECHAR[cchName];
|
|
sc = ScCheckPointers(pszName, E_OUTOFMEMORY);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CAutoArrayPtr<OLECHAR> Name;
|
|
Name.Attach(pszName); // Attach to CAuto... so that it is automatically freed.
|
|
|
|
int alWidths[INDEX_MAX] = {0, 0};
|
|
GetDefaultColumnWidths(alWidths);
|
|
|
|
for (i=0; i < INDEX_MAX; i++)
|
|
{
|
|
// Bug 157408: remove the "Type" column for static nodes
|
|
if (i == 1)
|
|
continue;
|
|
|
|
USES_CONVERSION;
|
|
|
|
sc = StringCchCopyW(pszName, cchName, T2COLE( (LPCTSTR) str[i] ));
|
|
if (sc)
|
|
sc.TraceAndClear(); // Ignore and set truncated column name.
|
|
|
|
sc = spHeaderCtrl->InsertColumn(i, pszName, LVCFMT_LEFT, alWidths[i]);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
SC
|
|
CAMCView::ScInitDefListView(LPUNKNOWN pUnkResultsPane)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScInitDefListView"));
|
|
|
|
if (!HasList())
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
sc = ScCheckPointers(pUnkResultsPane, m_ViewData.m_spResultData, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
m_ViewData.m_spResultData->ResetResultData();
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnSelectNode
|
|
*
|
|
* Most of this code was moved out of CAMCTreeView::OnSelectNode, as it is
|
|
* more appropriate that this is executed by CAMCView.
|
|
*
|
|
* PURPOSE: Called when an item in the tree is selected. Does the following:
|
|
* 1) Sets up the result pane to either a list, and OCX, or a web page.
|
|
* 2) Sets the view options
|
|
* 3) Sends a selection notification to the node.
|
|
* 3) Adds a history entry if needed.
|
|
*
|
|
* PARAMETERS:
|
|
* HNODE hNode : [IN]: The node that got selected.
|
|
* BOOL & bAddSubFolders : [OUT]: Whether subfolders should be added to the list
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnSelectNode(HNODE hNode, BOOL &bAddSubFolders)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnSelectNode"));
|
|
|
|
USES_CONVERSION;
|
|
|
|
//
|
|
// Set the result pane
|
|
//
|
|
LPOLESTR pszResultPane = NULL;
|
|
GUID guidTaskpad = GUID_NULL;
|
|
int lViewMode = MMCLV_VIEWSTYLE_REPORT; // the default view mode
|
|
|
|
//long lViewOptions = MMC_VIEW_OPTIONS_NONE;
|
|
|
|
bool bUsingHistory = false;
|
|
bool bRestoredView = false;
|
|
|
|
INodeCallback* spNodeCallBack = GetNodeCallback();
|
|
sc = ScCheckPointers(spNodeCallBack, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CHistoryList* pHistoryList = GetHistoryList();
|
|
sc = ScCheckPointers(pHistoryList, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CResultViewType rvt;
|
|
|
|
if (pHistoryList->GetNavigateState() == MMC_HISTORY_NAVIGATING)
|
|
{
|
|
// we're going "back" or "forward":
|
|
// get Result pane stuff from history
|
|
|
|
bUsingHistory = true;
|
|
sc = pHistoryList->ScGetCurrentResultViewType(rvt, lViewMode, guidTaskpad);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = spNodeCallBack->RestoreResultView(hNode, rvt);
|
|
if (sc)
|
|
{
|
|
TraceError(_T("Snapin failed on NCLBK_RESTORE_VIEW\n"), sc);
|
|
sc.Clear(); // Compatible with 1.2 dont need this error.
|
|
}
|
|
|
|
if (sc.ToHr() == S_OK)
|
|
bRestoredView = true;
|
|
else
|
|
rvt = CResultViewType(); // this restores rvt back to a nascent state. see Bug 176058.
|
|
|
|
}
|
|
|
|
// The view is not restored by history so ask snapin for view settings.
|
|
if (! bRestoredView)
|
|
{
|
|
|
|
// get Result pane stuff from snapin
|
|
GUID guid = GUID_NULL;
|
|
sc = spNodeCallBack->GetResultPane(hNode, rvt, &guid);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// we cannot pass the guidTaskpad to GetResultPane directly, since
|
|
// when it is navigation what causes the change, view settings are
|
|
// not yet updated and thus the guid returned will not reflect the
|
|
// current situation
|
|
if (!bUsingHistory)
|
|
guidTaskpad = guid;
|
|
}
|
|
|
|
// make sure we have a taskpad set (this will change the value of guidTaskpad if required)
|
|
// This is required when pages referred from history are no longer available when returning
|
|
// to the view (taskpad being deleted/default page being replaced/etc.)
|
|
if (bUsingHistory)
|
|
spNodeCallBack->SetTaskpad(hNode, &guidTaskpad);
|
|
|
|
//SetViewOptions(lViewOptions);
|
|
|
|
|
|
// at this stage, rvt contains all the result view information (excluding, as always the list view mode.)
|
|
if (rvt.HasList())
|
|
{
|
|
SetListViewMultiSelect(
|
|
(rvt.GetListOptions() & RVTI_LIST_OPTIONS_MULTISELECT) == RVTI_LIST_OPTIONS_MULTISELECT);
|
|
}
|
|
|
|
sc = ScSetResultPane(hNode, rvt, lViewMode, bUsingHistory);
|
|
if(sc)
|
|
return sc;
|
|
|
|
::CoTaskMemFree(pszResultPane);
|
|
|
|
//
|
|
// Initialize default list view.
|
|
//
|
|
LPUNKNOWN pUnkResultsPane = GetPaneUnknown(CConsoleView::ePane_Results);
|
|
if (rvt.HasList())
|
|
{
|
|
sc = ScInitDefListView(pUnkResultsPane);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = ScCheckPointers(m_ViewData.m_spResultData, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// this turns off list view redrawing. Should have some sort of smart object that automatically
|
|
// turns redrawing on in its destructor.
|
|
m_ViewData.m_spResultData->SetLoadMode(TRUE); // SetLoadMode(FALSE) is called by the caller, CAMCTreeView::OnSelectNode
|
|
}
|
|
|
|
|
|
//
|
|
// Notify the new node that it is selected.
|
|
//
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
|
|
selInfo.m_bScope = TRUE;
|
|
selInfo.m_pView = pUnkResultsPane;
|
|
|
|
if (rvt.HasWebBrowser())
|
|
{
|
|
selInfo.m_bResultPaneIsWeb = TRUE;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
|
|
}
|
|
else if (rvt.HasOCX())
|
|
{
|
|
selInfo.m_bResultPaneIsOCX = TRUE;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
|
|
}
|
|
|
|
// Increment and save local copy of nesting level counter. This counter serves
|
|
// two purposes. First, it allows AMCView to inhibit inserting scope items in
|
|
// the result pane during a select by checking the IsSelectingNode method.
|
|
// Without this test the scope items would appear twice because all the scope
|
|
// items are added to the result pane at the end of this method.
|
|
// Second, during the following ScNotifySelect call the snap-in could do another
|
|
// select which would re-enter this method. In that case, only the innermost
|
|
// call to this method should do the post-notify processing. The outer calls
|
|
// should just exit, returning S_FALSE instead of S_OK.
|
|
|
|
int nMyNestLevel = ++m_nSelectNestLevel;
|
|
|
|
// collect / manage view tabs
|
|
sc = ScAddFolderTabs( hNode, guidTaskpad );
|
|
if (sc)
|
|
return sc;
|
|
|
|
try
|
|
{
|
|
sc = ScNotifySelect ( spNodeCallBack, hNode, false /*fMultiSelect*/, true, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
catch(...)
|
|
{
|
|
// if first call to Select, reset level to zero before leaving
|
|
if (nMyNestLevel == 1) m_nSelectNestLevel = 0;
|
|
throw;
|
|
}
|
|
|
|
|
|
// if the local call level does not match the shared call level then this
|
|
// method was reentered during the ScNotifySelect. In that case don't finish
|
|
// the processing because the node and/or view may have changed.
|
|
// Be sure to reset the call level to zero if this is the outermost call.
|
|
|
|
ASSERT(nMyNestLevel <= m_nSelectNestLevel);
|
|
BOOL bDoProcessing = (nMyNestLevel == m_nSelectNestLevel);
|
|
if (nMyNestLevel == 1)
|
|
m_nSelectNestLevel = 0;
|
|
|
|
if (!bDoProcessing)
|
|
return S_FALSE;
|
|
|
|
|
|
//
|
|
// If the result pane is the def-LV, ensure that there are headers.
|
|
// If not add the default ones
|
|
//
|
|
|
|
if (rvt.HasList())
|
|
{
|
|
SetUsingDefColumns(FALSE);
|
|
|
|
// Get ptr to ResultPane.
|
|
IMMCListViewPtr pMMCLV = pUnkResultsPane;
|
|
sc = ScCheckPointers(pMMCLV, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
int nCols = 0;
|
|
sc = pMMCLV->GetColumnCount(&nCols);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if(0 == nCols)
|
|
{
|
|
sc = ScAddDefaultColumns();
|
|
if(sc)
|
|
return sc;
|
|
|
|
IResultDataPrivatePtr& pResultDataPrivate = m_ViewData.m_spResultData;
|
|
sc = ScCheckPointers(pResultDataPrivate, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
long lViewMode = GetViewMode();
|
|
|
|
// If default mode is filtered and new node doesn't
|
|
// support that, use report mode instead
|
|
if (lViewMode == MMCLV_VIEWSTYLE_FILTERED &&
|
|
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_FILTERED))
|
|
lViewMode = LVS_REPORT;
|
|
|
|
// you've got to change the mode before you change the
|
|
// style: style doesn't contain the "quickfilter" bit.
|
|
pResultDataPrivate->SetViewMode (lViewMode);
|
|
|
|
long style = GetDefaultListViewStyle();
|
|
if (style != 0)
|
|
{
|
|
sc = pResultDataPrivate->SetListStyle(style);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Show the static scope items in the result pane,
|
|
// but not for a virtual list view, or views specifically
|
|
// marked that they don't want scope items in the result view
|
|
//
|
|
|
|
if (rvt.HasList() &&
|
|
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_OWNERDATALIST) &&
|
|
!(rvt.GetListOptions() & RVTI_LIST_OPTIONS_EXCLUDE_SCOPE_ITEMS_FROM_LIST))
|
|
{
|
|
bAddSubFolders = TRUE;
|
|
}
|
|
|
|
|
|
// Update window title.
|
|
sc = ScUpdateWindowTitle();
|
|
if(sc)
|
|
return sc;
|
|
|
|
// fire event to script
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnViewChange, this, hNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScSetResultPane
|
|
*
|
|
* PURPOSE: Sets the result pane to the specified configuration.
|
|
*
|
|
* PARAMETERS:
|
|
* HNODE hNode :
|
|
* CResultViewType rvt :
|
|
* long lViewOptions :
|
|
* bool bUsingHistory :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScSetResultPane(HNODE hNode, CResultViewType rvt, int viewMode, bool bUsingHistory)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::SetResultPane"));
|
|
|
|
m_ViewData.SetResultViewType(rvt);
|
|
|
|
if(rvt.HasList())
|
|
{
|
|
sc = ScAttachListViewAsResultPane();
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
else if(rvt.HasWebBrowser())
|
|
{
|
|
sc = ScAttachWebViewAsResultPane();
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
else if(rvt.HasOCX())
|
|
{
|
|
sc = ScAttachOCXAsResultPane(hNode);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0 && "Should not come here!!");
|
|
return (sc = E_UNEXPECTED);
|
|
}
|
|
|
|
// show the toolbars
|
|
if(GetStdToolbar() != NULL) // may be NULL at startup.
|
|
{
|
|
sc = GetStdToolbar()->ScShowStdBar(true);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
// if we haven't gotten here using history, add a history entry.
|
|
if(!bUsingHistory)
|
|
{
|
|
GUID guidTaskpad = GUID_NULL;
|
|
GetTaskpadID(guidTaskpad);
|
|
sc = m_pHistoryList->ScAddEntry(rvt, m_nViewMode, guidTaskpad);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
|
|
// if we have a node manager, tell it what the result pane is.
|
|
if(m_ViewData.m_spNodeManager)
|
|
{
|
|
LPUNKNOWN pUnkResultsPane = GetPaneUnknown(CConsoleView::ePane_Results);
|
|
m_ViewData.m_spNodeManager->SetResultView(pUnkResultsPane);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
BOOL CAMCView::CreateListCtrl(int nID, CCreateContext* pContext)
|
|
{
|
|
TRACE_METHOD(CAMCView, CreateListCtrl);
|
|
|
|
ASSERT(m_pListCtrl == NULL);
|
|
|
|
CComObject<CCCListViewCtrl> *pLV = NULL;
|
|
CComObject<CCCListViewCtrl>::CreateInstance( &pLV );
|
|
|
|
if (pLV == NULL)
|
|
{
|
|
ASSERT(0 && "Unable to create list control");
|
|
return FALSE;
|
|
}
|
|
|
|
// we assign directly - implicit cast works, since we have a type derived from the one we need
|
|
m_pListCtrl = pLV;
|
|
// we intend to hold a reference, so do addref here (CreateInstance creates w/ 0 reffs)
|
|
m_pListCtrl->AddRef();
|
|
|
|
if (!m_pListCtrl->Create (WS_VISIBLE | WS_CHILD, g_rectEmpty, this, nID, pContext))
|
|
{
|
|
ASSERT(0 && "Unable to create list control");
|
|
return FALSE;
|
|
}
|
|
|
|
m_pListCtrl->SetViewMode (m_nViewMode);
|
|
|
|
SC SC = m_pListCtrl->ScInitialize(); // intialize the list control
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CAMCView::SetListViewOptions(DWORD dwListOptions)
|
|
{
|
|
TRACE_METHOD(CAMCView, SetListViewOptions);
|
|
|
|
bool bVirtual = (dwListOptions & RVTI_LIST_OPTIONS_OWNERDATALIST) ? true : false;
|
|
|
|
ASSERT(m_pListCtrl != NULL);
|
|
|
|
CDocument* pDoc = GetDocument();
|
|
ASSERT(pDoc != NULL);
|
|
|
|
// If change to/from virtual list, change list mode
|
|
if (IsVirtualList() != bVirtual)
|
|
{
|
|
m_ViewData.SetVirtualList (bVirtual);
|
|
pDoc->RemoveView(m_pListCtrl->GetListViewPtr());
|
|
m_pListCtrl->SetVirtualMode(bVirtual);
|
|
pDoc->AddView(m_pListCtrl->GetListViewPtr());
|
|
m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND();
|
|
}
|
|
|
|
// if snapin doesn't support filtering make sure it's off
|
|
if (!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED) &&
|
|
m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED)
|
|
{
|
|
m_pListCtrl->SetViewMode(LVS_REPORT);
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScAttachListViewAsResultPane
|
|
*
|
|
* PURPOSE: Sets up the list view as the result pane.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScAttachListViewAsResultPane()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAttachListViewAsResultPane"));
|
|
|
|
bool bVirtual = (GetListOptions() & RVTI_LIST_OPTIONS_OWNERDATALIST) ? true : false;
|
|
GUID guidTaskpad;
|
|
GetTaskpadID(guidTaskpad);
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
CDocument* pDoc = GetDocument();
|
|
ASSERT(pDoc != NULL);
|
|
|
|
// If change to/from virtual list, change list mode
|
|
if (IsVirtualList() != bVirtual)
|
|
{
|
|
m_ViewData.SetVirtualList (bVirtual);
|
|
pDoc->RemoveView(m_pListCtrl->GetListViewPtr());
|
|
m_pListCtrl->SetVirtualMode(bVirtual);
|
|
pDoc->AddView(m_pListCtrl->GetListViewPtr());
|
|
m_ViewData.m_hwndListCtrl = m_pListCtrl->GetListViewHWND();
|
|
}
|
|
|
|
// if snapin doesn't support filtering make sure it's off
|
|
if (!(GetListOptions() & RVTI_LIST_OPTIONS_FILTERED) &&
|
|
m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED)
|
|
{
|
|
m_pListCtrl->SetViewMode(LVS_REPORT);
|
|
}
|
|
|
|
ShowResultPane(m_pListCtrl->GetListViewPtr(), uiClientEdge);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScAttachWebViewAsResultPane
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScAttachWebViewAsResultPane()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAttachWebViewAsResultPane"));
|
|
|
|
// if we were in ListPad-mode, undo that.
|
|
if (m_pListCtrl->IsListPad())
|
|
{
|
|
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
// The control is created on demand. This prevents IE from loading when unnecessary
|
|
// and reduces startup time.
|
|
if (m_pWebViewCtrl == NULL)
|
|
CreateView (IDC_WebViewCtrl);
|
|
|
|
sc = ScCheckPointers(m_pWebViewCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// Force web control to update its palette
|
|
SendMessage(WM_QUERYNEWPALETTE);
|
|
|
|
ShowResultPane(m_pWebViewCtrl, uiNoClientEdge);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScAttachOCXAsResultPane
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* LPCTSTR pszResultPane :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScAttachOCXAsResultPane(HNODE hNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAttachOCXAsResultPane"));
|
|
USES_CONVERSION;
|
|
|
|
ASSERT(m_pListCtrl != NULL);
|
|
|
|
if (m_pOCXHostView == NULL)
|
|
CreateView (IDC_OCXHostView);
|
|
|
|
sc = ScCheckPointers(m_pOCXHostView);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = m_pOCXHostView->ScSetControl(hNode, m_ViewData.m_rvt, GetNodeCallback());
|
|
if(sc)
|
|
return sc;
|
|
|
|
ShowResultPane(m_pOCXHostView, uiClientEdge);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScApplyViewExtension
|
|
*
|
|
* Applies a view extension to the current view. pszURL specifies the
|
|
* URL of the HTML to load as the view extension. If pszURL is NULL or
|
|
* empty, the view extension is removed.
|
|
*
|
|
* This method will force a layout of the view if it is required.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScApplyViewExtension (
|
|
LPCTSTR pszURL) /* I:URL to use, NULL to remove */
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScApplyViewExtension"));
|
|
|
|
/*
|
|
* assume no view extension
|
|
*/
|
|
bool fViewWasExtended = m_fViewExtended;
|
|
m_fViewExtended = false;
|
|
|
|
/*
|
|
* if we're given a URL with which to extend the view, turn on the extension
|
|
*/
|
|
if ((pszURL != NULL) && (*pszURL != 0))
|
|
{
|
|
/*
|
|
* if we don't have a web control for the view extension yet, create one
|
|
*/
|
|
if (m_pViewExtensionCtrl == NULL)
|
|
CreateView (IDC_ViewExtensionView);
|
|
|
|
sc = ScCheckPointers (m_pViewExtensionCtrl, E_FAIL);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
m_fViewExtended = true;
|
|
|
|
// hide the hosted window initially
|
|
CWnd *pwndHosted = GetPaneView(ePane_Results);
|
|
sc = ScCheckPointers(pwndHosted);
|
|
if(sc)
|
|
return sc;
|
|
|
|
pwndHosted->ShowWindow(SW_HIDE);
|
|
|
|
RecalcLayout(); // do this BEFORE calling Navigate, which may resize the above rectangle via the mmcview behavior
|
|
|
|
// navigate to the requested URL
|
|
m_pViewExtensionCtrl->Navigate (pszURL, NULL);
|
|
}
|
|
else if (fViewWasExtended && (m_pViewExtensionCtrl != NULL))
|
|
{
|
|
/*
|
|
* Bug 96948: If we've got an extension and we're currently extending
|
|
* the view, navigate the view extension's web browser to an empty page
|
|
* so the behavior that resizes the hosted result frame is disabled
|
|
*/
|
|
CStr strEmptyPage;
|
|
sc = CHistoryList::ScGeneratePageBreakURL (strEmptyPage);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
m_pViewExtensionCtrl->Navigate (strEmptyPage, NULL);
|
|
|
|
if(fViewWasExtended)
|
|
DeferRecalcLayout();
|
|
}
|
|
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ShowResultPane
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* CView* pNewView :
|
|
* EUIStyleType nStyle :
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::ShowResultPane(CView* pNewView, EUIStyleType nStyle)
|
|
{
|
|
TRACE_METHOD(CAMCView, ShowResultPane);
|
|
ASSERT(pNewView != NULL);
|
|
|
|
CView* pCurrentView = GetPaneView(ePane_Results);
|
|
|
|
bool bActive = (GetParentFrame()->GetActiveView() == pCurrentView);
|
|
|
|
// Check to see if we need to swap the CWnd control in the result pane
|
|
if (pNewView != pCurrentView)
|
|
{
|
|
HWND hwndCurrentView = pCurrentView->GetSafeHwnd();
|
|
|
|
if (IsWindow (hwndCurrentView))
|
|
{
|
|
pCurrentView->ShowWindow(SW_HIDE);
|
|
|
|
// Note: We are directly hiding the window for cases that controls
|
|
// don't hide during a DoVerb(OLEIVERB_HIDE). Actually, this does a
|
|
// hide on all windows. It's too hard at this point to optimize the code
|
|
// for doing this with an OLE control only.
|
|
::ShowWindow(hwndCurrentView, SW_HIDE);
|
|
}
|
|
|
|
SetPane(ePane_Results, pNewView, nStyle);
|
|
RecalcLayout();
|
|
|
|
// if other pane was active, make the new one active
|
|
if ((pCurrentView != NULL) && bActive)
|
|
{
|
|
// make sure the new window is visible
|
|
pNewView->ShowWindow(SW_SHOW);
|
|
GetParentFrame()->SetActiveView(pNewView);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetPaneInfo
|
|
//
|
|
// Synopsis: Get information about a particular pane
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CAMCView::GetPaneInfo(ViewPane ePane, int* pcxCur, int* pcxMin)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetPaneInfo);
|
|
ASSERT_VALID(this);
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::GetPaneInfo: Invalid pane specifier");
|
|
return;
|
|
}
|
|
|
|
if ((pcxCur==NULL) || (pcxMin==NULL))
|
|
{
|
|
ASSERT(FALSE); // One or more of the args is wrong
|
|
return;
|
|
}
|
|
|
|
// REVIEW fix enum
|
|
*pcxCur = m_PaneInfo[ePane].cx;
|
|
*pcxMin = m_PaneInfo[ePane].cxMin;
|
|
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SetPaneInfo
|
|
//
|
|
// Synopsis: Set information about a particular pane
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CAMCView::SetPaneInfo(ViewPane ePane, int cxCur, int cxMin)
|
|
{
|
|
TRACE_METHOD(CAMCView, SetPaneInfo);
|
|
ASSERT_VALID(this);
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::SetPaneInfo: Invalid pane specifier");
|
|
return;
|
|
}
|
|
|
|
if (cxCur < 0 || cxMin < 0)
|
|
{
|
|
ASSERT(FALSE); // One or more of the args is wrong
|
|
return;
|
|
}
|
|
|
|
m_PaneInfo[ePane].cx = cxCur;
|
|
m_PaneInfo[ePane].cxMin = cxMin;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetPaneView
|
|
//
|
|
// Synopsis: Returns a pointer to CView for a particular pane
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CView* CAMCView::GetPaneView(ViewPane ePane)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetPaneView);
|
|
ASSERT_VALID(this);
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::GetPaneView: Invalid pane specifier");
|
|
return (NULL);
|
|
}
|
|
|
|
return (m_PaneInfo[ePane].pView);
|
|
}
|
|
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::GetResultView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CView* CAMCView::GetResultView() const
|
|
{
|
|
CView* pView = NULL;
|
|
|
|
// may need changes here - assumes the different types are independent.
|
|
|
|
if(HasWebBrowser())
|
|
pView = m_pWebViewCtrl;
|
|
|
|
else if(HasList())
|
|
pView = m_pListCtrl->GetListViewPtr();
|
|
|
|
else if(HasOCX())
|
|
pView = m_pOCXHostView;
|
|
|
|
ASSERT (pView != NULL);
|
|
return (pView);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetPaneUnknown
|
|
//
|
|
// Synopsis: Returns a pointer to the Unknown
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
LPUNKNOWN CAMCView::GetPaneUnknown(ViewPane ePane)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetPaneUnknown);
|
|
ASSERT_VALID(this);
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::GetPaneUnknown: Invalid pane specifier");
|
|
return (NULL);
|
|
}
|
|
|
|
if (!IsWindow (GetPaneView(ePane)->GetSafeHwnd()))
|
|
{
|
|
ASSERT(FALSE); // Invalid pane element
|
|
return NULL;
|
|
}
|
|
|
|
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
|
|
{
|
|
return m_pWebViewCtrl->GetIUnknown();
|
|
}
|
|
else if( HasList() && m_pListCtrl != NULL )
|
|
{
|
|
IUnknownPtr spUnk = m_pListCtrl;
|
|
LPUNKNOWN pUnk = spUnk;
|
|
return pUnk;
|
|
}
|
|
else if (HasOCX() && m_pOCXHostView != NULL)
|
|
{
|
|
ASSERT(GetPaneView (ePane));
|
|
return m_pOCXHostView->GetIUnknown();
|
|
}
|
|
else
|
|
{
|
|
// result pane not initialized yet. This is usually because we are in between a deselect and a
|
|
// subsequent reselect.
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SetPane
|
|
//
|
|
// Synopsis: Set a CWnd pointer for a particular pane and other information
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CAMCView::SetPane(ViewPane ePane, CView* pView, EUIStyleType nStyle)
|
|
{
|
|
TRACE_METHOD(CAMCView, SetPane);
|
|
ASSERT_VALID(this);
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::SetPane: Invalid pane specifier");
|
|
return;
|
|
}
|
|
|
|
if (pView==NULL || !IsWindow(*pView))
|
|
{
|
|
ASSERT(FALSE); // Invalid arg
|
|
return;
|
|
}
|
|
|
|
m_PaneInfo[ePane].pView = pView;
|
|
|
|
// Ensure that the window is visible & at the top of the Z-order.
|
|
pView->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
|
|
|
|
// Note: We are directly showing the window for cases that controls
|
|
// don't show during a DoVerb(OLEIVERB_SHOW). Actually, this does a
|
|
// show on all windows. It's too hard at this point to optimize the code
|
|
// for doing this with an OLE control only.
|
|
::ShowWindow(pView->m_hWnd, SW_SHOW);
|
|
}
|
|
|
|
//
|
|
// Other Methods
|
|
//
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScShowScopePane
|
|
*
|
|
* Shows or hides the scope pane in the current view. If fForce is true,
|
|
* we'll go through the motions of showing the scope pane even if we think
|
|
* its visibility state wouldn't change.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScShowScopePane (bool fShow, bool fForce /* =false */)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScShowScopePane"));
|
|
|
|
/*
|
|
* if the current visibility state doesn't match the requested state,
|
|
* change the current state to match the requested state
|
|
*/
|
|
if (fForce || (IsScopePaneVisible() != fShow))
|
|
{
|
|
/*
|
|
* If MMC_NW_OPTION_NOSCOPEPANE was specified when this view was
|
|
* created, we can't display a scope pane. If we're asked to, fail.
|
|
*/
|
|
if (fShow && !IsScopePaneAllowed())
|
|
return (sc = E_FAIL);
|
|
|
|
/*
|
|
* if the scope pane is being hidden and it contained the active
|
|
* view, activate the result pane
|
|
*/
|
|
if (!fShow && (GetFocusedPane() == ePane_ScopeTree))
|
|
ScSetFocusToResultPane (); // ignore errors here
|
|
|
|
/*
|
|
* remember the new state
|
|
*/
|
|
SetScopePaneVisible (fShow);
|
|
|
|
/*
|
|
* Don't defer this layout. This may be called by the Customize View
|
|
* dialog which wants to see its updates in real time. It will be
|
|
* sitting in a modal message loop so we won't get a chance to precess
|
|
* our idle task.
|
|
*/
|
|
RecalcLayout();
|
|
|
|
/*
|
|
* the console has changed
|
|
*/
|
|
SetDirty();
|
|
}
|
|
|
|
/*
|
|
* put the scope pane toolbar button in the right state
|
|
*/
|
|
CStandardToolbar* pStdToolbar = GetStdToolbar();
|
|
sc = ScCheckPointers(pStdToolbar, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
CAMCDoc *pDoc = GetDocument();
|
|
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
bool bEnableScopePaneButton = (IsScopePaneAllowed() && pDoc->AllowViewCustomization());
|
|
|
|
// IF view customization is not allowed then "Show/Hide Consolte tree" button should be hidden.
|
|
if (bEnableScopePaneButton)
|
|
{
|
|
/*
|
|
* the scope pane is permitted; show and check the toolbar
|
|
* button if the scope pane is visible, show and uncheck the
|
|
* toolbar button if the scope pane is hidden
|
|
*/
|
|
sc = pStdToolbar->ScCheckScopePaneBtn (fShow);
|
|
if (sc)
|
|
return (sc);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* no scope pane permitted, hide the scope pane button
|
|
*/
|
|
sc = pStdToolbar->ScEnableScopePaneBtn (bEnableScopePaneButton);
|
|
if (sc)
|
|
return (sc);
|
|
}
|
|
|
|
/*
|
|
* if we get to this point, the current state should match the requested state
|
|
*/
|
|
ASSERT (IsScopePaneVisible() == fShow);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::CDeferredLayout
|
|
*
|
|
* Constructs a CAMCView::CDeferredLayout::CDeferredLayout. Note that if
|
|
* an error occurs during construction, an SC exception will be thrown.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CAMCView::CDeferredLayout::CDeferredLayout (CAMCView* pAMCView)
|
|
: m_atomTask (AddAtom (_T("CAMCView::CDeferredLayout")))
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::CDeferredLayout::CDeferredLayout"));
|
|
|
|
if (!Attach (pAMCView))
|
|
(sc = E_INVALIDARG).Throw();
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::~CDeferredLayout
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
CAMCView::CDeferredLayout::~CDeferredLayout()
|
|
{
|
|
DeleteAtom (m_atomTask);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::ScDoWork
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::CDeferredLayout::ScDoWork()
|
|
{
|
|
WindowCollection::iterator it;
|
|
WindowCollection::iterator itEnd = m_WindowsToLayout.end();
|
|
|
|
for (it = m_WindowsToLayout.begin(); it != itEnd; ++it)
|
|
{
|
|
CWnd* pwnd = CWnd::FromHandlePermanent (*it);
|
|
CAMCView* pAMCView = dynamic_cast<CAMCView*>(pwnd);
|
|
|
|
if (pAMCView != NULL)
|
|
{
|
|
pAMCView->RecalcLayout();
|
|
pAMCView->Invalidate();
|
|
pAMCView->UpdateWindow();
|
|
}
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::ScGetTaskID
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::CDeferredLayout::ScGetTaskID(ATOM* pID)
|
|
{
|
|
*pID = m_atomTask;
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::ScMerge
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::CDeferredLayout::ScMerge(CIdleTask* pitMergeFrom)
|
|
{
|
|
CDeferredLayout* pdlMergeFrom = dynamic_cast<CDeferredLayout*>(pitMergeFrom);
|
|
ASSERT (pdlMergeFrom != NULL);
|
|
|
|
/*
|
|
* copy the windows from the merge-from task into the merge-to task
|
|
*/
|
|
WindowCollection::iterator it;
|
|
WindowCollection::iterator itEnd = pdlMergeFrom->m_WindowsToLayout.end();
|
|
|
|
for (it = pdlMergeFrom->m_WindowsToLayout.begin(); it != itEnd; ++it)
|
|
{
|
|
m_WindowsToLayout.insert (*it);
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CDeferredLayout::Attach
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
bool CAMCView::CDeferredLayout::Attach (CAMCView* pAMCView)
|
|
{
|
|
ASSERT (pAMCView != NULL);
|
|
|
|
HWND hwndAMCView = pAMCView->GetSafeHwnd();
|
|
|
|
if (hwndAMCView != NULL)
|
|
m_WindowsToLayout.insert (hwndAMCView);
|
|
|
|
return (hwndAMCView != NULL);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::DeferRecalcLayout
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::DeferRecalcLayout (bool fUseIdleTaskQueue /* =true */, bool bArrangeIcons /* = false*/)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::DeferRecalcLayout"));
|
|
|
|
if (fUseIdleTaskQueue)
|
|
{
|
|
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (idle task)"));
|
|
try
|
|
{
|
|
/*
|
|
* get the idle task manager
|
|
*/
|
|
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
|
|
if (pIdleTaskQueue == NULL)
|
|
(sc = E_UNEXPECTED).Throw();
|
|
|
|
/*
|
|
* create the deferred layout task
|
|
*/
|
|
CAutoPtr<CDeferredLayout> spDeferredLayout (new CDeferredLayout (this));
|
|
if (spDeferredLayout == NULL)
|
|
(sc = E_OUTOFMEMORY).Throw();
|
|
|
|
/*
|
|
* put the task in the queue, which will take ownership of it
|
|
*/
|
|
sc = pIdleTaskQueue->ScPushTask (spDeferredLayout, ePriority_Normal);
|
|
if (sc)
|
|
sc.Throw();
|
|
|
|
/*
|
|
* if we get here, the idle task queue owns the idle task, so
|
|
* we can detach it from our smart pointer
|
|
*/
|
|
spDeferredLayout.Detach();
|
|
|
|
/*
|
|
* jiggle the message pump so that it wakes up and checks idle tasks
|
|
*/
|
|
PostMessage (WM_NULL);
|
|
}
|
|
catch (SC& scCaught)
|
|
{
|
|
/*
|
|
* if we failed to enqueue our deferred layout task, do the layout now
|
|
*/
|
|
RecalcLayout();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* post a message instead of using the idle task queue
|
|
*/
|
|
else
|
|
{
|
|
/*
|
|
* we only need to post a message if there's not one in the queue
|
|
* already
|
|
*/
|
|
MSG msg;
|
|
|
|
if (!PeekMessage (&msg, GetSafeHwnd(),
|
|
m_nDeferRecalcLayoutMsg,
|
|
m_nDeferRecalcLayoutMsg,
|
|
PM_NOREMOVE))
|
|
{
|
|
PostMessage (m_nDeferRecalcLayoutMsg, bArrangeIcons);
|
|
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (posted message)"));
|
|
}
|
|
else
|
|
{
|
|
Trace (tagLayout, _T("CAMCView::DeferRecalcLayout (skipping redundant posted message)"));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RecalcLayout
|
|
//
|
|
// Synopsis: Calls methods to layout control and paint borders and splitters.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CAMCView::RecalcLayout(void)
|
|
{
|
|
TRACE_METHOD(CAMCView, RecalcLayout);
|
|
ASSERT_VALID(this);
|
|
Trace (tagLayout, _T("CAMCView::RecalcLayout"));
|
|
|
|
/*
|
|
* short out if the client rect is empty
|
|
*/
|
|
CRect rectClient;
|
|
GetClientRect (rectClient);
|
|
|
|
if (rectClient.IsRectEmpty())
|
|
return;
|
|
|
|
CDeferWindowPos dwp (10);
|
|
|
|
LayoutScopePane (dwp, rectClient);
|
|
LayoutResultPane (dwp, rectClient);
|
|
|
|
/*
|
|
* CDeferWindowPos dtor will position the windows
|
|
*/
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::LayoutScopePane
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::LayoutScopePane (CDeferWindowPos& dwp, CRect& rectRemaining)
|
|
{
|
|
int cxScope = 0;
|
|
|
|
// If a scope pane is visible
|
|
if (IsScopePaneVisible())
|
|
{
|
|
int cxTotal = rectRemaining.Width();
|
|
|
|
// get the current width
|
|
cxScope = m_PaneInfo[ePane_ScopeTree].cx;
|
|
|
|
// if not determined yet, set scope pane width to 1/4 of window
|
|
if (cxScope == -1)
|
|
cxScope = cxTotal / 3;
|
|
|
|
/*
|
|
* Bug 86718: Make sure we leave at least the minimum width
|
|
* for the result pane, which is always visible
|
|
*/
|
|
cxScope = std::_MIN (cxScope, cxTotal - m_PaneInfo[ePane_Results].cxMin - m_cxSplitter);
|
|
|
|
/*
|
|
* remember the scope pane width
|
|
*/
|
|
m_PaneInfo[ePane_ScopeTree].cx = cxScope;
|
|
}
|
|
|
|
CRect rectScope = rectRemaining;
|
|
rectScope.right = rectScope.left + cxScope;
|
|
|
|
|
|
/*
|
|
* remove space used by the scope pane
|
|
* (and splitter) from the remaining area
|
|
*/
|
|
if (IsScopePaneVisible())
|
|
{
|
|
m_rectVSplitter.left = rectScope.right;
|
|
m_rectVSplitter.top = rectScope.top;
|
|
m_rectVSplitter.right = rectScope.right + m_cxSplitter;
|
|
m_rectVSplitter.bottom = rectScope.bottom;
|
|
|
|
rectRemaining.left = m_rectVSplitter.right;
|
|
|
|
/*
|
|
* Inflate the splitter rect to give a little bigger hot area.
|
|
* We need to do this logically instead of physically (i.e. instead
|
|
* of increasing m_cxSplitter) to keep the visuals right.
|
|
*/
|
|
m_rectVSplitter.InflateRect (GetSystemMetrics (SM_CXEDGE), 0);
|
|
|
|
}
|
|
else
|
|
m_rectVSplitter = g_rectEmpty;
|
|
|
|
|
|
/*
|
|
* scope pane
|
|
*/
|
|
dwp.AddWindow (GetPaneView(ePane_ScopeTree), rectScope,
|
|
SWP_NOZORDER | SWP_NOACTIVATE |
|
|
(IsScopePaneVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::LayoutResultPane
|
|
*
|
|
* Lays out the children of the result pane.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::LayoutResultPane (CDeferWindowPos& dwp, CRect& rectRemaining)
|
|
{
|
|
/*
|
|
* Note: the order of these calls to LayoutXxx is *critical*.
|
|
*/
|
|
LayoutResultDescriptionBar (dwp, rectRemaining);
|
|
LayoutResultFolderTabView (dwp, rectRemaining);
|
|
|
|
m_rectResultFrame = rectRemaining;
|
|
|
|
LayoutResultView (dwp, rectRemaining);
|
|
|
|
/*
|
|
* remember the final width of the result pane in m_PaneInfo[ePane_Results].cx
|
|
*/
|
|
m_PaneInfo[ePane_Results].cx = m_rectResultFrame.Width();
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::LayoutResultFolderTabView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::LayoutResultFolderTabView (CDeferWindowPos& dwp, CRect& rectRemaining)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::LayoutResultFolderTabView"));
|
|
|
|
sc = ScCheckPointers(m_pResultFolderTabView, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
// layout the folder tab control - always on top.
|
|
bool bVisible = AreTaskpadTabsAllowed() && m_pResultFolderTabView->IsVisible();
|
|
|
|
CRect rectFolder;
|
|
|
|
if (bVisible)
|
|
m_pResultFolderTabView->Layout(rectRemaining, rectFolder);
|
|
else
|
|
rectFolder = g_rectEmpty;
|
|
|
|
DWORD dwPosFlags = SWP_NOZORDER | SWP_NOACTIVATE |
|
|
(bVisible ? SWP_SHOWWINDOW : SWP_HIDEWINDOW);
|
|
dwp.AddWindow (m_pResultFolderTabView, rectFolder, dwPosFlags);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::LayoutResultDescriptionBar
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::LayoutResultDescriptionBar (CDeferWindowPos& dwp, CRect& rectRemaining)
|
|
{
|
|
DWORD dwPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
|
|
CRect rectT = rectRemaining;
|
|
|
|
if (IsDescBarVisible() && !rectT.IsRectEmpty())
|
|
{
|
|
rectT.bottom = rectT.top + m_RightDescCtrl.GetHeight();
|
|
rectRemaining.top = rectT.bottom;
|
|
dwPosFlags |= SWP_SHOWWINDOW;
|
|
}
|
|
else
|
|
{
|
|
dwPosFlags |= SWP_HIDEWINDOW;
|
|
}
|
|
|
|
dwp.AddWindow (&m_RightDescCtrl, rectT, dwPosFlags);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::LayoutResultView
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::LayoutResultView (CDeferWindowPos& dwp, const CRect& rectRemaining)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::LayoutResultView"));
|
|
Trace (tagLayout, _T("CAMCView::LayoutResultView"));
|
|
CWnd* pwndResult = GetPaneView(ePane_Results);
|
|
|
|
/*
|
|
* we should never think the view is extended if we don't also have
|
|
* a view extension web host control
|
|
*/
|
|
ASSERT (!(m_fViewExtended && (m_pViewExtensionCtrl == NULL)));
|
|
|
|
/*
|
|
* if it exists, the view extension control is always at the bottom of
|
|
* the Z-order, and visible if the view is being extended
|
|
*/
|
|
if(m_pViewExtensionCtrl != NULL)
|
|
{
|
|
/*
|
|
* note no SWP_NOZORDER
|
|
*/
|
|
DWORD dwPosFlags = SWP_NOACTIVATE | ((m_fViewExtended)
|
|
? SWP_SHOWWINDOW
|
|
: SWP_HIDEWINDOW);
|
|
|
|
dwp.AddWindow (m_pViewExtensionCtrl, rectRemaining,
|
|
dwPosFlags, &CWnd::wndBottom);
|
|
}
|
|
|
|
/*
|
|
* If the view's not extended, show or hide the result window based on
|
|
* whether there's any room left in the positioning rectangle. (If the
|
|
* view is extended, the result window will have been hidden when the
|
|
* view extension was applied (in ScApplyViewExtension), and possibly
|
|
* redisplayed by the extension in ScSetViewExtensionFrame.)
|
|
*/
|
|
if (!m_fViewExtended)
|
|
{
|
|
DWORD dwFlags = SWP_NOZORDER | SWP_NOACTIVATE |
|
|
(rectRemaining.IsRectEmpty() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW);
|
|
|
|
dwp.AddWindow (pwndResult, rectRemaining, dwFlags);
|
|
}
|
|
|
|
/*
|
|
* lists in extended views and listpads don't get a border, all others do
|
|
*/
|
|
if (HasListOrListPad())
|
|
{
|
|
if (HasListPad())
|
|
{
|
|
sc = ScCheckPointers (m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
CWnd* pwndListCtrl = m_pListCtrl->GetListViewPtr();
|
|
sc = ScCheckPointers (pwndListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
pwndListCtrl->ModifyStyleEx (WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED); // remove border
|
|
}
|
|
|
|
else if (m_fViewExtended)
|
|
pwndResult->ModifyStyleEx (WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED); // remove border
|
|
else
|
|
pwndResult->ModifyStyleEx (0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED); // add border
|
|
}
|
|
}
|
|
|
|
//
|
|
// Tracking and and hit testing methods
|
|
//
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: HitTestPane
|
|
//
|
|
// Synopsis: Test which pane contains the point arg, or ePane_None for
|
|
// the splitter bar
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int CAMCView::HitTestPane(CPoint& point)
|
|
{
|
|
TRACE_METHOD(CAMCView, HitTestPane);
|
|
|
|
if (PtInWindow(m_pTreeCtrl, point))
|
|
return ePane_ScopeTree;
|
|
|
|
if (m_PaneInfo[ePane_Results].pView &&
|
|
PtInWindow(m_PaneInfo[ePane_Results].pView, point))
|
|
return ePane_Results;
|
|
|
|
return ePane_None;
|
|
}
|
|
|
|
|
|
HNODE CAMCView::GetSelectedNode(void)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
TRACE_METHOD(CAMCView, GetSelectedNode);
|
|
|
|
// When the tree is empty we don't want to AV
|
|
HTREEITEM hti = m_pTreeCtrl->GetSelectedItem();
|
|
if (hti == NULL)
|
|
return NULL;
|
|
|
|
HNODE hNode = m_pTreeCtrl->GetItemNode(hti);
|
|
return hNode;
|
|
}
|
|
|
|
|
|
HNODE CAMCView::GetRootNode(void)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetSelectedNode);
|
|
|
|
// When the tree is empty we don't want to AV
|
|
HTREEITEM hti = m_pTreeCtrl->GetRootItem();
|
|
if (hti == NULL)
|
|
return NULL;
|
|
|
|
HNODE hNode = m_pTreeCtrl->GetItemNode(hti);
|
|
return hNode;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScUpdateWindowTitle
|
|
*
|
|
* PURPOSE: Updates the window title and informs observers about the change.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScUpdateWindowTitle()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScUpdateWindowTitle"));
|
|
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
|
|
sc = ScCheckPointers(pFrame);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (pFrame)
|
|
pFrame->OnUpdateFrameTitle(TRUE);
|
|
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnViewTitleChanged, this);
|
|
|
|
return sc;
|
|
}
|
|
|
|
BOOL CAMCView::RenameItem(HNODE hNode, BOOL bScopeItem, MMC_COOKIE lResultItemCookie,
|
|
LPWSTR pszText, LRESULT* pResult)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::RenameItem"));
|
|
|
|
sc = S_FALSE;
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
|
|
selInfo.m_bScope = bScopeItem;
|
|
selInfo.m_lCookie = lResultItemCookie;
|
|
|
|
if (pszText != NULL)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
/*
|
|
* Bug 322184: The snap-in may throw up some UI on this notification.
|
|
* The list or tree may have captured the mouse to look for a drag,
|
|
* which will interfere with the snap-in's UI. Release the capture
|
|
* during the callback and put it back when we're done.
|
|
*/
|
|
HWND hwndCapture = ::SetCapture (NULL);
|
|
|
|
sc = m_spNodeCallback->Notify(hNode, NCLBK_RENAME,
|
|
reinterpret_cast<LPARAM>(&selInfo), reinterpret_cast<LPARAM>(pszText));
|
|
|
|
/*
|
|
* put the capture back
|
|
*/
|
|
::SetCapture (hwndCapture);
|
|
}
|
|
|
|
*pResult = (sc == SC(S_OK));
|
|
if (*pResult)
|
|
{
|
|
sc = ScUpdateWindowTitle();
|
|
if(sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CAMCView::DispatchListCtrlNotificationMsg(LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::DispatchListCtrlNotificationMsg"));
|
|
|
|
TRACE_METHOD(CAMCView, DispatchListCtrlNotificationMsg);
|
|
|
|
NM_LISTVIEW *pNm = reinterpret_cast<NM_LISTVIEW*>(lParam);
|
|
BOOL bReturn = TRUE;
|
|
|
|
switch (pNm->hdr.code)
|
|
{
|
|
case NM_RCLICK:
|
|
bReturn = FALSE; // In case of right click send the select notification to the snapin
|
|
// but return FALSE so that message is further processed to display
|
|
// context menu.
|
|
|
|
// Fall thro into NM_CLICK
|
|
case NM_CLICK:
|
|
{
|
|
sc = ScOnLeftOrRightMouseClickInListView();
|
|
if (sc)
|
|
return bReturn;
|
|
}
|
|
break;
|
|
|
|
case NM_DBLCLK:
|
|
OnListCtrlItemDblClk();
|
|
break;
|
|
|
|
case NM_CUSTOMDRAW:
|
|
*pResult = m_pListCtrl->OnCustomDraw (
|
|
reinterpret_cast<NMLVCUSTOMDRAW *>(lParam));
|
|
break;
|
|
|
|
case LVN_BEGINLABELEDITA:
|
|
case LVN_BEGINLABELEDITW:
|
|
{
|
|
CMainFrame* pFrame = AMCGetMainWnd();
|
|
|
|
if ((pFrame != NULL) && (IsVerbEnabled(MMC_VERB_RENAME) ||
|
|
m_bRenameListPadItem == true))
|
|
{
|
|
pFrame->SetInRenameMode(true);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case LVN_ENDLABELEDITW:
|
|
case LVN_ENDLABELEDITA:
|
|
{
|
|
CMainFrame* pFrame = AMCGetMainWnd();
|
|
if (pFrame != NULL)
|
|
pFrame->SetInRenameMode(false);
|
|
|
|
LPARAM lResultParam = 0;
|
|
long index = -1;
|
|
LPWSTR pszText = NULL;
|
|
|
|
if (pNm->hdr.code == LVN_ENDLABELEDITW)
|
|
{
|
|
LV_DISPINFOW* pdi = (LV_DISPINFOW*) lParam;
|
|
index = pdi->item.iItem;
|
|
pszText = pdi->item.pszText;
|
|
lResultParam = pdi->item.lParam;
|
|
}
|
|
else // if (pNm->hdr.code == LVN_ENDLABELEDIT)
|
|
{
|
|
LV_DISPINFO* pdi = (LV_DISPINFO*) lParam;
|
|
index = pdi->item.iItem;
|
|
USES_CONVERSION;
|
|
pszText = T2W(pdi->item.pszText);
|
|
lResultParam = pdi->item.lParam;
|
|
}
|
|
|
|
if (IsVirtualList())
|
|
{
|
|
// for virtual list pass the item index rather than the lparam
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
RenameItem(hNodeSel, FALSE, index, pszText, pResult);
|
|
}
|
|
else
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle (lResultParam);
|
|
|
|
if (pri != NULL)
|
|
{
|
|
if (pri->IsScopeItem())
|
|
RenameItem(pri->GetScopeNode(), TRUE, 0, pszText, pResult);
|
|
else
|
|
RenameItem(GetSelectedNode(), FALSE, pri->GetSnapinData(), pszText, pResult);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case LVN_GETDISPINFOW:
|
|
{
|
|
LV_DISPINFOW *pDispInfo = reinterpret_cast<LV_DISPINFOW*>(lParam);
|
|
|
|
// If column is hidden do not forward the call to snapin.
|
|
if (m_pListCtrl && m_pListCtrl->IsColumnHidden(pDispInfo->item.iSubItem))
|
|
break;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
if (hNode)
|
|
m_spNodeCallback->GetDispInfo (GetSelectedNode(), &pDispInfo->item);
|
|
else
|
|
bReturn = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
case LVN_GETDISPINFOA:
|
|
{
|
|
LV_DISPINFOA *pDispInfo = reinterpret_cast<LV_DISPINFOA*>(lParam);
|
|
ASSERT (pDispInfo != NULL);
|
|
|
|
// If column is hidden do not forward the call to snapin.
|
|
if (m_pListCtrl && m_pListCtrl->IsColumnHidden(pDispInfo->item.iSubItem))
|
|
break;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
if (! hNode)
|
|
{
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* put the data in the UNICODE structure for the query
|
|
*/
|
|
LV_ITEMW lviW;
|
|
lviW.mask = pDispInfo->item.mask;
|
|
lviW.iItem = pDispInfo->item.iItem;
|
|
lviW.iSubItem = pDispInfo->item.iSubItem;
|
|
lviW.state = pDispInfo->item.state;
|
|
lviW.stateMask = pDispInfo->item.stateMask;
|
|
lviW.cchTextMax = pDispInfo->item.cchTextMax;
|
|
lviW.iImage = pDispInfo->item.iImage;
|
|
lviW.lParam = pDispInfo->item.lParam;
|
|
lviW.iIndent = pDispInfo->item.iIndent;
|
|
|
|
if (pDispInfo->item.mask & LVIF_TEXT)
|
|
lviW.pszText = new WCHAR[pDispInfo->item.cchTextMax];
|
|
|
|
/*
|
|
* convert to ANSI
|
|
*/
|
|
if (SUCCEEDED (m_spNodeCallback->GetDispInfo (GetSelectedNode(), &lviW)) &&
|
|
(pDispInfo->item.mask & LVIF_TEXT))
|
|
{
|
|
WideCharToMultiByte (CP_ACP, 0, lviW.pszText, -1,
|
|
pDispInfo->item.pszText,
|
|
pDispInfo->item.cchTextMax,
|
|
NULL, NULL);
|
|
}
|
|
|
|
if (pDispInfo->item.mask & LVIF_TEXT)
|
|
delete [] lviW.pszText;
|
|
|
|
/*
|
|
* copy the results back to the ANSI structure
|
|
*/
|
|
pDispInfo->item.mask = lviW.mask;
|
|
pDispInfo->item.iItem = lviW.iItem;
|
|
pDispInfo->item.iSubItem = lviW.iSubItem;
|
|
pDispInfo->item.state = lviW.state;
|
|
pDispInfo->item.stateMask = lviW.stateMask;
|
|
pDispInfo->item.cchTextMax = lviW.cchTextMax;
|
|
pDispInfo->item.iImage = lviW.iImage;
|
|
pDispInfo->item.lParam = lviW.lParam;
|
|
pDispInfo->item.iIndent = lviW.iIndent;
|
|
break;
|
|
}
|
|
|
|
case LVN_DELETEALLITEMS:
|
|
// return TRUE to prevent notification for each item
|
|
return TRUE;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
bReturn = OnListItemChanged (pNm);
|
|
break;
|
|
|
|
case LVN_ODSTATECHANGED:
|
|
// The state of an item or range of items has changed in virtual list.
|
|
return OnVirtualListItemsStateChanged(reinterpret_cast<LPNMLVODSTATECHANGE>(lParam));
|
|
break;
|
|
|
|
case LVN_ODFINDITEMA:
|
|
case LVN_ODFINDITEMW:
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
NM_FINDITEM *pNmFind = reinterpret_cast<NM_FINDITEM*>(lParam);
|
|
ASSERT(IsVirtualList() && (pNmFind->lvfi.flags & LVFI_STRING));
|
|
|
|
LPOLESTR polestr = NULL;
|
|
if (pNm->hdr.code == LVN_ODFINDITEMW)
|
|
{
|
|
LVFINDINFOW* pfiw = reinterpret_cast<LVFINDINFOW*>(&pNmFind->lvfi);
|
|
polestr = const_cast<LPOLESTR>(pfiw->psz);
|
|
}
|
|
else
|
|
{
|
|
LVFINDINFOA* pfi = reinterpret_cast<LVFINDINFOA*>(&pNmFind->lvfi);
|
|
polestr = A2W(const_cast<LPSTR>(pfi->psz));
|
|
}
|
|
Dbg(DEB_USER1, _T("\n********************** polestr = %ws\n"), polestr);
|
|
RESULTFINDINFO findInfo;
|
|
findInfo.psz = polestr;
|
|
findInfo.nStart = pNmFind->iStart;
|
|
findInfo.dwOptions = 0;
|
|
|
|
// Listview bug: LVFI_SUBSTRING is not defined in the SDK headers and the
|
|
// listview sets it instead of LVFI_PARTIAL when it wants a
|
|
// partial match. So for now, define it here and test for both.
|
|
#define LVFI_SUBSTRING 0x0004
|
|
|
|
if (pNmFind->lvfi.flags & (LVFI_PARTIAL | LVFI_SUBSTRING))
|
|
findInfo.dwOptions |= RFI_PARTIAL;
|
|
|
|
if (pNmFind->lvfi.flags & LVFI_WRAP)
|
|
findInfo.dwOptions |= RFI_WRAP;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
pNC->Notify(hNodeSel, NCLBK_FINDITEM,
|
|
reinterpret_cast<LPARAM>(&findInfo),
|
|
reinterpret_cast<LPARAM>(pResult));
|
|
}
|
|
break;
|
|
|
|
case LVN_ODCACHEHINT:
|
|
{
|
|
NM_CACHEHINT *pNmHint = reinterpret_cast<NM_CACHEHINT*>(lParam);
|
|
|
|
ASSERT(IsVirtualList());
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
pNC->Notify(hNodeSel, NCLBK_CACHEHINT, pNmHint->iFrom, pNmHint->iTo);
|
|
}
|
|
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
{
|
|
NMLVKEYDOWN *pNmKeyDown = reinterpret_cast<NMLVKEYDOWN*>(lParam);
|
|
|
|
switch (pNmKeyDown->wVKey)
|
|
{
|
|
case VK_DELETE:
|
|
{
|
|
if (!IsVerbEnabled(MMC_VERB_DELETE))
|
|
break;
|
|
|
|
INodeCallback* pCallback = GetNodeCallback();
|
|
ASSERT(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
break;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
if (hNode == 0)
|
|
break;
|
|
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
ASSERT(cSel >= 0);
|
|
|
|
LPARAM lvData;
|
|
if (cSel == 0)
|
|
{
|
|
break;
|
|
}
|
|
else if (cSel == 1)
|
|
{
|
|
if (_GetLVSelectedItemData(&lvData) == -1)
|
|
break;
|
|
}
|
|
else if (cSel > 1)
|
|
{
|
|
lvData = LVDATA_MULTISELECT;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
pCallback->Notify(hNode, NCLBK_DELETE, FALSE, lvData);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case VK_TAB:
|
|
GetParentFrame()->SetActiveView (m_pTreeCtrl);
|
|
break;
|
|
|
|
case VK_BACK:
|
|
ScUpOneLevel();
|
|
break;
|
|
|
|
case VK_RETURN:
|
|
if(GetKeyState(VK_MENU)<0) // has the ALT key been pressed?
|
|
{
|
|
// Process <ALT><ENTER>
|
|
if (! IsVerbEnabled(MMC_VERB_PROPERTIES))
|
|
break;
|
|
|
|
LPARAM lvData = 0;
|
|
|
|
if (HasList())
|
|
{
|
|
ASSERT (m_pListCtrl != NULL);
|
|
ASSERT (GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr());
|
|
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
ASSERT(cSel >= 0);
|
|
|
|
lvData = LVDATA_ERROR;
|
|
if (cSel == 0)
|
|
lvData = LVDATA_BACKGROUND;
|
|
else if (cSel == 1)
|
|
_GetLVSelectedItemData(&lvData);
|
|
else if (cSel > 1)
|
|
lvData = LVDATA_MULTISELECT;
|
|
|
|
ASSERT(lvData != LVDATA_ERROR);
|
|
if (lvData == LVDATA_ERROR)
|
|
break;
|
|
|
|
if (lvData == LVDATA_BACKGROUND)
|
|
break;
|
|
}
|
|
else if (HasOCX())
|
|
{
|
|
lvData = LVDATA_CUSTOMOCX;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(HasWebBrowser());
|
|
lvData = LVDATA_CUSTOMWEB;
|
|
}
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
if (pNC == NULL)
|
|
break;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
ASSERT(hNodeSel != NULL);
|
|
if (hNodeSel == NULL)
|
|
break;
|
|
|
|
pNC->Notify(hNodeSel, NCLBK_PROPERTIES, FALSE, lvData);
|
|
break;
|
|
}
|
|
else // nope, the ALT key has not been pressed.
|
|
{
|
|
// do the default verb.
|
|
OnListCtrlItemDblClk();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bReturn = OnSharedKeyDown(pNmKeyDown->wVKey);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScOnLeftOrRightMouseClickInListView
|
|
//
|
|
// Synopsis: Left or right mouse button is clicked on the list view, see
|
|
// if it is clicked on list-view background. If so send a select.
|
|
//
|
|
// Click on list view background is treated as scope owner item selected.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScOnLeftOrRightMouseClickInListView()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnLeftOrRightMouseClickInListView"));
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
|
|
sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CPoint pt;
|
|
GetCursorPos(&pt);
|
|
pAMCListView->ScreenToClient(&pt);
|
|
|
|
UINT uFlags = 0;
|
|
int iItem = pAMCListView->GetListCtrl().HitTest(pt, &uFlags);
|
|
Dbg(DEB_USER1, _T("----- HitTest > %d \n"), iItem);
|
|
|
|
// Make sure mouse click is in the ListView and there are
|
|
// no items selected in the list view.
|
|
if ( (iItem == -1) &&
|
|
!(uFlags & (LVHT_ABOVE | LVHT_BELOW | LVHT_TOLEFT | LVHT_TORIGHT) ) &&
|
|
(m_pListCtrl->GetSelectedCount() == 0) )
|
|
{
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = TRUE;
|
|
selInfo.m_bDueToFocusChange = TRUE;
|
|
selInfo.m_bBackground = TRUE;
|
|
selInfo.m_lCookie = LVDATA_BACKGROUND;
|
|
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnListItemChanged
|
|
*
|
|
* WM_NOTIFY (LVN_ITEMCHANGED) handler for CAMCView.
|
|
*
|
|
* return true as message is handled here.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
bool CAMCView::OnListItemChanged (NM_LISTVIEW* pnmlv)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::OnListItemChanged"));
|
|
|
|
bool bOldState = (pnmlv->uOldState & LVIS_SELECTED);
|
|
bool bNewState = (pnmlv->uNewState & LVIS_SELECTED);
|
|
|
|
// is this a selection change?
|
|
if ( (pnmlv->uChanged & LVIF_STATE) &&
|
|
(bOldState != bNewState) )
|
|
{
|
|
const int cSelectedItems = m_pListCtrl->GetSelectedCount();
|
|
|
|
#ifdef DBG
|
|
Trace (tagListSelection,
|
|
_T("Item %d %sselected, %d total items selected"),
|
|
pnmlv->iItem,
|
|
(pnmlv->uOldState & LVIS_SELECTED) ? _T("de") : _T(" "),
|
|
cSelectedItems);
|
|
#endif
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
|
|
selInfo.m_bScope = FALSE;
|
|
selInfo.m_pView = NULL;
|
|
selInfo.m_lCookie = IsVirtualList() ? pnmlv->iItem : pnmlv->lParam;
|
|
|
|
/*
|
|
* If user is (de)selecting multiple items using control and/or shift keys
|
|
* then defer the multi-select notification until we're quiescent
|
|
* with the exception of only one item being (de)selected.
|
|
*/
|
|
if ((IsKeyPressed(VK_SHIFT) || IsKeyPressed(VK_CONTROL)) &&
|
|
(GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr()) &&
|
|
(cSelectedItems > 1) )
|
|
{
|
|
// See ScPostMultiSelectionChangesMessage (this handles both selection
|
|
// and de-selection of multiple items).
|
|
sc = ScPostMultiSelectionChangesMessage();
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return (true);
|
|
}
|
|
else
|
|
{
|
|
m_bProcessMultiSelectionChanges = false;
|
|
}
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, (void*) hNodeSel, E_UNEXPECTED);
|
|
if (sc)
|
|
return (true);
|
|
|
|
// item = -1 is only expected for deselect in virtual list
|
|
ASSERT( pnmlv->iItem != -1 || (IsVirtualList() && (pnmlv->uOldState & LVIS_SELECTED)));
|
|
|
|
if (pnmlv->uOldState & LVIS_SELECTED)
|
|
{
|
|
if (cSelectedItems == 0)
|
|
{
|
|
if (!m_bLastSelWasMultiSel)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, false, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
else
|
|
{
|
|
m_bLastSelWasMultiSel = false;
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
}
|
|
else if (m_bLastSelWasMultiSel)
|
|
{
|
|
// may need to cancel multiselect and send single select notify.
|
|
// if another change comes in, it will cancel the delayed message
|
|
// This fixes a problem that is caused by large icon mode not
|
|
// sending as many noifications as the other modes.
|
|
|
|
// See ScPostMultiSelectionChangesMessage (this handles both selection
|
|
// and de-selection of multiple items).
|
|
sc = ScPostMultiSelectionChangesMessage();
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
}
|
|
else if (pnmlv->uNewState & LVIS_SELECTED)
|
|
{
|
|
ASSERT(cSelectedItems >= 1);
|
|
|
|
if (cSelectedItems == 1)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
else
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
m_bLastSelWasMultiSel = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::OnVirtualListItemsStateChanged
|
|
//
|
|
// Synopsis: The state of an item or range of items has changed in virtual list.
|
|
//
|
|
// Arguments: lpStateChange -
|
|
//
|
|
// Returns: should return 0 according to docs.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
int CAMCView::OnVirtualListItemsStateChanged(LPNMLVODSTATECHANGE lpStateChange )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnVirtualListItemsStateChanged"));
|
|
sc = ScCheckPointers(lpStateChange);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return 0;
|
|
}
|
|
|
|
bool bOldState = (lpStateChange->uOldState & LVIS_SELECTED);
|
|
bool bNewState = (lpStateChange->uNewState & LVIS_SELECTED);
|
|
int cItems = (lpStateChange->iTo - lpStateChange->iFrom) + 1;
|
|
|
|
#ifdef DBG
|
|
Trace (tagListSelection,
|
|
_T("Items %d to %d were %sselected, %d total items selected"),
|
|
lpStateChange->iFrom, lpStateChange->iTo,
|
|
bOldState ? _T("de") : _T(" "),
|
|
cItems );
|
|
#endif
|
|
|
|
if (bOldState != bNewState)
|
|
{
|
|
sc = ScPostMultiSelectionChangesMessage();
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScPostMultiSelectionChangesMessage
|
|
//
|
|
// Synopsis: Post selection change message (need to post because multi-sel
|
|
// may not be over, wait till it is quiet.)
|
|
//
|
|
// This method posts message telling selection states of multiple
|
|
// items are changed but not if they are selected or de-selected.
|
|
// The m_bLastSelWasMultiSel is used to determine if it is
|
|
// selection or de-selection.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScPostMultiSelectionChangesMessage ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScPostMultiSelectionChangesMessage"));
|
|
|
|
/*
|
|
* This is a multi-selection, defer notification until we're quiescent
|
|
*/
|
|
m_bProcessMultiSelectionChanges = true;
|
|
PostMessage (m_nProcessMultiSelectionChangesMsg);
|
|
|
|
// We need to disable all the toolbars, menubuttons
|
|
// during multiselect. Above PostMessage enables
|
|
// stdbar and MMC menubuttons.
|
|
CAMCViewToolbarsMgr* pAMCViewToolbarsMgr = m_ViewData.GetAMCViewToolbarsMgr();
|
|
CMenuButtonsMgr* pMenuBtnsMgr = m_ViewData.GetMenuButtonsMgr();
|
|
|
|
sc = ScCheckPointers(pAMCViewToolbarsMgr, pMenuBtnsMgr, E_UNEXPECTED);
|
|
if (sc)
|
|
return 0;
|
|
|
|
pAMCViewToolbarsMgr->ScDisableToolbars();
|
|
pMenuBtnsMgr->ScDisableMenuButtons();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
void CAMCView::OpenResultItem(HNODE hNode)
|
|
{
|
|
/*
|
|
* Bug 139695: Make certain this function doesn't need to change the
|
|
* active view. We should only get here as a result of double- clicking
|
|
* or pressing Enter on a scope node in the result pane, in which case
|
|
* the result pane should already be the active view. If it is, we don't
|
|
* need to change the active view, which can cause the problems listed in
|
|
* the bug.
|
|
*/
|
|
ASSERT (m_pListCtrl != NULL);
|
|
ASSERT (GetParentFrame() != NULL);
|
|
ASSERT (GetParentFrame()->GetActiveView() == m_pListCtrl->GetListViewPtr());
|
|
|
|
ASSERT(m_pTreeCtrl);
|
|
HTREEITEM htiParent = m_pTreeCtrl->GetSelectedItem();
|
|
ASSERT(htiParent != NULL);
|
|
|
|
m_pTreeCtrl->ExpandNode(htiParent);
|
|
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
|
|
|
|
HTREEITEM hti = m_pTreeCtrl->GetChildItem(htiParent);
|
|
|
|
if (hti == NULL)
|
|
return;
|
|
|
|
while (hti)
|
|
{
|
|
if (m_pTreeCtrl->GetItemNode(hti) == hNode)
|
|
break;
|
|
|
|
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
|
|
}
|
|
|
|
if (hti != 0)
|
|
{
|
|
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
|
|
m_pTreeCtrl->SelectItem(hti);
|
|
}
|
|
}
|
|
|
|
BOOL CAMCView::OnListCtrlItemDblClk(void)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnListCtrlItemDblClk);
|
|
|
|
LPARAM lvData = -1;
|
|
if (_GetLVSelectedItemData(&lvData) == -1)
|
|
lvData = LVDATA_BACKGROUND;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
if (!pNC)
|
|
return FALSE;
|
|
|
|
HRESULT hr = pNC->Notify(hNodeSel, NCLBK_DBLCLICK, lvData, 0);
|
|
if (hr == S_FALSE)
|
|
{
|
|
ASSERT(lvData != LVDATA_BACKGROUND);
|
|
if (!IsVirtualList())
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle (lvData);
|
|
|
|
if ((pri != NULL) && pri->IsScopeItem())
|
|
OpenResultItem (pri->GetScopeNode());
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CAMCView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnNotify"));
|
|
|
|
NMHDR *pNmHdr = reinterpret_cast<NMHDR*>(lParam);
|
|
|
|
sc = ScCheckPointers(pNmHdr, pResult);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return CView::OnNotify(wParam, lParam, pResult);
|
|
}
|
|
|
|
*pResult = TRUE; // init
|
|
|
|
switch(pNmHdr->code)
|
|
{
|
|
case HDN_ENDTRACKA: // Save the column width changes.
|
|
case HDN_ENDTRACKW: // HDN_BEGINTRACK handles dis-allowing hidden column dragging.
|
|
{
|
|
NMHEADER* nmh = (NMHEADER*)lParam;
|
|
|
|
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
|
|
SC sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return FALSE;
|
|
}
|
|
|
|
sc = pAMCListView->ScOnColumnsAttributeChanged(nmh, HDN_ENDTRACK);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return FALSE;
|
|
}
|
|
|
|
// S_FALSE : dont allow the change
|
|
if (sc == SC(S_FALSE))
|
|
return TRUE;
|
|
|
|
return CView::OnNotify(wParam, lParam, pResult);
|
|
}
|
|
break;
|
|
|
|
case HDN_ENDDRAG: // Column order changes.
|
|
{
|
|
NMHEADER* nmh = (NMHEADER*)lParam;
|
|
if (nmh->pitem->mask & HDI_ORDER)
|
|
{
|
|
CAMCListView *pAMCListView = m_pListCtrl->GetListViewPtr();
|
|
SC sc = ScCheckPointers(pAMCListView, E_UNEXPECTED);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return FALSE;
|
|
}
|
|
|
|
sc = pAMCListView->ScOnColumnsAttributeChanged(nmh, HDN_ENDDRAG);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return FALSE;
|
|
}
|
|
|
|
// S_FALSE : dont allow the change
|
|
if (sc = SC(S_FALSE))
|
|
return TRUE;
|
|
}
|
|
|
|
return CView::OnNotify(wParam, lParam, pResult);
|
|
}
|
|
break;
|
|
|
|
case TVN_BEGINLABELEDIT:
|
|
{
|
|
TV_DISPINFO* ptvdi = (TV_DISPINFO*)lParam;
|
|
if ((ptvdi->item.lParam == CAMCTreeView::LParamFromNode (GetSelectedNode())) &&
|
|
(IsVerbEnabled(MMC_VERB_RENAME) == FALSE))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
CMainFrame* pFrame = AMCGetMainWnd();
|
|
if (pFrame != NULL)
|
|
pFrame->SetInRenameMode(true);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
case TVN_ENDLABELEDIT:
|
|
{
|
|
TV_DISPINFO* ptvdi = (TV_DISPINFO*)lParam;
|
|
CMainFrame* pFrame = AMCGetMainWnd();
|
|
if (pFrame != NULL)
|
|
pFrame->SetInRenameMode(false);
|
|
|
|
USES_CONVERSION;
|
|
return RenameItem(CAMCTreeView::NodeFromLParam (ptvdi->item.lParam), TRUE, 0,
|
|
T2W(ptvdi->item.pszText), pResult);
|
|
}
|
|
|
|
case TVN_KEYDOWN:
|
|
{
|
|
TV_KEYDOWN* ptvkd = reinterpret_cast<TV_KEYDOWN*>(lParam);
|
|
if (ptvkd->wVKey == VK_TAB)
|
|
{
|
|
ScSetFocusToResultPane();
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return OnSharedKeyDown(ptvkd->wVKey);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (UsingDefColumns() &&
|
|
(pNmHdr->code == HDN_ENDTRACKA || pNmHdr->code == HDN_ENDTRACKW))
|
|
{
|
|
// WARNING: If HD_NOTIFY::pitem::pszText needs to be used you should cast
|
|
// lParam to either HD_NOTIFYA or HD_NOTIFYW depending on the pNmHdr->code
|
|
HD_NOTIFY* phdn = reinterpret_cast<HD_NOTIFY*>(lParam);
|
|
ASSERT(phdn != NULL);
|
|
|
|
if (phdn->pitem->mask & HDI_WIDTH)
|
|
{
|
|
int alWidths[2] = {0, 0};
|
|
GetDefaultColumnWidths(alWidths);
|
|
alWidths[phdn->iItem] = phdn->pitem->cxy;
|
|
SetDefaultColumnWidths(alWidths, FALSE);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
#ifdef DBG
|
|
if (m_pTreeCtrl && m_pTreeCtrl->m_hWnd == pNmHdr->hwndFrom)
|
|
{
|
|
switch (pNmHdr->code)
|
|
{
|
|
case NM_CLICK: Dbg(DEB_USER2, "\t Tree item clicked\n"); break;
|
|
case NM_DBLCLK: Dbg(DEB_USER2, "\t Tree item dbl-clicked\n"); break;
|
|
case NM_RCLICK: Dbg(DEB_USER2, "\t Tree item R-clicked\n"); break;
|
|
default: break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// HasList() is added to prevent dispatching notifications, when AMCView thinks
|
|
// it does not have a list. This lead to wrong assumptions about the list type
|
|
// and as a result - AV handling messages like GetDisplayInfo
|
|
// See BUG 451896
|
|
if (m_pListCtrl && HasListOrListPad())
|
|
{
|
|
if (m_pListCtrl->GetListViewHWND() == pNmHdr->hwndFrom)
|
|
{
|
|
if (DispatchListCtrlNotificationMsg(lParam, pResult) == TRUE)
|
|
return TRUE;
|
|
}
|
|
else if (m_pListCtrl->GetHeaderCtrl() && m_pListCtrl->GetHeaderCtrl()->m_hWnd == pNmHdr->hwndFrom)
|
|
{
|
|
switch(pNmHdr->code)
|
|
{
|
|
case HDN_ITEMCLICKA:
|
|
case HDN_ITEMCLICKW:
|
|
{
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
|
|
HD_NOTIFY* phdn = reinterpret_cast<HD_NOTIFY*>(lParam);
|
|
ASSERT(phdn != NULL);
|
|
int nCol = phdn->iItem;
|
|
|
|
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_COLUMN_CLICKED, 0, nCol);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// filter related code
|
|
case HDN_FILTERCHANGE:
|
|
{
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
int nCol = ((NMHEADER*)lParam)->iItem;
|
|
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTER_CHANGE, MFCC_VALUE_CHANGE, nCol);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case HDN_FILTERBTNCLICK:
|
|
{
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
int nCol = ((NMHDFILTERBTNCLICK*)lParam)->iItem;
|
|
RECT rc = ((NMHDFILTERBTNCLICK*)lParam)->rc;
|
|
|
|
// rect is relative to owning list box, convert to screen
|
|
::MapWindowPoints(m_pListCtrl->GetListViewHWND(), NULL, (LPPOINT)&rc, 2);
|
|
|
|
sc = m_spNodeCallback->Notify(hNodeSel, NCLBK_FILTERBTN_CLICK, nCol, (LPARAM)&rc);
|
|
*pResult = (sc == SC(S_OK));
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return CView::OnNotify(wParam, lParam, pResult);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnMinimize
|
|
*
|
|
* PURPOSE: Send the NCLBK_MINIMIZED notification to the node manager.
|
|
*
|
|
* PARAMETERS:
|
|
* bool fMinimized : TRUE if the window is being minimized, false if maximized.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnMinimize(bool fMinimized)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnMinimize"));
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
if (hNode == NULL)
|
|
return (sc = E_FAIL);
|
|
|
|
INodeCallback* pNodeCallback = GetNodeCallback();
|
|
|
|
if (pNodeCallback == NULL)
|
|
return (sc = E_FAIL);
|
|
|
|
sc = pNodeCallback->Notify (hNode, NCLBK_MINIMIZED, fMinimized, 0);
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnSize
|
|
*
|
|
* PURPOSE: Send the size notification to all
|
|
*
|
|
* PARAMETERS:
|
|
* UINT nType :
|
|
* int cx :
|
|
* int cy :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnSize(UINT nType, int cx, int cy)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnSize"));
|
|
|
|
if (IsPersisted() && GetDocument())
|
|
GetDocument()->SetFrameModifiedFlag(true);
|
|
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnViewResized, this, nType, cx, cy);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScActivate
|
|
*
|
|
* PURPOSE: Sets the view as the active view.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScActivate()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScActivate"));
|
|
|
|
// get the child frame.
|
|
CChildFrame * pChildFrame = GetParentFrame();
|
|
sc = ScCheckPointers(pChildFrame);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (pChildFrame->IsIconic())
|
|
pChildFrame->MDIRestore();
|
|
else
|
|
pChildFrame->MDIActivate(); // activate the child frame.
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
void CAMCView::OnContextMenu(CWnd* pWnd, CPoint point)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnContextMenu);
|
|
|
|
/*
|
|
* make sure this child frame is active
|
|
*/
|
|
CChildFrame* pFrameWnd = GetParentFrame();
|
|
if (NULL == pFrameWnd)
|
|
{
|
|
TRACE(_T("CAMCView::OnContextMenu: failed call to GetParentFrame()\n" ));
|
|
return;
|
|
}
|
|
|
|
pFrameWnd->MDIActivate();
|
|
|
|
if (NULL == m_pTreeCtrl)
|
|
{
|
|
TRACE(_T("CAMCView::OnContextMenu: tree control not ready\n" ));
|
|
return;
|
|
}
|
|
|
|
// (-1,-1) => came from context menu key or Shift-F10
|
|
// Pop-up context for whatever has focus
|
|
if (point.x == -1 && point.y == -1)
|
|
{
|
|
OnShiftF10();
|
|
return;
|
|
}
|
|
|
|
|
|
switch (HitTestPane(point))
|
|
{
|
|
case ePane_Results:
|
|
{
|
|
CPoint pointListCtrlCoord = point;
|
|
CListView* pListView = m_pListCtrl->GetListViewPtr();
|
|
pListView->ScreenToClient(&pointListCtrlCoord);
|
|
|
|
CWnd* pwndHit = pListView->ChildWindowFromPoint (pointListCtrlCoord,
|
|
CWP_SKIPINVISIBLE);
|
|
|
|
/*
|
|
* if the hit window isn't the list view, it must be the list's
|
|
* header window; ignore the context menu request
|
|
*/
|
|
if (pwndHit != pListView)
|
|
{
|
|
TRACE (_T("CAMCView::OnContextMenu: ignore right-click on result pane header\n"));
|
|
break;
|
|
}
|
|
|
|
if (NULL != m_pListCtrl && pWnd->m_hWnd == m_pListCtrl->GetListViewHWND())
|
|
OnListContextMenu(point);
|
|
else
|
|
TRACE(_T("CAMCView::OnContextMenu: result control not ready\n"));
|
|
|
|
// CODEWORK should do something here
|
|
break;
|
|
}
|
|
case ePane_ScopeTree:
|
|
{
|
|
TRACE(_T("CAMCView::OnContextMenu: handle right-click on scope pane\n"));
|
|
CPoint pointTreeCtrlCoord = point;
|
|
m_pTreeCtrl->ScreenToClient(&pointTreeCtrlCoord);
|
|
|
|
OnTreeContextMenu( point, pointTreeCtrlCoord, NULL );
|
|
break;
|
|
}
|
|
case ePane_Tasks:
|
|
// TO BE ADDED - put up taskpad context menu
|
|
break;
|
|
|
|
case ePane_None:
|
|
TRACE(_T("CAMCView::OnContextMenu: ignore right-click on splitter\n"));
|
|
break;
|
|
|
|
default:
|
|
TRACE(_T("CAMCView::OnContextMenu: unexpected return value from HitTestPane()\n"));
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
void CAMCView::OnTreeContextMenu(CPoint& point, CPoint& pointClientCoord, HTREEITEM htiRClicked)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnTreeContextMenu);
|
|
|
|
if (NULL == m_pTreeCtrl)
|
|
{
|
|
TRACE(_T("CAMCTreeView::OnTreeContextMenu: IFrame not ready\n"));
|
|
return;
|
|
}
|
|
|
|
UINT fHitTestFlags = TVHT_ONITEM;
|
|
|
|
if (htiRClicked == NULL)
|
|
htiRClicked = m_pTreeCtrl->HitTest(pointClientCoord, &fHitTestFlags);
|
|
|
|
switch(fHitTestFlags)
|
|
{
|
|
case TVHT_ABOVE:
|
|
case TVHT_BELOW:
|
|
case TVHT_TOLEFT:
|
|
case TVHT_TORIGHT:
|
|
// Outside the tree view area so return without doing anything.
|
|
return;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (NULL == htiRClicked || !(fHitTestFlags & TVHT_ONITEM))
|
|
{
|
|
OnContextMenuForTreeBackground(point);
|
|
}
|
|
else
|
|
{
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(htiRClicked);
|
|
ASSERT(hNode != 0);
|
|
|
|
OnContextMenuForTreeItem(INDEX_INVALID, hNode, point, CCT_SCOPE, htiRClicked);
|
|
}
|
|
}
|
|
|
|
void CAMCView::OnContextMenuForTreeItem(int iIndex, HNODE hNode,
|
|
CPoint& point, DATA_OBJECT_TYPES type_of_pane,
|
|
HTREEITEM htiRClicked, MMC_CONTEXT_MENU_TYPES eMenuType,
|
|
LPCRECT prcExclude, bool bAllowDefaultItem)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnContextMenuForTreeItem);
|
|
DECLARE_SC (sc, _T("CAMCView::OnContextMenuForTreeItem"));
|
|
|
|
ASSERT(hNode != 0);
|
|
CContextMenuInfo contextInfo;
|
|
|
|
contextInfo.m_displayPoint.x = point.x;
|
|
contextInfo.m_displayPoint.y = point.y;
|
|
contextInfo.m_eContextMenuType = eMenuType;
|
|
contextInfo.m_eDataObjectType = CCT_SCOPE;
|
|
contextInfo.m_bBackground = FALSE;
|
|
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
|
|
contextInfo.m_hWnd = m_hWnd;
|
|
contextInfo.m_pConsoleView = this;
|
|
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
|
|
|
|
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
|
|
contextInfo.m_htiRClicked = htiRClicked;
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
|
|
/*
|
|
* if given, initialize the rectangle not to obscure
|
|
*/
|
|
if (prcExclude != NULL)
|
|
contextInfo.m_rectExclude = *prcExclude;
|
|
|
|
|
|
// If selected scope node is same as node for which context menu is
|
|
// needed, then add savelist, view menus
|
|
if (contextInfo.m_hSelectedScopeNode == hNode)
|
|
{
|
|
// Show view owner items
|
|
contextInfo.m_dwFlags |= CMINFO_SHOW_VIEWOWNER_ITEMS;
|
|
|
|
// Don't need to remove temporary selection, since none was applied
|
|
contextInfo.m_pConsoleTree = NULL;
|
|
|
|
if (eMenuType == MMC_CONTEXT_MENU_DEFAULT)
|
|
contextInfo.m_dwFlags |= CMINFO_SHOW_VIEW_ITEMS;
|
|
|
|
if (HasListOrListPad())
|
|
contextInfo.m_dwFlags |= CMINFO_SHOW_SAVE_LIST;
|
|
}
|
|
else if (htiRClicked) // htiRClicked is NULL for tree items in list view.
|
|
{
|
|
// TempNodeSelect == TRUE -> menu is not for the node that owns the result pane
|
|
sc = m_pTreeCtrl->ScSetTempSelection (htiRClicked);
|
|
if (sc)
|
|
return;
|
|
|
|
contextInfo.m_pConsoleTree = m_pTreeCtrl;
|
|
contextInfo.m_dwFlags |= CMINFO_USE_TEMP_VERB;
|
|
}
|
|
|
|
if (htiRClicked)
|
|
contextInfo.m_dwFlags |= CMINFO_DO_SCOPEPANE_MENU;
|
|
else
|
|
contextInfo.m_dwFlags |= CMINFO_SCOPEITEM_IN_RES_PANE;
|
|
|
|
if (HasListOrListPad())
|
|
contextInfo.m_spListView = m_pListCtrl;
|
|
|
|
INodeCallback* spNodeCallback = GetNodeCallback();
|
|
ASSERT(spNodeCallback != NULL);
|
|
|
|
HRESULT hr = spNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
|
|
reinterpret_cast<LPARAM>(&contextInfo));
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::GetTaskpadID
|
|
*
|
|
* PURPOSE: returns the GUID id of the currently selected taskpad.
|
|
*
|
|
* RETURNS:
|
|
* GUID : the taskpad, if any, else GUID_NULL.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::GetTaskpadID(GUID &guidID)
|
|
{
|
|
ITaskCallback * pTaskCallback = m_ViewData.m_spTaskCallback;
|
|
if(pTaskCallback != NULL)
|
|
{
|
|
pTaskCallback->GetTaskpadID(&guidID);
|
|
}
|
|
else
|
|
{
|
|
guidID = GUID_NULL;
|
|
}
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScInitializeMemento
|
|
*
|
|
* PURPOSE: Initializes the memento from the current view.
|
|
*
|
|
* PARAMETERS:
|
|
* CMemento & memento :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScInitializeMemento(CMemento &memento)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScInitializeMemento"));
|
|
|
|
sc = GetSelectedNodePath(&memento.GetBookmark());
|
|
if (sc)
|
|
return sc;
|
|
|
|
GUID guidTaskpad = GUID_NULL;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
// get Result pane stuff from snapin
|
|
CResultViewType rvt;
|
|
sc = GetNodeCallback()->GetResultPane(hNode, rvt, &guidTaskpad /*this is not used*/);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CViewSettings& viewSettings = memento.GetViewSettings();
|
|
|
|
// Initialize the CViewSettings.
|
|
sc = viewSettings.ScSetResultViewType(rvt);
|
|
if (sc)
|
|
return sc;
|
|
|
|
GUID guid;
|
|
GetTaskpadID(guid); // we use this guid instead of guidTaskpad because
|
|
// the memento should contain the taskpad that is currently being displayed.
|
|
sc = viewSettings.ScSetTaskpadID(guid);
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::OnAddToFavorites
|
|
*
|
|
* PURPOSE: Creates a memento from the currently configured view. Saves it into a
|
|
* shortcut.
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void CAMCView::OnAddToFavorites()
|
|
{
|
|
DECLARE_SC(sc , _T("CAMCView::OnAddToFavorites"));
|
|
USES_CONVERSION;
|
|
|
|
CAMCDoc* pDoc = GetDocument();
|
|
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
CMemento memento;
|
|
sc = ScInitializeMemento(memento); // init the memento with the current view settings.
|
|
if(sc)
|
|
return;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
tstring strName;
|
|
sc = GetNodeCallback()->GetDisplayName(hNode, strName);
|
|
if (sc)
|
|
return;
|
|
|
|
HMTNODE hmtNode;
|
|
sc = m_spNodeCallback->GetMTNode(hNode, &hmtNode);
|
|
if (sc)
|
|
return;
|
|
|
|
CCoTaskMemPtr<WCHAR> spszPath;
|
|
sc = pScopeTree->GetPathString(NULL, hmtNode, &spszPath);
|
|
if (sc)
|
|
return;
|
|
|
|
sc = ScCheckPointers(pDoc->GetFavorites(), E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
sc = pDoc->GetFavorites()->AddToFavorites(strName.data(), W2CT(spszPath), memento, this);
|
|
if (sc)
|
|
return;
|
|
|
|
pDoc->SetModifiedFlag();
|
|
}
|
|
|
|
|
|
void CAMCView::OnContextMenuForTreeBackground(CPoint& point, LPCRECT prcExclude, bool bAllowDefaultItem)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnContextMenuForTreeBackground);
|
|
|
|
HNODE hNode = NULL;
|
|
|
|
CContextMenuInfo contextInfo;
|
|
|
|
contextInfo.m_displayPoint.x = point.x;
|
|
contextInfo.m_displayPoint.y = point.y;
|
|
contextInfo.m_eDataObjectType = CCT_SCOPE;
|
|
contextInfo.m_bBackground = TRUE;
|
|
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
|
|
contextInfo.m_hWnd = m_hWnd;
|
|
contextInfo.m_pConsoleView = this;
|
|
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
|
|
|
|
/*
|
|
* if given, initialize the rectangle not to obscure
|
|
*/
|
|
if (prcExclude != NULL)
|
|
contextInfo.m_rectExclude = *prcExclude;
|
|
|
|
INodeCallback* spNodeCallback = GetNodeCallback();
|
|
ASSERT(spNodeCallback != NULL);
|
|
HRESULT hr = spNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
|
|
reinterpret_cast<LPARAM>(&contextInfo));
|
|
}
|
|
|
|
SC CAMCView::ScWebCommand (WebCommand eCommand)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
if (m_pWebViewCtrl == NULL)
|
|
{
|
|
ASSERT (m_pHistoryList);
|
|
if (!m_pHistoryList)
|
|
return FALSE;
|
|
|
|
// this is the case when we don't have a web control yet....
|
|
bool bHandled = false;
|
|
|
|
switch (eCommand)
|
|
{
|
|
case eWeb_Back:
|
|
m_pHistoryList->Back (bHandled);
|
|
ASSERT(bHandled);
|
|
break;
|
|
|
|
case eWeb_Forward:
|
|
m_pHistoryList->Forward (bHandled);
|
|
ASSERT(bHandled);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
switch (eCommand)
|
|
{
|
|
case eWeb_Back: m_pWebViewCtrl->Back(); break;
|
|
case eWeb_Forward: m_pWebViewCtrl->Forward(); break;
|
|
case eWeb_Home: ASSERT(0 && "Should not come here! - remove all code related to Web_Home"); break;
|
|
case eWeb_Refresh: m_pWebViewCtrl->Refresh(); break;
|
|
case eWeb_Stop: m_pWebViewCtrl->Stop(); break;
|
|
default: ASSERT(0); return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScCreateTaskpadHost
|
|
*
|
|
* PURPOSE: Creates a legacy (snapin taskpad) host interface pointer
|
|
*
|
|
* NOTE: When a view containing a taskpad is navigated away from, the amcview
|
|
* forgets about the taskpad host pointer, but the html window does not.
|
|
* When the same view is re-navigated to using History, the amcview needs
|
|
* a taskpad host pointer, so a new instance is created. Thus at this point
|
|
* the amcview and the HTML have pointers to different taskpad host
|
|
* objects. This is OK, because both objects are initialized to the same
|
|
* amcview, and contain no other state
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScCreateTaskpadHost()
|
|
{
|
|
DECLARE_SC(sc , _T("CAMCView::ScCreateTaskpadHost"));
|
|
|
|
if(m_spTaskPadHost != NULL)
|
|
return sc;
|
|
|
|
CComObject<CTaskPadHost>* pTaskPadHost = NULL;
|
|
sc = CComObject<CTaskPadHost>::CreateInstance(&pTaskPadHost);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScCheckPointers (pTaskPadHost, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
pTaskPadHost->Init (this);
|
|
m_spTaskPadHost = pTaskPadHost;
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
LRESULT CAMCView::OnConnectToCIC (WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::OnConnectToCIC"));
|
|
|
|
// fill out wparam, which is an IUnknown ** (alloc'd by CIC)
|
|
ASSERT (wParam != NULL);
|
|
IUnknown ** ppunk = (IUnknown **)wParam;
|
|
ASSERT (!IsBadReadPtr (ppunk, sizeof(IUnknown *)));
|
|
ASSERT (!IsBadWritePtr (ppunk, sizeof(IUnknown *)));
|
|
|
|
sc = ScCheckPointers (ppunk);
|
|
if (sc)
|
|
return (sc.ToHr());
|
|
|
|
// lParam holds MMCCtrl's IUnknown: we can hang onto this if we
|
|
// need it. Presently not saved or used.
|
|
|
|
sc = ScCreateTaskpadHost();
|
|
if(sc)
|
|
return sc.ToHr();
|
|
|
|
sc = ScCheckPointers(m_spTaskPadHost, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc.ToHr();;
|
|
|
|
sc = m_spTaskPadHost->QueryInterface(IID_IUnknown, (void **)ppunk);
|
|
if (sc)
|
|
return (sc.ToHr());
|
|
|
|
return (sc.ToHr());
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::OnGetIconInfoForSelectedNode
|
|
//
|
|
// Synopsis: Icon control sends this message to get the small icon
|
|
// for currently the selected node.
|
|
//
|
|
// Arguments: [wParam] - Out param, ptr to HICON handle.
|
|
// [lParam] - Unused
|
|
//
|
|
// Returns: LRESULT
|
|
//
|
|
//--------------------------------------------------------------------
|
|
LRESULT CAMCView::OnGetIconInfoForSelectedNode(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCView::OnGetIconInfoForSelectedNode"));
|
|
|
|
HICON *phIcon = (HICON*)wParam;
|
|
sc = ScCheckPointers(phIcon);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
*phIcon = NULL;
|
|
|
|
sc = ScCheckPointers(m_pTreeCtrl, m_spNodeCallback, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
sc = m_pTreeCtrl->ScGetTreeItemIconInfo(GetSelectedNode(), phIcon);
|
|
|
|
return sc.ToHr();
|
|
}
|
|
|
|
HRESULT CAMCView::NotifyListPad (BOOL b)
|
|
{
|
|
if (b == TRUE) // attaching: save current node
|
|
m_ListPadNode = GetSelectedNode();
|
|
else if (m_ListPadNode == NULL) // detaching, but no hnode
|
|
return E_UNEXPECTED;
|
|
|
|
// send notify to snapin
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
HRESULT hr = pNC->Notify (m_ListPadNode, NCLBK_LISTPAD, (long)b, (long)0);
|
|
|
|
if (b == FALSE) // if detaching, ensure that we do this only once
|
|
m_ListPadNode = NULL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnConnectToTPLV
|
|
*
|
|
* PURPOSE: Connects the listpad to the HTML frame
|
|
*
|
|
* PARAMETERS:
|
|
* WPARAM wParam : parent window
|
|
* LPARAM lParam : [OUT]: pointer to window to be created and filled out
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnConnectToTPLV(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnConnectToTPLV"));
|
|
|
|
HWND hwnd = (HWND )wParam;
|
|
if(!IsWindow (hwnd))
|
|
return (sc = S_FALSE);
|
|
|
|
if (lParam == NULL) // detaching
|
|
{
|
|
SC sc = m_pListCtrl->ScAttachToListPad (hwnd, NULL);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
else
|
|
{ // attaching
|
|
|
|
sc = ScCreateTaskpadHost();
|
|
if(sc)
|
|
return sc;
|
|
|
|
HWND* phwnd = (HWND*)lParam;
|
|
if (IsBadWritePtr (phwnd, sizeof(HWND *)))
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Attach TaskPad's ListView to the NodeMgr
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = m_pTreeCtrl->m_spNodeManager->SetTaskPadList(m_pListCtrl);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// Attach TaskPad's ListView to the curr selected node
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
sc = pNC->SetTaskPadList(hNodeSel, m_pListCtrl);
|
|
if(sc) // this test was commented out earlier. Uncommented it so we can figure out why.
|
|
return sc;
|
|
|
|
//
|
|
// Attach the listctrl to the list pad.
|
|
//
|
|
|
|
// First set the list view options.
|
|
SetListViewOptions(GetListOptions());
|
|
|
|
sc = m_pListCtrl->ScAttachToListPad (hwnd, phwnd);
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
RecalcLayout();
|
|
return sc;
|
|
}
|
|
|
|
|
|
SC CAMCView::ScShowWebContextMenu ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
PostMessage (m_nShowWebContextMenuMsg);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
LRESULT CAMCView::OnShowWebContextMenu (WPARAM /*wParam*/, LPARAM /*lParam*/)
|
|
{
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
if (pNC)
|
|
pNC->Notify (GetSelectedNode(), NCLBK_WEBCONTEXTMENU, 0, 0);
|
|
|
|
return (0);
|
|
}
|
|
|
|
SC CAMCView::ScSetDescriptionBarText (LPCTSTR pszDescriptionText)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
GetRightDescCtrl().SetSnapinText (pszDescriptionText);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HWND CAMCView::CreateFavoriteObserver (HWND hwndParent, int nID)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::CreateFavoriteObserver"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
CFavTreeCtrl* pFavCtrl = CFavTreeCtrl::CreateInstance();
|
|
|
|
if (pFavCtrl != NULL)
|
|
{
|
|
pFavCtrl->Create (NULL, TEXT(""), WS_CHILD|WS_TABSTOP|WS_VISIBLE,
|
|
g_rectEmpty, CWnd::FromHandle(hwndParent), nID);
|
|
pFavCtrl->ModifyStyleEx (0, WS_EX_CLIENTEDGE, 0);
|
|
|
|
CAMCDoc* pDoc = GetDocument();
|
|
ASSERT(pDoc != NULL && pDoc->GetFavorites() != NULL);
|
|
|
|
sc = pFavCtrl->ScInitialize(pDoc->GetFavorites(), TOBSRV_HIDEROOT);
|
|
if (sc)
|
|
{
|
|
pFavCtrl->DestroyWindow(); // CFavTreeCtrl::PostNcDestroy will "delete this"
|
|
pFavCtrl = NULL;
|
|
}
|
|
}
|
|
|
|
return (pFavCtrl->GetSafeHwnd());
|
|
}
|
|
|
|
|
|
|
|
int CAMCView::GetListSize ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
return (m_pListCtrl->GetItemCount() * m_pListCtrl->GetColCount());
|
|
}
|
|
|
|
long CAMCView::GetListViewStyle()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::GetListViewStyle"));
|
|
|
|
sc = ScCheckPointers(m_pTreeCtrl, m_pTreeCtrl->m_spResultData, E_UNEXPECTED);
|
|
if (sc)
|
|
return 0;
|
|
|
|
if (HasList())
|
|
return 0;
|
|
|
|
long style = 0;
|
|
|
|
// First findout if the result view is properly
|
|
// set in the nodemgr by asking IFramePrivate.
|
|
IFramePrivatePtr spFrame = m_pTreeCtrl->m_spResultData;
|
|
sc = ScCheckPointers(spFrame, E_UNEXPECTED);
|
|
if (sc)
|
|
return 0;
|
|
|
|
BOOL bIsResultViewSet = FALSE;
|
|
sc = spFrame->IsResultViewSet(&bIsResultViewSet);
|
|
|
|
// The result view is set, clean it up.
|
|
if (bIsResultViewSet)
|
|
{
|
|
sc = m_pTreeCtrl->m_spResultData->GetListStyle(&style);
|
|
if (sc)
|
|
return 0;
|
|
}
|
|
|
|
return style;
|
|
}
|
|
|
|
void CAMCView::OnListContextMenu(CPoint& point)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnListContextMenu"));
|
|
|
|
ASSERT(m_pTreeCtrl != NULL);
|
|
ASSERT(m_pTreeCtrl->m_spResultData != NULL);
|
|
|
|
// Determine which item is affected
|
|
UINT fHitTestFlags = 0;
|
|
HRESULTITEM hHitTestItem = 0;
|
|
COMPONENTID componentID = 0;
|
|
int iIndex = -1;
|
|
|
|
do // not a loop
|
|
{
|
|
if (!HasList())
|
|
break;
|
|
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
ASSERT(cSel >= 0);
|
|
|
|
if (cSel == 0)
|
|
{
|
|
OnContextMenuForListItem(INDEX_BACKGROUND, NULL, point);
|
|
return;
|
|
}
|
|
else if (cSel > 1)
|
|
{
|
|
if (IsKeyPressed(VK_SHIFT) || IsKeyPressed(VK_CONTROL))
|
|
{
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
ASSERT(hNodeSel != 0);
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
if (pNC != NULL)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
m_bLastSelWasMultiSel = true;
|
|
}
|
|
}
|
|
|
|
iIndex = INDEX_MULTISELECTION; // => MultiSelect
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
iIndex = _GetLVSelectedItemData(&lvData);
|
|
ASSERT(iIndex != -1);
|
|
ASSERT(lvData != LVDATA_ERROR);
|
|
|
|
if (IsVirtualList())
|
|
{
|
|
// for virtual list pass the item index rather than the lparam
|
|
OnContextMenuForListItem(iIndex, iIndex, point);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle (lvData);
|
|
|
|
if (pri != NULL)
|
|
{
|
|
if (pri->IsScopeItem())
|
|
OnContextMenuForTreeItem(iIndex, pri->GetScopeNode(), point, CCT_SCOPE);
|
|
else
|
|
OnContextMenuForListItem(iIndex, lvData, point);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
} while (0);
|
|
|
|
OnContextMenuForListItem(iIndex, hHitTestItem, point);
|
|
}
|
|
|
|
void CAMCView::OnContextMenuForListItem(int iIndex, HRESULTITEM hHitTestItem,
|
|
CPoint& point, MMC_CONTEXT_MENU_TYPES eMenuType,
|
|
LPCRECT prcExclude, bool bAllowDefaultItem)
|
|
{
|
|
CContextMenuInfo contextInfo;
|
|
|
|
contextInfo.m_displayPoint.x = point.x;
|
|
contextInfo.m_displayPoint.y = point.y;
|
|
contextInfo.m_eContextMenuType = eMenuType;
|
|
contextInfo.m_eDataObjectType = CCT_RESULT;
|
|
contextInfo.m_bBackground = (iIndex == INDEX_BACKGROUND);
|
|
contextInfo.m_bMultiSelect = (iIndex == INDEX_MULTISELECTION);
|
|
contextInfo.m_bAllowDefaultItem = bAllowDefaultItem;
|
|
|
|
if (iIndex >= 0)
|
|
contextInfo.m_resultItemParam = IsVirtualList() ? iIndex : hHitTestItem;
|
|
else if (contextInfo.m_bMultiSelect)
|
|
contextInfo.m_resultItemParam = LVDATA_MULTISELECT;
|
|
|
|
contextInfo.m_bScopeAllowed = IsScopePaneAllowed();
|
|
contextInfo.m_hWnd = m_hWnd;
|
|
contextInfo.m_pConsoleView = this;
|
|
|
|
contextInfo.m_hSelectedScopeNode = GetSelectedNode();
|
|
contextInfo.m_iListItemIndex = iIndex;
|
|
|
|
if (HasListOrListPad())
|
|
contextInfo.m_spListView = m_pListCtrl;
|
|
|
|
if ((INDEX_OCXPANE == iIndex) && HasOCX())
|
|
{
|
|
contextInfo.m_resultItemParam = LVDATA_CUSTOMOCX;
|
|
}
|
|
else if ((INDEX_WEBPANE == iIndex) && HasWebBrowser())
|
|
{
|
|
contextInfo.m_resultItemParam = LVDATA_CUSTOMWEB;
|
|
}
|
|
|
|
/*
|
|
* if given, initialize the rectangle not to obscure
|
|
*/
|
|
if (prcExclude != NULL)
|
|
contextInfo.m_rectExclude = *prcExclude;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
ASSERT(hNode != NULL);
|
|
|
|
INodeCallback* pNodeCallback = GetNodeCallback();
|
|
ASSERT(pNodeCallback != NULL);
|
|
|
|
HRESULT hr = pNodeCallback->Notify(hNode, NCLBK_CONTEXTMENU, 0,
|
|
reinterpret_cast<LPARAM>(&contextInfo));
|
|
}
|
|
|
|
HTREEITEM CAMCView::FindChildNode(HTREEITEM hti, DWORD dwItemDataKey)
|
|
{
|
|
hti = m_pTreeCtrl->GetChildItem(hti);
|
|
|
|
while (hti && (dwItemDataKey != m_pTreeCtrl->GetItemData(hti)))
|
|
{
|
|
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
|
|
}
|
|
|
|
return hti;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/// Context Menu Handlers for Result View Item and Background
|
|
|
|
void CAMCView::ArrangeIcon(long style)
|
|
{
|
|
#ifdef OLD_STUFF
|
|
ASSERT(m_pTreeCtrl && m_pTreeCtrl->m_pNodeInstCurr);
|
|
if (!m_pTreeCtrl || !m_pTreeCtrl->m_pNodeInstCurr)
|
|
return;
|
|
|
|
IFrame* const pFrame = m_pTreeCtrl->m_pNodeInstCurr->GetIFrame();
|
|
ASSERT(pFrame);
|
|
if (!pFrame)
|
|
return;
|
|
|
|
IResultDataPrivatePtr pResult = pFrame;
|
|
ASSERT(static_cast<bool>(pResult));
|
|
if (pResult == NULL)
|
|
return ;
|
|
|
|
HRESULT hr = pResult->Arrange(style);
|
|
ASSERT(SUCCEEDED(style));
|
|
#endif // OLD_STUFF
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/// Menu handlers
|
|
|
|
CAMCView::ViewPane CAMCView::GetFocusedPane ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
ASSERT_VALID (this);
|
|
CView* pActiveView = GetParentFrame()->GetActiveView();
|
|
|
|
for (ViewPane ePane = ePane_First; ePane <= ePane_Last; ePane = (ViewPane)(ePane+1))
|
|
{
|
|
if (GetPaneView (ePane) == pActiveView)
|
|
return (ePane);
|
|
}
|
|
|
|
return (ePane_None);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CDeferredResultPaneActivation
|
|
*
|
|
*
|
|
* PURPOSE: If the result pane has the focus before and after the node was
|
|
* selected, then the last event snapin receives is scope selected which
|
|
* is incorrect. So we first set scope pane as active view but do not
|
|
* send notifications. Then we set result pane as active view which
|
|
* sends scope de-select and result pane select.
|
|
* But when we try to set result pane as active view, the listview may
|
|
* not be visible yet (if there is view extension, the behavior hides
|
|
* and then shows the listview).
|
|
* So we need to wait till listview is setup. We cannot use PostMessage
|
|
* as the resizing of listview happens using PostMessage which is sent
|
|
* later (race condition). Therefore we use the idle timer as shown below
|
|
* so that activation will occur after resizing occurs.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
class CDeferredResultPaneActivation : public CIdleTask
|
|
{
|
|
public:
|
|
CDeferredResultPaneActivation(HWND hWndAMCView) :
|
|
m_atomTask (AddAtom (_T("CDeferredResultPaneActivation"))),
|
|
m_hWndAMCView(hWndAMCView)
|
|
{
|
|
}
|
|
|
|
~CDeferredResultPaneActivation() {}
|
|
|
|
// IIdleTask methods
|
|
SC ScDoWork()
|
|
{
|
|
DECLARE_SC (sc, TEXT("CDeferredResultPaneActivation::ScDoWork"));
|
|
|
|
sc = ScCheckPointers((void*)m_hWndAMCView, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
CWnd *pWnd = CWnd::FromHandle(m_hWndAMCView);
|
|
sc = ScCheckPointers(pWnd, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CAMCView *pAMCView = dynamic_cast<CAMCView*>(pWnd);
|
|
|
|
// Since this method is called by IdleQueue, the target
|
|
// CAMCView may have gone by now, if it does not exist
|
|
// it is not an error (see bug 175737 related to SQL).
|
|
if (! pAMCView)
|
|
return sc;
|
|
|
|
sc = pAMCView->ScSetFocusToResultPane();
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
SC ScGetTaskID(ATOM* pID)
|
|
{
|
|
DECLARE_SC (sc, TEXT("CDeferredResultPaneActivation::ScGetTaskID"));
|
|
sc = ScCheckPointers(pID);
|
|
if(sc)
|
|
return sc;
|
|
|
|
*pID = m_atomTask;
|
|
return sc;
|
|
}
|
|
|
|
SC ScMerge(CIdleTask* pitMergeFrom) {return S_FALSE /*do not merge*/;}
|
|
|
|
private:
|
|
const ATOM m_atomTask;
|
|
HWND m_hWndAMCView;
|
|
};
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScDeferSettingFocusToResultPane
|
|
*
|
|
* Synopsis: If the result pane has the focus before and after the node was
|
|
* selected, then the last event snapin receives is scope selected which
|
|
* is incorrect. So we first set scope pane as active view but do not
|
|
* send notifications. Then we set result pane as active view which
|
|
* sends scope de-select and result pane select.
|
|
* But when we try to set result pane as active view, the listview may
|
|
* not be visible yet (if there is view extension, the behavior hides
|
|
* and then shows the listview).
|
|
* So we need to wait till listview is setup. We cannot use PostMessage
|
|
* as the resizing of listview happens using PostMessage which is sent
|
|
* later (race condition). Therefore we use the idle timer as shown below
|
|
* so that activation will occur after resizing occurs.
|
|
*
|
|
* Returns: SC
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
SC CAMCView::ScDeferSettingFocusToResultPane ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState()); // not sure if we need this, but doesn't hurt to have it in here.
|
|
|
|
DECLARE_SC (sc, TEXT("CAMCView::ScDeferSettingFocusToResultPane"));
|
|
|
|
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
|
|
sc = ScCheckPointers(pIdleTaskQueue, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
/*
|
|
* create the deferred page break task
|
|
*/
|
|
CAutoPtr<CDeferredResultPaneActivation> spDeferredResultPaneActivation(new CDeferredResultPaneActivation (GetSafeHwnd()));
|
|
sc = ScCheckPointers(spDeferredResultPaneActivation, E_OUTOFMEMORY);
|
|
if(sc)
|
|
return sc;
|
|
|
|
/*
|
|
* put the task in the queue, which will take ownership of it
|
|
* Activation should happen at lower priority than layout.
|
|
*/
|
|
sc = pIdleTaskQueue->ScPushTask (spDeferredResultPaneActivation, ePriority_Low);
|
|
if (sc)
|
|
return sc;
|
|
|
|
/*
|
|
* if we get here, the idle task queue owns the idle task, so
|
|
* we can detach it from our smart pointer
|
|
*/
|
|
spDeferredResultPaneActivation.Detach();
|
|
|
|
/*
|
|
* jiggle the message pump so that it wakes up and checks idle tasks
|
|
*/
|
|
PostMessage (WM_NULL);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScSetFocusToResultPane
|
|
//
|
|
// Synopsis: Set focus to result pane (list or ocx or web). If result
|
|
// is hidden then set to folder tab else set to tasks pane.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSetFocusToResultPane ()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSetFocusToResultPane"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
if (GetFocusedPane() == ePane_Results)
|
|
return (sc);
|
|
|
|
// Make active
|
|
// 1. ListView/OCX/Web if it exists else
|
|
// 2. Folder tab if it exists.
|
|
// 3. Tasks in console taskpad.
|
|
|
|
CView* rgActivationOrderEntry[] =
|
|
{
|
|
GetPaneView(ePane_Results), // results
|
|
m_pResultFolderTabView, // result tab control
|
|
m_pViewExtensionCtrl, // view extension web page
|
|
};
|
|
|
|
const int INDEX_RESULTS_PANE = 0;
|
|
ASSERT (rgActivationOrderEntry[INDEX_RESULTS_PANE] == GetPaneView(ePane_Results));
|
|
|
|
int cEntries = (sizeof(rgActivationOrderEntry) / sizeof(rgActivationOrderEntry[0]));
|
|
|
|
// get the currently active entry.
|
|
for(int i = 0; i< cEntries; i++)
|
|
{
|
|
CView *pView = rgActivationOrderEntry[i];
|
|
sc = ScCheckPointers(pView, E_UNEXPECTED);
|
|
if (sc)
|
|
continue;
|
|
|
|
if (IsWindow (pView->GetSafeHwnd()) &&
|
|
pView->IsWindowVisible() &&
|
|
pView->IsWindowEnabled())
|
|
{
|
|
GetParentFrame()->SetActiveView (pView);
|
|
return (sc);
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScSetFocusToPane
|
|
//
|
|
// Synopsis: Call this member to set focus to any pane.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSetFocusToPane (ViewPane ePane)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSetFocusToPane"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
if (!IsValidPane (ePane))
|
|
{
|
|
ASSERT (false && "CAMCView::ScSetFocusToPane: Invalid pane specifier");
|
|
return (sc = E_FAIL);
|
|
}
|
|
|
|
if (GetFocusedPane() == ePane)
|
|
return (sc);
|
|
|
|
if (ePane == ePane_Results)
|
|
return (sc = ScSetFocusToResultPane());
|
|
|
|
CView* pView = GetPaneView(ePane);
|
|
|
|
if (!IsWindow (pView->GetSafeHwnd()) ||
|
|
!pView->IsWindowVisible() ||
|
|
!pView->IsWindowEnabled())
|
|
{
|
|
return (sc = E_FAIL);
|
|
}
|
|
|
|
GetParentFrame()->SetActiveView (pView);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScGetFocusedItem
|
|
//
|
|
// Synopsis: Get the currently selected item's context.
|
|
//
|
|
// Arguments: [hNode] - [out] The owner of result pane.
|
|
// [lCookie] - [out] If result pane selected the LVDATA.
|
|
// [fScope] - [out] scope or result
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScGetFocusedItem (HNODE& hNode, LPARAM& lCookie, bool& fScope)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetFocusedItem"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
ASSERT_VALID (this);
|
|
|
|
lCookie = LVDATA_ERROR;
|
|
hNode = GetSelectedNode();
|
|
if (hNode == NULL)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
switch (m_eCurrentActivePane)
|
|
{
|
|
case eActivePaneScope:
|
|
fScope = true;
|
|
break;
|
|
|
|
case eActivePaneResult:
|
|
{
|
|
fScope = false;
|
|
|
|
// Calculate the LPARAM for result item.
|
|
if (HasOCX())
|
|
lCookie = LVDATA_CUSTOMOCX;
|
|
|
|
else if (HasWebBrowser())
|
|
lCookie = LVDATA_CUSTOMWEB;
|
|
|
|
else if (HasListOrListPad())
|
|
{
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
ASSERT(cSel >= 0);
|
|
|
|
if (cSel == 0)
|
|
lCookie = LVDATA_BACKGROUND;
|
|
else if (cSel == 1)
|
|
_GetLVSelectedItemData (&lCookie);
|
|
else if (cSel > 1)
|
|
lCookie = LVDATA_MULTISELECT;
|
|
}
|
|
else
|
|
{
|
|
return (sc = E_FAIL); // dont know who has the focus???
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eActivePaneNone:
|
|
default:
|
|
sc = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::PrivateChangeListViewMode
|
|
//
|
|
// Synopsis: Private function to change view mode. Consider using
|
|
// ScChangeViewMode instead of this function.
|
|
//
|
|
// Arguments: [nMode] - view mode to be set.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void CAMCView::PrivateChangeListViewMode(int nMode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::PrivateChangeListViewMode"));
|
|
|
|
if ((nMode < 0) || (nMode > MMCLV_VIEWSTYLE_FILTERED) )
|
|
{
|
|
sc = E_INVALIDARG;
|
|
return;
|
|
}
|
|
|
|
// Add a history entry which will be same as current
|
|
// one except for view mode change.
|
|
|
|
sc = ScCheckPointers(m_pHistoryList, m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
// change the current history list entry's view mode
|
|
sc = m_pHistoryList->ScChangeViewMode(nMode);
|
|
if(sc)
|
|
return;
|
|
|
|
// set the list control's view mode
|
|
sc = m_pListCtrl->SetViewMode(nMode);
|
|
if (!sc)
|
|
{
|
|
m_nViewMode = nMode;
|
|
SetDirty();
|
|
|
|
SetDefaultListViewStyle(GetListViewStyle());
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::OnProcessMultiSelectionChanges
|
|
//
|
|
// Synopsis: message handler for m_nProcessMultiSelectionChangesMsg
|
|
// messages that are posted.
|
|
//
|
|
// Handles multi-item de-selection for list view and then
|
|
// send selection for list view items.
|
|
//
|
|
// This method knows that selection states of multiple items
|
|
// are changed but not if they are selected or de-selected.
|
|
// The m_bLastSelWasMultiSel is used to determine if it is
|
|
// selection or de-selection.
|
|
//
|
|
// Arguments: none used.
|
|
//
|
|
// Returns: LRESULT
|
|
//
|
|
//--------------------------------------------------------------------
|
|
LRESULT CAMCView::OnProcessMultiSelectionChanges (WPARAM, LPARAM)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::OnProcessMultiSelectionChanges"));
|
|
|
|
// Selection change so appropriately enable std-toolbar buttons
|
|
// back, forward, export-list, up-one-level, show/hide-scope, help
|
|
sc = ScUpdateStandardbarMMCButtons();
|
|
if (sc)
|
|
return (0);
|
|
|
|
if (! m_bProcessMultiSelectionChanges)
|
|
return (0);
|
|
|
|
m_bProcessMultiSelectionChanges = false;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
sc = ScCheckPointers((void*) hNodeSel, pNC, m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return (0);
|
|
|
|
// If some thing was selected previously send a deselection
|
|
// message before sending a selection message (single item de-select
|
|
// is already handled in OnListItemChanged so just handle multi item
|
|
// deselect here).
|
|
if (m_bLastSelWasMultiSel)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
m_bLastSelWasMultiSel = false;
|
|
}
|
|
|
|
// Now send a selection message
|
|
UINT cSel = m_pListCtrl->GetSelectedCount ();
|
|
if (cSel == 1)
|
|
{
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = FALSE;
|
|
|
|
int iItem = _GetLVSelectedItemData(&selInfo.m_lCookie);
|
|
ASSERT(iItem != -1);
|
|
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, true, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
else if (cSel > 1)
|
|
{
|
|
Dbg(DEB_USER1, _T(" 5. LVN_SELCHANGE <MS> <0, 1>\n"));
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, true, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
m_bLastSelWasMultiSel = true;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
SC CAMCView::ScRenameListPadItem() // obsolete?
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScRenameListPadItem"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
ASSERT(m_pListCtrl != NULL);
|
|
ASSERT(m_pListCtrl->GetListViewPtr() != NULL);
|
|
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
if (cSel != 1)
|
|
return (sc = E_FAIL);
|
|
|
|
LPARAM lParam;
|
|
int iItem = _GetLVSelectedItemData(&lParam);
|
|
ASSERT(iItem >= 0);
|
|
if (iItem >= 0)
|
|
{
|
|
m_bRenameListPadItem = true;
|
|
m_pListCtrl->GetListViewPtr()->SetFocus();
|
|
m_pListCtrl->GetListViewPtr()->GetListCtrl().EditLabel(iItem);
|
|
m_bRenameListPadItem = false;
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOrganizeFavorites
|
|
*
|
|
* PURPOSE: Display the "organize favorites" dialog.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOrganizeFavorites()
|
|
{
|
|
DECLARE_SC (sc, TEXT("CAMCView::ScOrganizeFavorites"));
|
|
|
|
CAMCDoc* pDoc = GetDocument();
|
|
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
CFavorites *pFavorites = pDoc->GetFavorites();
|
|
sc = ScCheckPointers(pFavorites);
|
|
if(sc)
|
|
return sc;
|
|
|
|
pFavorites->OrganizeFavorites(this);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScLineUpIcons
|
|
*
|
|
* PURPOSE: line up the icons in the list
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScLineUpIcons()
|
|
{
|
|
DECLARE_SC (sc, TEXT("CAMCView::ScLineUpIcons"));
|
|
|
|
ArrangeIcon(LVA_SNAPTOGRID);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScAutoArrangeIcons
|
|
*
|
|
* PURPOSE: auto arrange the icons in the list
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScAutoArrangeIcons()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAutoArrangeIcons"));
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
m_pListCtrl->SetListStyle(m_pListCtrl->GetListStyle() ^ LVS_AUTOARRANGE);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnRefresh
|
|
*
|
|
* PURPOSE: Refreshes the view.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnRefresh(HNODE hNode, bool bScope, LPARAM lResultItemParam)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnRefresh"));
|
|
sc = ScCheckPointers((void*)hNode);
|
|
if (sc)
|
|
return sc;
|
|
|
|
HWND hwnd = ::GetFocus();
|
|
|
|
sc = ScProcessConsoleVerb(hNode, bScope, lResultItemParam, evRefresh);
|
|
::SetFocus(hwnd);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* CLASS: CDeferredRenameListItem
|
|
*
|
|
* PURPOSE: This class encapsulates means to put a list control in the rename mode
|
|
* asynchronously. This is needed to assure all mesages are processed before
|
|
* and no-one will steel the focus ending unexpectidly the edit mode.
|
|
*
|
|
* USAGE:
|
|
* use CDeferredRenameListItem::ScDoRenameAsIdleTask() to invoke the operation
|
|
* asyncronously
|
|
*
|
|
\***************************************************************************/
|
|
class CDeferredRenameListItem : public CIdleTask
|
|
{
|
|
// constructor - used internally only
|
|
CDeferredRenameListItem( HWND hwndListCtrl, int iItemIndex ) :
|
|
m_atomTask (AddAtom (_T("CDeferredRenameListItem"))),
|
|
m_hwndListCtrl(hwndListCtrl), m_iItemIndex(iItemIndex)
|
|
{
|
|
}
|
|
|
|
protected:
|
|
|
|
// IIdleTask methods
|
|
SC ScDoWork()
|
|
{
|
|
DECLARE_SC (sc, TEXT("CDeferredRenameListItem::ScDoWork"));
|
|
|
|
// get the ListCtrl pointer
|
|
CListCtrl *pListCtrl = (CListCtrl *)CWnd::FromHandlePermanent(m_hwndListCtrl);
|
|
sc = ScCheckPointers( pListCtrl );
|
|
if (sc)
|
|
return sc;
|
|
|
|
// do what you are asked for - put LV in the rename mode
|
|
pListCtrl->SetFocus(); // set the focus first. Don't need to do a SetActiveView here, I believe (vivekj)
|
|
pListCtrl->EditLabel( m_iItemIndex );
|
|
|
|
return sc;
|
|
}
|
|
|
|
SC ScGetTaskID(ATOM* pID)
|
|
{
|
|
DECLARE_SC (sc, TEXT("CDeferredPageBreak::ScGetTaskID"));
|
|
sc = ScCheckPointers(pID);
|
|
if(sc)
|
|
return sc;
|
|
|
|
*pID = m_atomTask;
|
|
return sc;
|
|
}
|
|
|
|
SC ScMerge(CIdleTask* pitMergeFrom) { return S_FALSE /*do not merge*/; }
|
|
|
|
public:
|
|
|
|
// this method is called to invoke rename asyncronously.
|
|
// it constructs the idle task and puts it into the queue
|
|
static SC ScDoRenameAsIdleTask( HWND hwndListCtrl, int iItemIndex )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CDeferredPageBreak::ScDoRenameAsIdleTask"));
|
|
|
|
CIdleTaskQueue* pIdleTaskQueue = AMCGetIdleTaskQueue();
|
|
sc = ScCheckPointers(pIdleTaskQueue, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// create the deferred task
|
|
CAutoPtr<CDeferredRenameListItem> spTask(new CDeferredRenameListItem (hwndListCtrl, iItemIndex));
|
|
sc = ScCheckPointers( spTask, E_OUTOFMEMORY);
|
|
if(sc)
|
|
return sc;
|
|
|
|
// put the task in the queue, which will take ownership of it
|
|
sc = pIdleTaskQueue->ScPushTask (spTask, ePriority_Normal);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// ownership tranfered to the queue, get rid of control over the pointer
|
|
spTask.Detach();
|
|
|
|
return sc;
|
|
}
|
|
|
|
private:
|
|
const ATOM m_atomTask;
|
|
HWND m_hwndListCtrl;
|
|
int m_iItemIndex;
|
|
};
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnRename
|
|
*
|
|
* PURPOSE: Allows the user to renames the scope or result item specified by pContextInfo
|
|
*
|
|
* PARAMETERS:
|
|
* CContextMenuInfo * pContextInfo :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnRename(CContextMenuInfo *pContextInfo)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScOnRename"));
|
|
|
|
sc = ScCheckPointers(pContextInfo, m_pTreeCtrl, m_pListCtrl);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (pContextInfo->m_htiRClicked != NULL)
|
|
{
|
|
m_pTreeCtrl->EditLabel(pContextInfo->m_htiRClicked);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(pContextInfo->m_iListItemIndex >= 0);
|
|
|
|
sc = ScCheckPointers(m_pListCtrl->GetListCtrl());
|
|
if(sc)
|
|
return sc;
|
|
|
|
// Do this on idle - or else we'll suffer from someone steeling focus
|
|
// Syncronous operation fails in console task case.
|
|
sc = CDeferredRenameListItem::ScDoRenameAsIdleTask( m_pListCtrl->GetListCtrl().m_hWnd, pContextInfo->m_iListItemIndex );
|
|
if(sc)
|
|
return sc;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScRenameScopeNode
|
|
*
|
|
* PURPOSE: put the specified scope node into rename mode.
|
|
*
|
|
* PARAMETERS:
|
|
* HMTNODE hMTNode : The scope node
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScRenameScopeNode(HMTNODE hMTNode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScRenameScopeNode"));
|
|
|
|
sc = ScCheckPointers(m_pTreeCtrl, E_FAIL);
|
|
if(sc)
|
|
return sc;
|
|
|
|
sc = m_pTreeCtrl->ScRenameScopeNode(hMTNode);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetStatusBar
|
|
*
|
|
* PURPOSE: Returns the status bar
|
|
*
|
|
* PARAMETERS:
|
|
* CConsoleStatusBar ** ppStatusBar :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScGetStatusBar(CConsoleStatusBar **ppStatusBar)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetStatusBar"));
|
|
|
|
sc = ScCheckPointers(ppStatusBar);
|
|
if(sc)
|
|
return sc;
|
|
|
|
*ppStatusBar = m_ViewData.GetStatusBar();
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetProperty
|
|
*
|
|
* PURPOSE: Gets the property for a result item
|
|
*
|
|
* PARAMETERS:
|
|
* int m_iIndex : The index of the item in the list.
|
|
* BSTR bstrPropertyName :
|
|
* PBSTR pbstrPropertyValue :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScGetProperty(int iIndex, BSTR bstrPropertyName, PBSTR pbstrPropertyValue)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetProperty"));
|
|
|
|
sc = ScCheckPointers(GetNodeCallback(), m_pListCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
LPARAM resultItemParam = iIndex; // the virtual list case
|
|
bool bScopeItem = false; // the virtual list case
|
|
|
|
if(!IsVirtualList())
|
|
{
|
|
CResultItem *pri = NULL;
|
|
sc = m_pListCtrl->GetLParam(iIndex, pri);
|
|
if(sc)
|
|
return sc;
|
|
|
|
resultItemParam = CResultItem::ToHandle(pri);
|
|
|
|
sc = ScCheckPointers(pri);
|
|
if(sc)
|
|
return sc;
|
|
|
|
bScopeItem = pri->IsScopeItem();
|
|
}
|
|
|
|
sc = GetNodeCallback()->GetProperty(GetSelectedNode(), bScopeItem, resultItemParam, bstrPropertyName, pbstrPropertyValue);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetNodetype
|
|
*
|
|
* PURPOSE: Returns the nodetype for a list item
|
|
*
|
|
* PARAMETERS:
|
|
* int iIndex :
|
|
* PBSTR Nodetype :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScGetNodetype(int iIndex, PBSTR Nodetype)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetProperty"));
|
|
|
|
sc = ScCheckPointers(GetNodeCallback(), m_pListCtrl, E_UNEXPECTED);
|
|
if(sc)
|
|
return sc;
|
|
|
|
LPARAM resultItemParam = iIndex; // the virtual list case
|
|
bool bScopeItem = false; // the virtual list case
|
|
|
|
if(!IsVirtualList())
|
|
{
|
|
CResultItem *pri = NULL;
|
|
sc = m_pListCtrl->GetLParam(iIndex, pri);
|
|
if(sc)
|
|
return sc;
|
|
|
|
resultItemParam = CResultItem::ToHandle(pri);
|
|
|
|
sc = ScCheckPointers(pri);
|
|
if(sc)
|
|
return sc;
|
|
|
|
bScopeItem = pri->IsScopeItem();
|
|
}
|
|
|
|
sc = GetNodeCallback()->GetNodetypeForListItem(GetSelectedNode(), bScopeItem, resultItemParam, Nodetype);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScAddViewExtension
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScAddViewExtension (const CViewExtensionData& ved)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScAddViewExtension"));
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
void
|
|
CAMCView::OnChangedResultTab(NMHDR *nmhdr, LRESULT *pRes)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnChangedResultTab"));
|
|
|
|
NMFOLDERTAB* nmtab = static_cast<NMFOLDERTAB*>(nmhdr);
|
|
int iTab = nmtab->iItem;
|
|
CFolderTab &tab = m_pResultFolderTabView->GetItem(iTab);
|
|
|
|
GUID guidTaskpad = tab.GetClsid();
|
|
|
|
// check if we're moving to the same taskpad.
|
|
GUID guidCurrentTaskpad;
|
|
GetTaskpadID(guidCurrentTaskpad);
|
|
if(guidTaskpad == guidCurrentTaskpad)
|
|
return;
|
|
|
|
// lookup view extension URL
|
|
CViewExtensionURLs::iterator itVE = m_ViewExtensionURLs.find(guidTaskpad);
|
|
LPCTSTR url = (itVE != m_ViewExtensionURLs.end()) ? itVE->second.c_str() : NULL;
|
|
|
|
// apply URL
|
|
sc = ScApplyViewExtension(url);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
GetNodeCallback()->SetTaskpad(GetSelectedNode(), &guidTaskpad); // if not found, guidTaskpad is set to GUID_NULL.
|
|
|
|
// After setting the taskpad enable/disable save list button
|
|
CStandardToolbar* pStdToolbar = GetStdToolbar();
|
|
ASSERT(NULL != pStdToolbar);
|
|
if (NULL != pStdToolbar)
|
|
{
|
|
pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
|
|
}
|
|
|
|
// the taskpad changed. Create a new entry in the history list.
|
|
sc = m_pHistoryList->ScModifyViewTab( guidTaskpad );
|
|
if(sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CAMCView::GetRootNodePath(
|
|
CBookmark* pbm)
|
|
{
|
|
HTREEITEM htiRoot = m_pTreeCtrl->GetRootItem();
|
|
return GetNodePath(htiRoot, htiRoot, pbm);
|
|
}
|
|
|
|
HRESULT
|
|
CAMCView::GetSelectedNodePath(
|
|
CBookmark* pbm)
|
|
{
|
|
return GetNodePath(m_pTreeCtrl->GetSelectedItem(),
|
|
m_pTreeCtrl->GetRootItem(),
|
|
pbm);
|
|
}
|
|
|
|
HRESULT
|
|
CAMCView::GetNodePath(
|
|
HTREEITEM hti,
|
|
HTREEITEM htiRoot,
|
|
CBookmark* pbm)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetRootNodeID);
|
|
|
|
if (hti == NULL)
|
|
return E_FAIL;
|
|
|
|
if (htiRoot == NULL)
|
|
return E_FAIL;
|
|
|
|
ASSERT(hti != NULL);
|
|
ASSERT(htiRoot != NULL);
|
|
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
|
|
HNODE hRootNode = (HNODE)m_pTreeCtrl->GetItemData(htiRoot);
|
|
|
|
HRESULT hr = m_spNodeCallback->GetPath(hNode, hRootNode, (LPBYTE) pbm);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
inline HMTNODE CAMCView::GetHMTNode(HTREEITEM hti)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetHMTNode);
|
|
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
|
|
|
|
HMTNODE hMTNodeTemp;
|
|
HRESULT hr = m_spNodeCallback->GetMTNode(hNode, &hMTNodeTemp);
|
|
CHECK_HRESULT(hr);
|
|
|
|
return hMTNodeTemp;
|
|
}
|
|
|
|
HTREEITEM CAMCView::FindHTreeItem(HMTNODE hMTNode, HTREEITEM hti)
|
|
{
|
|
TRACE_METHOD(CAMCView, FindHTreeItem);
|
|
|
|
while (hti)
|
|
{
|
|
if (hMTNode == GetHMTNode(hti))
|
|
break;
|
|
|
|
hti = m_pTreeCtrl->GetNextItem(hti, TVGN_NEXT);
|
|
}
|
|
|
|
return hti;
|
|
}
|
|
|
|
UINT CAMCView::ClipPath(CHMTNODEList* pNodeList, POSITION& rpos, HNODE hNode)
|
|
{
|
|
TRACE_METHOD(CAMCView, ClipPath);
|
|
|
|
UINT uiReturn = ITEM_IS_IN_VIEW;
|
|
CCoTaskMemPtr<HMTNODE> sphMTNode;
|
|
long lLength = 0;
|
|
|
|
HRESULT hr = m_spNodeCallback->GetMTNodePath(hNode, &sphMTNode, &lLength);
|
|
CHECK_HRESULT(hr);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
ASSERT(lLength == 0 || sphMTNode != NULL);
|
|
|
|
for (long i=0; rpos != 0 && i < lLength; i++)
|
|
{
|
|
HMTNODE hMTNode = pNodeList->GetNext(rpos);
|
|
if (hMTNode != sphMTNode[i])
|
|
{
|
|
uiReturn = ITEM_NOT_IN_VIEW;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (uiReturn == ITEM_NOT_IN_VIEW)
|
|
return ITEM_NOT_IN_VIEW;
|
|
return (rpos == 0 && lLength >= i) ? ITEM_IS_PARENT_OF_ROOT : ITEM_IS_IN_VIEW;
|
|
}
|
|
|
|
//
|
|
// GetTreeItem returns TRUE if it can find the htreeitem of the item
|
|
// whose HMTNode is equal to the last element in pNodeList. It returns
|
|
// FALSE if the node does not appear in the view name space or if the
|
|
// the node has not yet been created.
|
|
//
|
|
// "pNodeList" is a list of HMTNODEs such that pNodeList[n] is the parent
|
|
// of pNodeList[n+1].
|
|
//
|
|
UINT CAMCView::GetTreeItem(CHMTNODEList* pNodeList, HTREEITEM* phItem)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetTreeItem);
|
|
|
|
ASSERT(pNodeList->IsEmpty() == FALSE);
|
|
|
|
HTREEITEM hti = NULL;
|
|
HMTNODE hMTNodeTemp = 0;
|
|
|
|
hti = m_pTreeCtrl->GetRootItem();
|
|
if (hti == NULL)
|
|
return ITEM_NOT_IN_VIEW;
|
|
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
|
|
POSITION pos = pNodeList->GetHeadPosition();
|
|
|
|
UINT uiReturn = ClipPath(pNodeList, pos, hNode);
|
|
if (uiReturn != ITEM_IS_IN_VIEW)
|
|
return uiReturn;
|
|
|
|
|
|
HTREEITEM htiTemp = NULL;
|
|
while (pos && hti)
|
|
{
|
|
hMTNodeTemp = (HMTNODE)pNodeList->GetNext(pos);
|
|
|
|
hti = FindHTreeItem(hMTNodeTemp, hti);
|
|
ASSERT(hti == NULL || hMTNodeTemp == GetHMTNode(hti));
|
|
|
|
htiTemp = hti;
|
|
|
|
if (hti != NULL)
|
|
hti = m_pTreeCtrl->GetChildItem(hti);
|
|
}
|
|
|
|
if (pos == 0 && htiTemp != NULL)
|
|
{
|
|
// Found the node.
|
|
ASSERT(hMTNodeTemp == pNodeList->GetTail());
|
|
ASSERT(hMTNodeTemp == GetHMTNode(htiTemp));
|
|
|
|
*phItem = htiTemp;
|
|
return ITEM_IS_IN_VIEW;
|
|
}
|
|
else
|
|
{
|
|
// The node has not yet been created.
|
|
*phItem = NULL;
|
|
return ITEM_NOT_IN_VIEW;
|
|
}
|
|
|
|
return ITEM_IS_IN_VIEW;
|
|
}
|
|
|
|
|
|
#define HMTNODE_FIRST reinterpret_cast<HMTNODE>(TVI_FIRST)
|
|
#define HMTNODE_LAST reinterpret_cast<HMTNODE>(TVI_LAST)
|
|
|
|
void CAMCView::OnAdd(SViewUpdateInfo *pvui)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnAdd);
|
|
|
|
ASSERT(pvui->path.IsEmpty() == FALSE);
|
|
|
|
HTREEITEM htiParent;
|
|
if (GetTreeItem(&pvui->path, &htiParent) != ITEM_IS_IN_VIEW || htiParent == NULL)
|
|
return;
|
|
|
|
bool bFirstChild = (m_pTreeCtrl->GetChildItem(htiParent) == NULL);
|
|
|
|
HNODE hNodeParent = (HNODE)m_pTreeCtrl->GetItemData(htiParent);
|
|
if (m_spNodeCallback->Notify(hNodeParent, NCLBK_EXPAND, 0, 0) == S_FALSE)
|
|
{
|
|
m_pTreeCtrl->SetCountOfChildren(htiParent, 1);
|
|
return; // Don't add if it is not expanded.
|
|
}
|
|
|
|
// If the hNode was already expanded add the item.
|
|
IScopeTree* const pScopeTree = GetScopeTree();
|
|
ASSERT(pScopeTree != NULL);
|
|
HNODE hNodeNew = 0;
|
|
HRESULT hr = pScopeTree->CreateNode(pvui->newNode,
|
|
reinterpret_cast<LONG_PTR>(GetViewData()),
|
|
FALSE, &hNodeNew);
|
|
CHECK_HRESULT(hr);
|
|
if (FAILED(hr))
|
|
return;
|
|
|
|
HTREEITEM hInsertAfter = TVI_LAST;
|
|
int iInsertIndex = -1;
|
|
|
|
if (pvui->insertAfter != NULL)
|
|
{
|
|
hInsertAfter = reinterpret_cast<HTREEITEM>(pvui->insertAfter);
|
|
|
|
if (pvui->insertAfter == HMTNODE_LAST)
|
|
{
|
|
}
|
|
else if (pvui->insertAfter == HMTNODE_FIRST)
|
|
{
|
|
iInsertIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
HTREEITEM hti = m_pTreeCtrl->GetChildItem(htiParent);
|
|
ASSERT(hti != NULL);
|
|
|
|
iInsertIndex = 1;
|
|
while (hti != NULL)
|
|
{
|
|
if (GetHMTNode(hti) == pvui->insertAfter)
|
|
break;
|
|
|
|
hti = m_pTreeCtrl->GetNextSiblingItem(hti);
|
|
iInsertIndex++;
|
|
}
|
|
|
|
if (hti)
|
|
{
|
|
hInsertAfter = hti;
|
|
}
|
|
else
|
|
{
|
|
hInsertAfter = TVI_LAST;
|
|
iInsertIndex = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_pTreeCtrl->InsertNode(htiParent, hNodeNew, hInsertAfter) == NULL)
|
|
return;
|
|
|
|
// if parent of the inserted item currently owns a non-virtual result list,
|
|
// add the item to result list too. Don't add the item if a node select is in
|
|
// progress because the tree control will automatically add all scope items
|
|
// as part of the select procedure.
|
|
if (OwnsResultList(htiParent) && CanInsertScopeItemInResultPane() )
|
|
{
|
|
// Ensure the node is enumerated
|
|
m_pTreeCtrl->ExpandNode(htiParent);
|
|
|
|
// Add to result pane.
|
|
RESULTDATAITEM tRDI;
|
|
::ZeroMemory(&tRDI, sizeof(tRDI));
|
|
tRDI.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
|
|
tRDI.nCol = 0;
|
|
tRDI.str = MMC_TEXTCALLBACK;
|
|
tRDI.nIndex = iInsertIndex;
|
|
|
|
int nImage;
|
|
int nSelectedImage;
|
|
|
|
hr = m_spNodeCallback->GetImages(hNodeNew, &nImage, &nSelectedImage);
|
|
ASSERT(hr == S_OK || nImage == 0);
|
|
|
|
tRDI.nImage = nImage;
|
|
tRDI.lParam = CAMCTreeView::LParamFromNode (hNodeNew);
|
|
|
|
LPRESULTDATA pResultData = m_pTreeCtrl->GetResultData();
|
|
ASSERT(pResultData != NULL);
|
|
hr = pResultData->InsertItem(&tRDI);
|
|
CHECK_HRESULT(hr);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = m_spNodeCallback->SetResultItem(hNodeNew, tRDI.itemID);
|
|
}
|
|
|
|
if ((m_pTreeCtrl->GetRootItem() == htiParent) ||
|
|
((bFirstChild == true) &&
|
|
(m_spNodeCallback->Notify(hNodeParent, NCLBK_GETEXPANDEDVISUALLY, 0, 0) == S_OK)))
|
|
{
|
|
m_pTreeCtrl->Expand(htiParent, TVE_EXPAND);
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::OnEmptyAddToCArray
|
|
*
|
|
* PURPOSE: Called to check if this view is empty.
|
|
* If this view is empty then add it to the given CArray
|
|
* so that the view can be deleted by the owner of CArray (CMainFrame).
|
|
*
|
|
* PARAMETERS:
|
|
* pHint - CArray of CAMCView*
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void CAMCView::OnEmptyAddToCArray(CObject* pHint)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnEmptyAddToCArray"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
// View is not empty.
|
|
if (m_pTreeCtrl->GetRootItem() != NULL)
|
|
return;
|
|
|
|
// Ensure that there is at least one *persistable* view
|
|
CAMCDoc* pDoc = dynamic_cast<CAMCDoc*>(GetDocument());
|
|
sc = ScCheckPointers(pDoc);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return;
|
|
}
|
|
|
|
// BUG #666149. Empty views should not be deleted if this method is
|
|
// called during a persist operation.
|
|
if(!pDoc->CanCloseViews())
|
|
return;
|
|
|
|
int cViews = pDoc->GetNumberOfPersistedViews();
|
|
ASSERT(cViews >= 1);
|
|
if ((cViews == 1) && IsPersisted())
|
|
{
|
|
CMainFrame* pMain = dynamic_cast<CMainFrame*>(AfxGetMainWnd());
|
|
sc = ScCheckPointers(pMain);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return;
|
|
}
|
|
|
|
pMain->SendMessage(WM_COMMAND, ID_WINDOW_NEW, 0);
|
|
}
|
|
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
sc = ScCheckPointers(pFrame, pHint);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return;
|
|
}
|
|
|
|
// Tell CChildFrame that the view is empty.
|
|
pFrame->SetAMCViewIsEmpty();
|
|
|
|
// Add this view to empty AMCViews
|
|
CArray<CAMCView*, CAMCView*> *prgEmptyAMCViews = reinterpret_cast<CArray<CAMCView*, CAMCView*> *>(pHint);
|
|
sc = ScCheckPointers(prgEmptyAMCViews);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return;
|
|
}
|
|
|
|
prgEmptyAMCViews->Add(this);
|
|
}
|
|
|
|
void CAMCView::OnDelete(SViewUpdateInfo *pvui)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnDelete);
|
|
|
|
ASSERT(pvui->path.IsEmpty() == FALSE);
|
|
|
|
HTREEITEM hti;
|
|
UINT uiReturn = GetTreeItem(&pvui->path, &hti);
|
|
|
|
if (uiReturn == ITEM_NOT_IN_VIEW)
|
|
return;
|
|
|
|
ASSERT(uiReturn != ITEM_IS_IN_VIEW || pvui->path.GetTail() == GetHMTNode(hti));
|
|
|
|
HTREEITEM htiSel = m_pTreeCtrl->GetSelectedItem();
|
|
BOOL fDeleteThis = (pvui->flag & VUI_DELETE_THIS) ? TRUE : FALSE;
|
|
BOOL fExpandable = (pvui->flag & VUI_DELETE_SETAS_EXPANDABLE) ? TRUE : FALSE;
|
|
|
|
if (uiReturn == ITEM_IS_PARENT_OF_ROOT ||
|
|
NULL == hti)
|
|
{
|
|
hti = m_pTreeCtrl->GetRootItem();
|
|
fDeleteThis = TRUE;
|
|
fExpandable = FALSE;
|
|
}
|
|
|
|
ASSERT(hti != NULL);
|
|
|
|
// If deleted scope item is also shown in the result pane
|
|
// delete it there too. Can't happen with a virtual list.
|
|
// Don't try deleting item if selection is in progress because
|
|
// the scope items haven't been added yet.
|
|
|
|
if (fDeleteThis == TRUE &&
|
|
OwnsResultList(m_pTreeCtrl->GetParentItem(hti)) &&
|
|
CanInsertScopeItemInResultPane())
|
|
{
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
HRESULTITEM itemID;
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
|
|
HRESULT hr = pNC->GetResultItem(hNode, &itemID);
|
|
if (SUCCEEDED(hr) && itemID != 0)
|
|
{
|
|
IResultData* pIRD = m_pTreeCtrl->GetResultData();
|
|
pIRD->DeleteItem(itemID, 0);
|
|
}
|
|
}
|
|
|
|
m_pTreeCtrl->DeleteNode(hti, fDeleteThis);
|
|
|
|
if (fDeleteThis == FALSE && fExpandable == TRUE)
|
|
m_pTreeCtrl->SetItemState(hti, 0, TVIS_EXPANDEDONCE | TVIS_EXPANDED);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::OnUpdateSelectionForDelete
|
|
*
|
|
* PURPOSE: Called when a scope node is deleted. If the node is an ancestor
|
|
* of the currently selected node, the selection is changed to the closest
|
|
* node of the deleted node. This is either the next sibling of the node that is being deleted,
|
|
* or, if there is no next sibling, the previous sibling, or, if there is none,
|
|
* the parent.
|
|
*
|
|
* PARAMETERS:
|
|
* SViewUpdateInfo* pvui :
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::OnUpdateSelectionForDelete(SViewUpdateInfo* pvui)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnUpdateSelectionForDelete"));
|
|
|
|
// make sure we have a path to the deleted node.
|
|
if(pvui->path.IsEmpty())
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return;
|
|
}
|
|
|
|
HTREEITEM htiToDelete;
|
|
UINT uiReturn = GetTreeItem(&pvui->path, &htiToDelete);
|
|
|
|
if (uiReturn == ITEM_IS_IN_VIEW && NULL != htiToDelete)
|
|
{
|
|
HTREEITEM htiSel = m_pTreeCtrl->GetSelectedItem();
|
|
BOOL fDeleteThis = (pvui->flag & VUI_DELETE_THIS);
|
|
|
|
// Determine whether the selected node is a descendant of the
|
|
// node bring deleted.
|
|
HTREEITEM htiTemp = htiSel;
|
|
while (htiTemp != NULL && htiTemp != htiToDelete)
|
|
{
|
|
htiTemp = m_pTreeCtrl->GetParentItem(htiTemp);
|
|
}
|
|
|
|
if (htiToDelete == htiTemp)
|
|
{
|
|
// The selected node is a descendant of the
|
|
// node being deleted.
|
|
|
|
if (fDeleteThis == TRUE)
|
|
htiTemp = m_pTreeCtrl->GetParentItem(htiToDelete);
|
|
|
|
if (!htiTemp)
|
|
htiTemp = htiToDelete;
|
|
|
|
if (htiTemp != htiSel)
|
|
{
|
|
HNODE hNode = m_pTreeCtrl->GetItemNode(htiSel);
|
|
|
|
// the next line is not needed because m_pTreeCtrl->SelectItem() winds up calling OnDeSelectNode anyway.
|
|
// m_pTreeCtrl->OnDeSelectNode(hNode);
|
|
|
|
ASSERT(htiTemp != NULL);
|
|
if (htiTemp != NULL)
|
|
m_pTreeCtrl->SelectItem(htiTemp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnUpdateTaskpadNavigation
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* SViewUpdateInfo * pvui:
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
/*+-------------------------------------------------------------------------*/
|
|
void CAMCView::OnUpdateTaskpadNavigation(SViewUpdateInfo *pvui)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnupdateTaskpadNavigation);
|
|
|
|
ASSERT(pvui->newNode != NULL);
|
|
|
|
//m_spNodeCallback->UpdateTaskpadNavigation(GetSelectedNode(), pvui->newNode);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnModify
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* SViewUpdateInfo * pvui:
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
/*+-------------------------------------------------------------------------*/
|
|
void CAMCView::OnModify(SViewUpdateInfo *pvui)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnModify);
|
|
|
|
ASSERT(pvui->path.IsEmpty() == FALSE);
|
|
|
|
HNODE hNode = 0;
|
|
HTREEITEM hti;
|
|
|
|
if (GetTreeItem(&pvui->path, &hti) == ITEM_IS_IN_VIEW && hti != NULL)
|
|
{
|
|
ASSERT(m_pTreeCtrl != NULL);
|
|
m_pTreeCtrl->ResetNode(hti);
|
|
|
|
/*
|
|
* The name of the selected node and all of its ancestors are
|
|
* displayed in the frame title. If the modified item is an
|
|
* ancestor of the selected node, we need to update the frame title.
|
|
*/
|
|
HTREEITEM htiAncesctor;
|
|
|
|
for (htiAncesctor = m_pTreeCtrl->GetSelectedItem();
|
|
htiAncesctor != NULL;
|
|
htiAncesctor = m_pTreeCtrl->GetParentItem (htiAncesctor))
|
|
{
|
|
if (htiAncesctor == hti)
|
|
{
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
if (pFrame)
|
|
pFrame->OnUpdateFrameTitle(TRUE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT(hti != NULL);
|
|
|
|
if (hti != NULL &&
|
|
OwnsResultList(m_pTreeCtrl->GetParentItem(hti)) &&
|
|
!IsVirtualList())
|
|
{
|
|
// Continue only if the currently selected item is the parent
|
|
// of the modified node. In this case we need to update the
|
|
// result view. Can't happen with a virtual list.
|
|
|
|
if (hNode == 0)
|
|
hNode = (HNODE)m_pTreeCtrl->GetItemData(hti);
|
|
|
|
ASSERT(hNode != NULL);
|
|
|
|
HRESULTITEM hri;
|
|
HRESULT hr = m_spNodeCallback->GetResultItem(hNode, &hri);
|
|
CHECK_HRESULT(hr);
|
|
|
|
// NOTE: the test for itemID != NULL below is related to bug 372242:
|
|
// MMC asserts on index server root node.
|
|
// What happens is that the snapin adds scope nodes on a SHOW event.
|
|
// These items have not yet been added to the result pane and so itemID
|
|
// comes back NULL.
|
|
if (SUCCEEDED(hr) && hri != NULL)
|
|
m_pListCtrl->OnModifyItem(CResultItem::FromHandle(hri));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void CAMCView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
|
|
{
|
|
Dbg(DEB_USER1, _T("CAMCView::OnUpdate<0x%08x, 0x%08x, 0x%08x>\n"),
|
|
pSender, lHint, pHint);
|
|
SViewUpdateInfo *pvui = reinterpret_cast<SViewUpdateInfo*>(pHint);
|
|
switch (lHint)
|
|
{
|
|
case 0:
|
|
// Sent by CView::OnInitialUpdate()
|
|
break;
|
|
|
|
case VIEW_UPDATE_ADD:
|
|
OnAdd(pvui);
|
|
break;
|
|
|
|
case VIEW_UPDATE_SELFORDELETE:
|
|
OnUpdateSelectionForDelete(pvui);
|
|
break;
|
|
|
|
case VIEW_UPDATE_DELETE:
|
|
OnDelete(pvui);
|
|
break;
|
|
|
|
case VIEW_UPDATE_DELETE_EMPTY_VIEW:
|
|
OnEmptyAddToCArray(pHint);
|
|
break;
|
|
|
|
case VIEW_UPDATE_MODIFY:
|
|
OnModify(pvui);
|
|
break;
|
|
|
|
case VIEW_RESELECT:
|
|
if (m_ViewData.m_spControlbarsCache != NULL)
|
|
m_ViewData.m_spControlbarsCache->DetachControlbars();
|
|
m_pTreeCtrl->ScReselect();
|
|
break;
|
|
|
|
case VIEW_UPDATE_TASKPAD_NAVIGATION:
|
|
OnUpdateTaskpadNavigation(pvui);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
static int static_nViewID = 1;
|
|
|
|
UINT CAMCView::GetViewID(void)
|
|
{
|
|
if (m_nViewID)
|
|
return m_nViewID;
|
|
SetViewID(static_nViewID);
|
|
++static_nViewID;
|
|
return m_nViewID;
|
|
//UINT const id = m_nViewID ? m_nViewID : m_nViewID = static_nViewID++;
|
|
//return id;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScCompleteInitialization
|
|
*
|
|
* This function completes the initialization process for CAMCView. It
|
|
* is called from OnInitialUpdate.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScCompleteInitialization()
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScCompleteInitialization"));
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTree();
|
|
sc = ScCheckPointers (pScopeTree, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
pScopeTree->QueryIterator(&m_spScopeTreeIter);
|
|
pScopeTree->QueryNodeCallback(&m_spNodeCallback);
|
|
|
|
m_ViewData.m_spNodeCallback = GetNodeCallback();
|
|
sc = ScCheckPointers (m_ViewData.m_spNodeCallback, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
CAMCDoc* const pDoc = GetDocument();
|
|
sc = ScCheckPointers (pDoc, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
if (m_hMTNode == NULL)
|
|
{
|
|
MTNODEID const nodeID = pDoc->GetMTNodeIDForNewView();
|
|
HRESULT hr = pScopeTree->Find(nodeID, &m_hMTNode);
|
|
|
|
if (FAILED(hr) || m_hMTNode == 0)
|
|
{
|
|
sc.FromMMC (IDS_ExploredWindowFailed);
|
|
return (sc);
|
|
}
|
|
}
|
|
|
|
sc = m_spStandardToolbar->ScInitializeStdToolbar(this);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
// Set the iterator to the correct node
|
|
m_spScopeTreeIter->SetCurrent(m_hMTNode);
|
|
|
|
bool fShowScopePane = IsScopePaneAllowed();
|
|
|
|
// Intialize the iterator and the callback interface
|
|
|
|
SetViewID(pDoc->GetViewIDForNewView());
|
|
GetViewID(); // initialized the view id if GetViewIDForNewView returned 0
|
|
|
|
// Insert the root node for this view
|
|
HNODE hNode = 0;
|
|
sc = pScopeTree->CreateNode (m_hMTNode, reinterpret_cast<LONG_PTR>(GetViewData()),
|
|
TRUE, &hNode);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
sc = ScCheckPointers (hNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
HTREEITEM hti = m_pTreeCtrl->InsertNode(TVI_ROOT, hNode);
|
|
m_htiStartingSelectedNode = hti;
|
|
|
|
// If the persisted state is expanded, call INodeCallback::Expand
|
|
m_pTreeCtrl->Expand(hti, TVE_EXPAND);
|
|
|
|
/*
|
|
* If a scope pane is permitted in this window, set the scope
|
|
* pane visible, and modify the scope pane & favorites toolbar
|
|
* buttons to the proper checked state.
|
|
*/
|
|
sc = ScShowScopePane (fShowScopePane, true);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
LPUNKNOWN pUnkResultsPane = NULL;
|
|
pUnkResultsPane = GetPaneUnknown(ePane_Results);
|
|
m_pTreeCtrl->m_spNodeManager->SetResultView(pUnkResultsPane);
|
|
|
|
DeferRecalcLayout();
|
|
|
|
m_pHistoryList->Clear();
|
|
IdentifyRootNode ();
|
|
|
|
// Select the root item
|
|
hti = m_pTreeCtrl->GetRootItem();
|
|
m_pTreeCtrl->SelectItem(hti);
|
|
|
|
/*
|
|
* if the document has a custom icon, use it on this window
|
|
*/
|
|
if (pDoc->HasCustomIcon())
|
|
{
|
|
GetParentFrame()->SetIcon (pDoc->GetCustomIcon(true), true);
|
|
GetParentFrame()->SetIcon (pDoc->GetCustomIcon(false), false);
|
|
}
|
|
|
|
/*
|
|
* we just initialized, so the view isn't dirty
|
|
*/
|
|
SetDirty (false);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
void CAMCView::OnInitialUpdate()
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::OnInitialUpdate"));
|
|
CView::OnInitialUpdate();
|
|
|
|
sc = ScCompleteInitialization ();
|
|
if (sc)
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScDocumentLoadCompleted
|
|
//
|
|
// Synopsis: The document is completely loaded so all the objects
|
|
// that initialize themself from document are in valid
|
|
// state. Any initialization performed earlier using invalid
|
|
// data can be now re-initialized with proper data.
|
|
//
|
|
// The above CAMCView::ScCompleteInitialization is called
|
|
// during the loading of views, thus the document is not
|
|
// completely loaded yet.
|
|
//
|
|
// Arguments: [pDoc] - [in] the CAMCDoc object
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScDocumentLoadCompleted (CAMCDoc *pDoc)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScDocumentLoadCompleted"));
|
|
sc = ScCheckPointers(pDoc);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// 1. Need to hide toolbutton "Show/Hide scopetree".
|
|
// The FrameState is loaded after views when CAMCDoc loads document. And it contains
|
|
// whether the "View Customization" is enabled or not. If "View customization" is
|
|
// disabled then we need to disable "Show ScopeTree" button.
|
|
if (! pDoc->AllowViewCustomization())
|
|
{
|
|
CStandardToolbar* pStdToolbar = GetStdToolbar();
|
|
sc = ScCheckPointers(pStdToolbar, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
sc = pStdToolbar->ScEnableScopePaneBtn (false);
|
|
if (sc)
|
|
return (sc);
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------*
|
|
* CAMCView::IdentifyRootNode
|
|
*
|
|
* This functions determines if this view is rooted at a non-persistent
|
|
* dynamic node. If so, we won't persist this view at save time.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::IdentifyRootNode ()
|
|
{
|
|
// In order to get results from GetRootNodePath that are meaningful
|
|
// in this context, there needs to be a root item in the tree.
|
|
ASSERT (m_pTreeCtrl->GetRootItem() != NULL);
|
|
|
|
CBookmark bm;
|
|
HRESULT hr = GetRootNodePath (&bm);
|
|
ASSERT (SUCCEEDED (hr) == bm.IsValid());
|
|
|
|
m_fRootedAtNonPersistedDynamicNode = (hr != S_OK);
|
|
}
|
|
|
|
|
|
void GetFullPath(CAMCTreeView &ctc, HTREEITEM hti, CString &strPath)
|
|
{
|
|
TRACE_FUNCTION(GetFullPath);
|
|
|
|
if (hti == NULL)
|
|
{
|
|
strPath = _T("");
|
|
return;
|
|
}
|
|
|
|
GetFullPath(ctc, ctc.GetParentItem(hti), strPath);
|
|
|
|
if (strPath.GetLength() > 0)
|
|
strPath += _T('\\');
|
|
|
|
HNODE hNode = ctc.GetItemNode(hti);
|
|
|
|
INodeCallback* spCallback = ctc.GetNodeCallback();
|
|
ASSERT(spCallback != NULL);
|
|
|
|
tstring strName;
|
|
HRESULT const hr = spCallback->GetDisplayName(hNode, strName);
|
|
|
|
strPath += strName.data();
|
|
}
|
|
|
|
LPCTSTR CAMCView::GetWindowTitle(void)
|
|
{
|
|
TRACE_METHOD(CAMCView, GetWindowTitle);
|
|
|
|
if (HasCustomTitle() && (m_spNodeCallback != NULL))
|
|
{
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
if (hNode != NULL)
|
|
{
|
|
tstring strWindowTitle;
|
|
|
|
if (SUCCEEDED(m_spNodeCallback->GetWindowTitle(hNode, strWindowTitle)))
|
|
{
|
|
m_strWindowTitle = strWindowTitle.data();
|
|
return m_strWindowTitle;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (m_pTreeCtrl == NULL)
|
|
{
|
|
m_strWindowTitle.Empty();
|
|
}
|
|
else
|
|
{
|
|
GetFullPath(*m_pTreeCtrl,
|
|
m_pTreeCtrl->GetSelectedItem(),
|
|
m_strWindowTitle);
|
|
}
|
|
|
|
return m_strWindowTitle;
|
|
}
|
|
|
|
|
|
void CAMCView::SelectNode(MTNODEID ID, GUID &guidTaskpad)
|
|
{
|
|
ScSelectNode(ID);
|
|
|
|
// After setting the taskpad enable/disable save list button
|
|
CStandardToolbar* pStdToolbar = GetStdToolbar();
|
|
ASSERT(NULL != pStdToolbar);
|
|
if (NULL != pStdToolbar)
|
|
{
|
|
pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScSelectNode
|
|
//
|
|
// Synopsis: Select the given node. Normally if the node is not available
|
|
// then we select nearest parent or child. But if bSelectExactNode
|
|
// is true then have to select the exact node else do not select any node.
|
|
//
|
|
// Arguments: [ID] - [in] node that needs to be selected.
|
|
// [bSelectExactNode] - [in] select exact node or not?
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSelectNode (MTNODEID ID, bool bSelectExactNode)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScSelectNode"));
|
|
|
|
IScopeTree* pIST = GetScopeTreePtr();
|
|
sc = ScCheckPointers(pIST, m_pTreeCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
long length = 0;
|
|
CCoTaskMemPtr<MTNODEID> spIDs;
|
|
|
|
sc = pIST->GetIDPath(ID, &spIDs, &length);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
if ( (length < 1) || (spIDs == NULL) )
|
|
return (sc = E_FAIL);
|
|
|
|
|
|
sc = m_pTreeCtrl->ScSelectNode(spIDs, length, bSelectExactNode);
|
|
|
|
// If select exact node is specified and the node could not be
|
|
// selected then return error without tracing it.
|
|
if (bSelectExactNode && (sc == ScFromMMC(IDS_NODE_NOT_FOUND)) )
|
|
{
|
|
SC scNoTrace = sc;
|
|
sc.Clear();
|
|
return scNoTrace;
|
|
}
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
SetDirty();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScExpandNode
|
|
*
|
|
* PURPOSE: Expands the tree up to the specified node. The expansion can occur
|
|
* either visually, where the user sees the expansion, or nonvisually,
|
|
* where all the child items are added but there is no visual effect.
|
|
*
|
|
* PARAMETERS:
|
|
* MTNODEID id : id of node to expand
|
|
* bool bExpand : true to expand the node, false to collapse
|
|
* bool bExpandVisually : true to show the changes, else false.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScExpandNode (
|
|
MTNODEID id,
|
|
bool fExpand,
|
|
bool fExpandVisually)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScExpandNode"));
|
|
|
|
IScopeTree* pIST = GetScopeTreePtr();
|
|
ASSERT(pIST != NULL);
|
|
if (!pIST)
|
|
return (sc = E_NOINTERFACE);
|
|
|
|
long length = 0;
|
|
CCoTaskMemPtr<MTNODEID> spIDs;
|
|
sc = pIST->GetIDPath(id, &spIDs, &length);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
ASSERT(length);
|
|
ASSERT(spIDs);
|
|
|
|
ASSERT(m_pTreeCtrl != NULL);
|
|
if (m_pTreeCtrl)
|
|
m_pTreeCtrl->ExpandNode(spIDs, length, fExpand, fExpandVisually);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
ViewSettings::ViewSettings(CAMCView* v)
|
|
: m_nViewID(v->m_nViewID), m_bDescriptionbarVisible(v->IsDescBarVisible()),
|
|
m_nViewMode(v->m_nViewMode), m_nListViewStyle(v->GetDefaultListViewStyle()),
|
|
m_DefaultLVStyle(v->m_DefaultLVStyle), m_bScopePaneVisible(v->IsScopePaneVisible())
|
|
{
|
|
|
|
ASSERT(v != NULL);
|
|
v->GetPaneInfo (CConsoleView::ePane_ScopeTree, &m_Scope.cxWidth, &m_Scope.cxMin);
|
|
v->GetDefaultColumnWidths(m_DefaultColumnWidths);
|
|
}
|
|
|
|
/*
|
|
* The location and hidden fields of the scope structure were redundant and are
|
|
* no longer used. Both fields were used to indicate when the scope pane was
|
|
* hidden, which is also determined by the FLAG1_SCOPE_VISIBLE flag. The space
|
|
* has been retained to avoid changing the persisted structure.
|
|
*/
|
|
|
|
struct PersistedViewData
|
|
{
|
|
WINDOWPLACEMENT windowPlacement;
|
|
|
|
struct
|
|
{
|
|
int location; // not used, but kept for compatibility
|
|
int min;
|
|
int ideal;
|
|
BOOL hidden; // not used, but kept for compatibility
|
|
} scope;
|
|
|
|
int viewMode;
|
|
long listViewStyle;
|
|
ULONG ulFlag1;
|
|
int viewID;
|
|
BOOL descriptionBarVisible;
|
|
int defaultColumnWidth[2];
|
|
};
|
|
|
|
|
|
/*
|
|
* The sense of the FLAG1_NO_xxx flags is negative. That is, when a
|
|
* FLAG1_NO_xxx flag is set, its corresponding UI element is *not*
|
|
* displayed. This is to maintain compatibility with console files
|
|
* created before the existence of the FLAG1_NO_xxx flags. These
|
|
* consoles always had all UI elements displayed, and the then-unused
|
|
* bits in their flags field were defaulted to 0. To maintain
|
|
* compatibility, we have to maintain that (0 == on).
|
|
*/
|
|
|
|
#define FLAG1_SCOPE_PANE_VISIBLE 0x00000001
|
|
#define FLAG1_NO_STD_MENUS 0x00000002
|
|
#define FLAG1_NO_STD_BUTTONS 0x00000004
|
|
#define FLAG1_NO_SNAPIN_MENUS 0x00000008
|
|
#define FLAG1_NO_SNAPIN_BUTTONS 0x00000010
|
|
#define FLAG1_DISABLE_SCOPEPANE 0x00000020
|
|
#define FLAG1_DISABLE_STD_TOOLBARS 0x00000040
|
|
#define FLAG1_CUSTOM_TITLE 0x00000080
|
|
#define FLAG1_NO_STATUS_BAR 0x00000100
|
|
#define FLAG1_CREATED_IN_USER_MODE 0x00000200 // used to be named FLAG1_NO_AUTHOR_MODE
|
|
//#define FLAG1_FAVORITES_SELECTED 0x00000400 // unused, but don't recycle (for compatibility)
|
|
#define FLAG1_NO_TREE_ALLOWED 0x00000800 // used for compatibility with MMC1.2 in CAMCView::Load.
|
|
// Do not use for any other purposes.
|
|
#define FLAG1_NO_TASKPAD_TABS 0x00001000
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* ARRAY: mappedViewModes
|
|
*
|
|
* PURPOSE: provides map to be used when persisting ViewMode enumeration
|
|
*
|
|
\***************************************************************************/
|
|
static const EnumLiteral mappedViewModes[] =
|
|
{
|
|
{ MMCLV_VIEWSTYLE_ICON, XML_ENUM_LV_STYLE_ICON },
|
|
{ MMCLV_VIEWSTYLE_REPORT, XML_ENUM_LV_STYLE_REPORT },
|
|
{ MMCLV_VIEWSTYLE_SMALLICON, XML_ENUM_LV_STYLE_SMALLICON },
|
|
{ MMCLV_VIEWSTYLE_LIST, XML_ENUM_LV_STYLE_LIST },
|
|
{ MMCLV_VIEWSTYLE_FILTERED, XML_ENUM_LV_STYLE_FILTERED},
|
|
};
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* ARRAY: mappedListStyles
|
|
*
|
|
* PURPOSE: provides map to be used when persisting ListView style flag
|
|
*
|
|
\***************************************************************************/
|
|
static const EnumLiteral mappedListStyles[] =
|
|
{
|
|
{ LVS_SINGLESEL, XML_BITFLAG_LV_STYLE_SINGLESEL },
|
|
{ LVS_SHOWSELALWAYS, XML_BITFLAG_LV_STYLE_SHOWSELALWAYS },
|
|
{ LVS_SORTASCENDING, XML_BITFLAG_LV_STYLE_SORTASCENDING },
|
|
{ LVS_SORTDESCENDING, XML_BITFLAG_LV_STYLE_SORTDESCENDING },
|
|
{ LVS_SHAREIMAGELISTS, XML_BITFLAG_LV_STYLE_SHAREIMAGELISTS },
|
|
{ LVS_NOLABELWRAP, XML_BITFLAG_LV_STYLE_NOLABELWRAP },
|
|
{ LVS_AUTOARRANGE, XML_BITFLAG_LV_STYLE_AUTOARRANGE },
|
|
{ LVS_EDITLABELS, XML_BITFLAG_LV_STYLE_EDITLABELS },
|
|
{ LVS_OWNERDATA, XML_BITFLAG_LV_STYLE_OWNERDATA },
|
|
{ LVS_NOSCROLL, XML_BITFLAG_LV_STYLE_NOSCROLL },
|
|
{ LVS_ALIGNLEFT, XML_BITFLAG_LV_STYLE_ALIGNLEFT },
|
|
{ LVS_OWNERDRAWFIXED, XML_BITFLAG_LV_STYLE_OWNERDRAWFIXED },
|
|
{ LVS_NOCOLUMNHEADER, XML_BITFLAG_LV_STYLE_NOCOLUMNHEADER },
|
|
{ LVS_NOSORTHEADER, XML_BITFLAG_LV_STYLE_NOSORTHEADER },
|
|
};
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* ARRAY: mappedViewFlags
|
|
*
|
|
* PURPOSE: provides map to be used when persisting View flags
|
|
*
|
|
\***************************************************************************/
|
|
static const EnumLiteral mappedViewFlags[] =
|
|
{
|
|
{ FLAG1_SCOPE_PANE_VISIBLE, XML_BITFLAG_VIEW_SCOPE_PANE_VISIBLE },
|
|
{ FLAG1_NO_STD_MENUS, XML_BITFLAG_VIEW_NO_STD_MENUS },
|
|
{ FLAG1_NO_STD_BUTTONS, XML_BITFLAG_VIEW_NO_STD_BUTTONS },
|
|
{ FLAG1_NO_SNAPIN_MENUS, XML_BITFLAG_VIEW_NO_SNAPIN_MENUS },
|
|
{ FLAG1_NO_SNAPIN_BUTTONS, XML_BITFLAG_VIEW_NO_SNAPIN_BUTTONS },
|
|
{ FLAG1_DISABLE_SCOPEPANE, XML_BITFLAG_VIEW_DISABLE_SCOPEPANE },
|
|
{ FLAG1_DISABLE_STD_TOOLBARS, XML_BITFLAG_VIEW_DISABLE_STD_TOOLBARS },
|
|
{ FLAG1_CUSTOM_TITLE, XML_BITFLAG_VIEW_CUSTOM_TITLE },
|
|
{ FLAG1_NO_STATUS_BAR, XML_BITFLAG_VIEW_NO_STATUS_BAR },
|
|
{ FLAG1_CREATED_IN_USER_MODE, XML_BITFLAG_VIEW_CREATED_IN_USER_MODE },
|
|
{ FLAG1_NO_TASKPAD_TABS, XML_BITFLAG_VIEW_NO_TASKPAD_TABS },
|
|
};
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* ARRAY: mappedSWCommands
|
|
*
|
|
* PURPOSE: provides mapping to persist show commands as literals
|
|
*
|
|
\***************************************************************************/
|
|
static const EnumLiteral mappedSWCommands[] =
|
|
{
|
|
{ SW_HIDE, XML_ENUM_SHOW_CMD_HIDE },
|
|
{ SW_SHOWNORMAL, XML_ENUM_SHOW_CMD_SHOWNORMAL },
|
|
{ SW_SHOWMINIMIZED, XML_ENUM_SHOW_CMD_SHOWMINIMIZED },
|
|
{ SW_SHOWMAXIMIZED, XML_ENUM_SHOW_CMD_SHOWMAXIMIZED },
|
|
{ SW_SHOWNOACTIVATE, XML_ENUM_SHOW_CMD_SHOWNOACTIVATE },
|
|
{ SW_SHOW, XML_ENUM_SHOW_CMD_SHOW },
|
|
{ SW_MINIMIZE, XML_ENUM_SHOW_CMD_MINIMIZE },
|
|
{ SW_SHOWMINNOACTIVE, XML_ENUM_SHOW_CMD_SHOWMINNOACTIVE },
|
|
{ SW_SHOWNA, XML_ENUM_SHOW_CMD_SHOWNA },
|
|
{ SW_RESTORE, XML_ENUM_SHOW_CMD_RESTORE },
|
|
{ SW_SHOWDEFAULT, XML_ENUM_SHOW_CMD_SHOWDEFAULT },
|
|
{ SW_FORCEMINIMIZE, XML_ENUM_SHOW_CMD_FORCEMINIMIZE },
|
|
};
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* ARRAY: mappedWPFlags
|
|
*
|
|
* PURPOSE: provides mapping to persist WP flags
|
|
*
|
|
\***************************************************************************/
|
|
|
|
static const EnumLiteral mappedWPFlags[] =
|
|
{
|
|
{ WPF_SETMINPOSITION, XML_ENUM_WIN_PLACE_SETMINPOSITION },
|
|
{ WPF_RESTORETOMAXIMIZED, XML_ENUM_WIN_PLACE_RESTORETOMAXIMIZED },
|
|
#ifdef WPF_ASYNCWINDOWPLACEMENT
|
|
{ WPF_ASYNCWINDOWPLACEMENT, XML_ENUM_WIN_PLACE_ASYNCWINDOWPLACEMENT },
|
|
#else
|
|
{ 4, XML_ENUM_WIN_PLACE_ASYNCWINDOWPLACEMENT },
|
|
#endif
|
|
};
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* PersistViewData(CPersistor &persistor, PersistedViewData viewData)
|
|
*
|
|
*
|
|
* PURPOSE: Persists a PersistedViewData object to the specified persistor.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void PersistViewData(CPersistor &persistor, PersistedViewData& viewData)
|
|
{
|
|
persistor.PersistAttribute(XML_ATTR_VIEW_ID, viewData.viewID);
|
|
|
|
// write out the windowPlacement structure.
|
|
persistor.Persist(CXMLWindowPlacement(viewData.windowPlacement));
|
|
|
|
// write out the scope structure
|
|
persistor.PersistAttribute(XML_ATTR_VIEW_SCOPE_WIDTH, viewData.scope.ideal);
|
|
|
|
if (persistor.IsLoading())
|
|
{
|
|
// initialize for compatibility;
|
|
viewData.scope.hidden = true;
|
|
viewData.scope.location = 0;
|
|
viewData.scope.min = 50;
|
|
}
|
|
|
|
// write out the remaining fields
|
|
CPersistor persistorSettings(persistor, XML_TAG_VIEW_SETTINGS_2);
|
|
|
|
// create wrapper to persist enumeration values as strings
|
|
CXMLEnumeration viewModePersistor(viewData.viewMode, mappedViewModes, countof(mappedViewModes));
|
|
// persist the wrapper
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_VIEW_MODE, viewModePersistor);
|
|
|
|
// create wrapper to persist flag values as strings
|
|
CXMLBitFlags viewStylePersistor(viewData.listViewStyle, mappedListStyles, countof(mappedListStyles));
|
|
// persist the wrapper
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_LIST_STYLE, viewStylePersistor);
|
|
|
|
// create wrapper to persist flag values as strings
|
|
CXMLBitFlags flagPersistor(viewData.ulFlag1, mappedViewFlags, countof(mappedViewFlags));
|
|
// persist the wrapper
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_FLAG, flagPersistor);
|
|
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DB_VISIBLE, CXMLBoolean(viewData.descriptionBarVisible));
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DEF_COL_W0, viewData.defaultColumnWidth[0]);
|
|
persistorSettings.PersistAttribute(XML_ATTR_VIEW_SETNGS_DEF_COL_W1, viewData.defaultColumnWidth[1]);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Persist
|
|
*
|
|
* PURPOSE: Persists the CAMCView object to the specified persistor. Based
|
|
* on CAMCView::Save.
|
|
*
|
|
* PARAMETERS:
|
|
* CPersistor& persistor :
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::Persist(CPersistor& persistor)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Persist"));
|
|
|
|
HRESULT hr;
|
|
|
|
CBookmark bmr;
|
|
CBookmark bms;
|
|
if (persistor.IsStoring())
|
|
{
|
|
sc = GetRootNodePath(&bmr);
|
|
if (sc)
|
|
sc.Throw();
|
|
persistor.Persist(bmr, XML_NAME_ROOT_NODE); // ... its too late for root node when loading
|
|
|
|
sc = GetSelectedNodePath(&bms);
|
|
if (sc)
|
|
sc.Throw();
|
|
}
|
|
persistor.Persist(bms, XML_NAME_SELECTED_NODE);
|
|
|
|
// mostly copied from CAMCView::Save
|
|
|
|
// Get the parent frame
|
|
CWnd* const pParent = GetParent();
|
|
sc = ScCheckPointers(pParent,E_POINTER);
|
|
if (sc)
|
|
sc.Throw();
|
|
|
|
// Get the frames state data
|
|
PersistedViewData vd;
|
|
vd.windowPlacement.length = sizeof(vd.windowPlacement);
|
|
const BOOL bGotPlacement = pParent->GetWindowPlacement(&vd.windowPlacement);
|
|
if (!bGotPlacement)
|
|
sc.Throw(E_FAIL);
|
|
|
|
if (persistor.IsStoring())
|
|
{
|
|
/*
|
|
* If this window is minimized, make sure we set things up so the
|
|
* WINDOWPLACEMENT.ptMinPosition will be restored by SetWindowPlacement
|
|
* when we load. If we don't do this, it'll get some random min
|
|
* position, likely not what we want.
|
|
*/
|
|
if (vd.windowPlacement.showCmd == SW_SHOWMINIMIZED)
|
|
vd.windowPlacement.flags |= WPF_SETMINPOSITION;
|
|
|
|
|
|
GetPaneInfo(ePane_ScopeTree, &vd.scope.ideal, &vd.scope.min);
|
|
vd.viewMode = m_nViewMode;
|
|
vd.listViewStyle = GetDefaultListViewStyle();
|
|
|
|
vd.ulFlag1 = 0;
|
|
|
|
if (IsScopePaneVisible())
|
|
vd.ulFlag1 |= FLAG1_SCOPE_PANE_VISIBLE;
|
|
|
|
if (!IsAuthorModeView())
|
|
vd.ulFlag1 |= FLAG1_CREATED_IN_USER_MODE;
|
|
|
|
if (!(m_ViewData.m_dwToolbarsDisplayed & STD_MENUS))
|
|
vd.ulFlag1 |= FLAG1_NO_STD_MENUS;
|
|
|
|
if (!(m_ViewData.m_dwToolbarsDisplayed & STD_BUTTONS))
|
|
vd.ulFlag1 |= FLAG1_NO_STD_BUTTONS;
|
|
|
|
if (!(m_ViewData.m_dwToolbarsDisplayed & SNAPIN_MENUS))
|
|
vd.ulFlag1 |= FLAG1_NO_SNAPIN_MENUS;
|
|
|
|
if (!(m_ViewData.m_dwToolbarsDisplayed & SNAPIN_BUTTONS))
|
|
vd.ulFlag1 |= FLAG1_NO_SNAPIN_BUTTONS;
|
|
|
|
if (!(m_ViewData.m_dwToolbarsDisplayed & STATUS_BAR))
|
|
vd.ulFlag1 |= FLAG1_NO_STATUS_BAR;
|
|
|
|
if (!AreStdToolbarsAllowed ())
|
|
vd.ulFlag1 |= FLAG1_DISABLE_STD_TOOLBARS;
|
|
|
|
if (!IsScopePaneAllowed ())
|
|
vd.ulFlag1 |= FLAG1_DISABLE_SCOPEPANE;
|
|
|
|
if (HasCustomTitle ())
|
|
vd.ulFlag1 |= FLAG1_CUSTOM_TITLE;
|
|
|
|
if (!AreTaskpadTabsAllowed())
|
|
(vd.ulFlag1 |= FLAG1_NO_TASKPAD_TABS);
|
|
|
|
vd.viewID = GetViewID();
|
|
vd.descriptionBarVisible = IsDescBarVisible();
|
|
|
|
GetDefaultColumnWidths(vd.defaultColumnWidth);
|
|
}
|
|
|
|
PersistViewData(persistor,vd);
|
|
|
|
if (persistor.IsLoading())
|
|
{
|
|
ASSERT(int(m_nViewID) == vd.viewID);
|
|
m_ViewData.m_nViewID = m_nViewID = vd.viewID;
|
|
if (int(m_nViewID) >= static_nViewID)
|
|
static_nViewID = m_nViewID + 1;
|
|
|
|
//SetDefaultColumnWidths(vd.defaultColumnWidth);
|
|
SetDescBarVisible(vd.descriptionBarVisible);
|
|
|
|
// we shouldn't restore maximized window position
|
|
// since it may not be proper one for the current resolution
|
|
// related to bug #404118
|
|
WINDOWPLACEMENT orgPlacement;
|
|
ZeroMemory(&orgPlacement,sizeof(orgPlacement));
|
|
orgPlacement.length = sizeof(orgPlacement);
|
|
if (pParent->GetWindowPlacement(&orgPlacement))
|
|
{
|
|
vd.windowPlacement.ptMaxPosition = orgPlacement.ptMaxPosition;
|
|
}
|
|
|
|
m_ViewData.SetScopePaneVisible( 0 != (vd.ulFlag1 & FLAG1_SCOPE_PANE_VISIBLE) );
|
|
|
|
// Set the location and size of the frame
|
|
const BOOL bPlaced = pParent->SetWindowPlacement(&vd.windowPlacement);
|
|
if (!bPlaced)
|
|
sc.Throw(E_FAIL);
|
|
|
|
// Restore window settings
|
|
if (vd.ulFlag1 & FLAG1_DISABLE_SCOPEPANE)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOSCOPEPANE;
|
|
|
|
if (vd.ulFlag1 & FLAG1_DISABLE_STD_TOOLBARS)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOTOOLBARS;
|
|
|
|
if (vd.ulFlag1 & FLAG1_CUSTOM_TITLE)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_CUSTOMTITLE;
|
|
|
|
SetAuthorModeView (!(vd.ulFlag1 & FLAG1_CREATED_IN_USER_MODE));
|
|
|
|
if ((vd.ulFlag1 & FLAG1_NO_TASKPAD_TABS))
|
|
SetTaskpadTabsAllowed(FALSE);
|
|
|
|
// Apply run time restrictions
|
|
// if at least one type of scope pane allowed then if the selected
|
|
// one is not allowed, switch to the other. If neither is allowed
|
|
// then keep the selection and hide the scope pane.
|
|
if (IsScopePaneAllowed())
|
|
{
|
|
// Restore scope pane settings
|
|
SetPaneInfo(ePane_ScopeTree, vd.scope.ideal, vd.scope.min);
|
|
|
|
sc = ScShowScopePane ( m_ViewData.IsScopePaneVisible() );
|
|
}
|
|
else
|
|
sc = ScShowScopePane (false);
|
|
|
|
if (sc)
|
|
sc.Throw();
|
|
|
|
// Force layout re-calculation
|
|
DeferRecalcLayout();
|
|
|
|
// Restore view style & view mode if persisted will be set by nodemgr.
|
|
SetDefaultListViewStyle(vd.listViewStyle);
|
|
|
|
DWORD dwToolbars = 0;
|
|
if (!(vd.ulFlag1 & FLAG1_NO_STD_MENUS))
|
|
dwToolbars |= STD_MENUS;
|
|
if (!(vd.ulFlag1 & FLAG1_NO_STD_BUTTONS))
|
|
dwToolbars |= STD_BUTTONS;
|
|
if (!(vd.ulFlag1 & FLAG1_NO_SNAPIN_MENUS))
|
|
dwToolbars |= SNAPIN_MENUS;
|
|
if (!(vd.ulFlag1 & FLAG1_NO_SNAPIN_BUTTONS))
|
|
dwToolbars |= SNAPIN_BUTTONS;
|
|
if (!(vd.ulFlag1 & FLAG1_NO_STATUS_BAR))
|
|
dwToolbars |= STATUS_BAR;
|
|
|
|
// display the status bar appropriately
|
|
if (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) != StatusBarOf (dwToolbars))
|
|
{
|
|
CChildFrame* pFrame = GetParentFrame ();
|
|
if (pFrame != NULL)
|
|
{
|
|
pFrame->ToggleStatusBar();
|
|
SetStatusBarVisible(!IsStatusBarVisible());
|
|
|
|
ASSERT (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) ==
|
|
StatusBarOf (dwToolbars));
|
|
}
|
|
}
|
|
|
|
// display the appropriate toolbars
|
|
if (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) != ToolbarsOf (dwToolbars))
|
|
{
|
|
m_spNodeCallback->UpdateWindowLayout(
|
|
reinterpret_cast<LONG_PTR>(&m_ViewData), dwToolbars);
|
|
ASSERT (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) ==
|
|
ToolbarsOf (dwToolbars));
|
|
}
|
|
|
|
// Update the status of MMC menus.
|
|
sc = ScUpdateMMCMenus();
|
|
if (sc)
|
|
sc.Throw();
|
|
|
|
SetDirty (false);
|
|
m_pHistoryList->Clear();
|
|
}
|
|
|
|
SaveStartingSelectedNode();
|
|
|
|
if (persistor.IsLoading())
|
|
{
|
|
SC sc;
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
if(!pScopeTree)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return;
|
|
}
|
|
|
|
MTNODEID idTemp = 0;
|
|
bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark, unused
|
|
sc = pScopeTree->GetNodeIDFromBookmark(bms, &idTemp, bExactMatchFound);
|
|
if(sc)
|
|
return;
|
|
|
|
sc = ScSelectNode(idTemp);
|
|
if(sc)
|
|
return;
|
|
}
|
|
|
|
// if we've stored everything -we're clean
|
|
if (persistor.IsStoring())
|
|
SetDirty (false);
|
|
}
|
|
|
|
|
|
bool CAMCView::Load(IStream& stream)
|
|
// Caller is responsible for notifying user if false is returned
|
|
{
|
|
TRACE_METHOD(CAMCView, Load);
|
|
|
|
SetDirty (false);
|
|
|
|
// Read the view data from the stream.
|
|
ASSERT(&stream);
|
|
if (!&stream)
|
|
return false;
|
|
PersistedViewData pvd;
|
|
unsigned long bytesRead;
|
|
HRESULT hr = stream.Read(&pvd, sizeof(pvd), &bytesRead);
|
|
ASSERT(SUCCEEDED(hr) && bytesRead == sizeof(pvd));
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
ASSERT(int(m_nViewID) == pvd.viewID);
|
|
m_ViewData.m_nViewID = m_nViewID = pvd.viewID;
|
|
if (int(m_nViewID) >= static_nViewID)
|
|
static_nViewID = m_nViewID + 1;
|
|
|
|
//SetDefaultColumnWidths(pvd.defaultColumnWidth);
|
|
SetDescBarVisible(pvd.descriptionBarVisible);
|
|
|
|
// Get the parent frame
|
|
CWnd* const pParent = GetParent();
|
|
ASSERT(pParent != NULL);
|
|
if (pParent == NULL)
|
|
return false;
|
|
|
|
// we shouldn't restore maximized window position
|
|
// since it may not be proper one for the current resolution
|
|
// related to bug #404118
|
|
WINDOWPLACEMENT orgPlacement;
|
|
ZeroMemory(&orgPlacement,sizeof(orgPlacement));
|
|
orgPlacement.length = sizeof(orgPlacement);
|
|
if (pParent->GetWindowPlacement(&orgPlacement))
|
|
{
|
|
pvd.windowPlacement.ptMaxPosition = orgPlacement.ptMaxPosition;
|
|
}
|
|
|
|
// Set the location and size of the frame
|
|
const BOOL bPlaced = pParent->SetWindowPlacement(&pvd.windowPlacement);
|
|
ASSERT(bPlaced != FALSE);
|
|
if (bPlaced == FALSE)
|
|
return false;
|
|
|
|
// Restore window settings
|
|
if (pvd.ulFlag1 & FLAG1_DISABLE_SCOPEPANE)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOSCOPEPANE;
|
|
|
|
if (pvd.ulFlag1 & FLAG1_DISABLE_STD_TOOLBARS)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_NOTOOLBARS;
|
|
|
|
if (pvd.ulFlag1 & FLAG1_CUSTOM_TITLE)
|
|
m_ViewData.m_lWindowOptions |= MMC_NW_OPTION_CUSTOMTITLE;
|
|
|
|
SetAuthorModeView (!(pvd.ulFlag1 & FLAG1_CREATED_IN_USER_MODE));
|
|
|
|
if ((pvd.ulFlag1 & FLAG1_NO_TASKPAD_TABS))
|
|
SetTaskpadTabsAllowed(FALSE);
|
|
|
|
// Restore scope pane settings
|
|
SetPaneInfo(ePane_ScopeTree, pvd.scope.ideal, pvd.scope.min);
|
|
|
|
// The FLAG1_NO_TREE_ALLOWED is used only for compatibility with MMC1.2 console files
|
|
// It is a relic from old console files that does not exist in MMC2.0 console files.
|
|
bool bScopeTreeNotAllowed = (pvd.ulFlag1 & FLAG1_NO_TREE_ALLOWED);
|
|
|
|
SC sc;
|
|
|
|
if ( (IsScopePaneAllowed()) && (! bScopeTreeNotAllowed) )
|
|
sc = ScShowScopePane ((pvd.ulFlag1 & FLAG1_SCOPE_PANE_VISIBLE) != 0);
|
|
else
|
|
sc = ScShowScopePane (false);
|
|
|
|
if (sc)
|
|
return (false);
|
|
|
|
// Force layout re-calculation
|
|
DeferRecalcLayout();
|
|
|
|
// Restore view style & view mode if persisted will be set by nodemgr.
|
|
SetDefaultListViewStyle(pvd.listViewStyle);
|
|
|
|
DWORD dwToolbars = 0;
|
|
if (!(pvd.ulFlag1 & FLAG1_NO_STD_MENUS))
|
|
dwToolbars |= STD_MENUS;
|
|
if (!(pvd.ulFlag1 & FLAG1_NO_STD_BUTTONS))
|
|
dwToolbars |= STD_BUTTONS;
|
|
if (!(pvd.ulFlag1 & FLAG1_NO_SNAPIN_MENUS))
|
|
dwToolbars |= SNAPIN_MENUS;
|
|
if (!(pvd.ulFlag1 & FLAG1_NO_SNAPIN_BUTTONS))
|
|
dwToolbars |= SNAPIN_BUTTONS;
|
|
if (!(pvd.ulFlag1 & FLAG1_NO_STATUS_BAR))
|
|
dwToolbars |= STATUS_BAR;
|
|
|
|
// display the status bar appropriately
|
|
if (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) != StatusBarOf (dwToolbars))
|
|
{
|
|
CChildFrame* pFrame = GetParentFrame ();
|
|
if (pFrame != NULL)
|
|
{
|
|
pFrame->ToggleStatusBar();
|
|
SetStatusBarVisible(!IsStatusBarVisible());
|
|
|
|
ASSERT (StatusBarOf (m_ViewData.m_dwToolbarsDisplayed) ==
|
|
StatusBarOf (dwToolbars));
|
|
}
|
|
}
|
|
|
|
// display the appropriate toolbars
|
|
if (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) != ToolbarsOf (dwToolbars))
|
|
{
|
|
m_spNodeCallback->UpdateWindowLayout(
|
|
reinterpret_cast<LONG_PTR>(&m_ViewData), dwToolbars);
|
|
ASSERT (ToolbarsOf (m_ViewData.m_dwToolbarsDisplayed) ==
|
|
ToolbarsOf (dwToolbars));
|
|
}
|
|
|
|
// Update the status of MMC menus.
|
|
sc = ScUpdateMMCMenus();
|
|
if (sc)
|
|
return false;
|
|
|
|
SetDirty (false);
|
|
m_pHistoryList->Clear();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScSpecialResultpaneSelectionActivate
|
|
//
|
|
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
|
|
// of view of selected items and MMCN_SELECT. This is not
|
|
// the same as the MFC concept of "active view". There are a couple
|
|
// of views that cannot be active in this sense, such as the taskpad
|
|
// and tab views.
|
|
// When the active view (according to this definition) changes, this
|
|
// function is called. Thus, ScTreeViewSelectionActivate and
|
|
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
|
|
// are always called in pairs when the activation changes, one to handle
|
|
// deactivation, and one to handle activation.
|
|
//
|
|
// Consider the following scenario
|
|
// 1) The tree view has (MFC/windows style) focus.
|
|
// 2) The user clicks on the taskpad view
|
|
// Result - selection activation does not change from the tree. All verbs
|
|
// still correspond to the selected tree item.
|
|
// 3) The user clicks on the folder view
|
|
// Result - once again, selection activation does not chang
|
|
// 4) The user clicks on one of the result views eg the list
|
|
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
|
|
// Thus verbs and the toolbar now correspond to the selected list item(s).
|
|
// 5) The user clicks on the taskpad view.
|
|
// Result - as in step 2, nothing happens
|
|
// 6) The user clicks on the result view
|
|
// Result - because the active view has not changed, nothing happens.
|
|
//
|
|
// Arguments: [bActivate] - special result pane is selected/de-selected.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScSpecialResultpaneSelectionActivate(bool bActivate)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSpecialResultpaneSelectionActivate"));
|
|
|
|
/*
|
|
* Bug 331904: prevent recursion
|
|
*/
|
|
if (m_fActivatingSpecialResultPane)
|
|
{
|
|
TRACE (_T("CAMCView:ScSpecialResultpaneSelectionActivate: shorting out of recursion\n"));
|
|
return sc;
|
|
}
|
|
|
|
do
|
|
{
|
|
m_fActivatingSpecialResultPane = true;
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = FALSE;
|
|
selInfo.m_bDueToFocusChange = TRUE;
|
|
selInfo.m_bBackground = FALSE;
|
|
|
|
INodeCallback* pNodeCallBack = GetNodeCallback();
|
|
|
|
if (HasOCX())
|
|
{
|
|
selInfo.m_bResultPaneIsOCX = TRUE;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
|
|
}
|
|
else if (HasWebBrowser())
|
|
{
|
|
selInfo.m_bResultPaneIsWeb = TRUE;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
|
|
}
|
|
else
|
|
{
|
|
// Dont do anything. Just return.
|
|
m_fActivatingSpecialResultPane = false;
|
|
return sc;
|
|
}
|
|
|
|
sc = ScNotifySelect (pNodeCallBack, hNode, false /*fMultiSelect*/, bActivate, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
} while ( FALSE );
|
|
|
|
m_fActivatingSpecialResultPane = false;
|
|
|
|
return sc;
|
|
}
|
|
|
|
void CAMCView::CloseView()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::CloseView"));
|
|
|
|
TRACE_METHOD(CAMCView, CloseView);
|
|
|
|
// fire event to script
|
|
// this needs to be done while view is still 'alive'
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnCloseView, this);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
ASSERT(pScopeTree != NULL);
|
|
if (pScopeTree != NULL)
|
|
{
|
|
HRESULT hr = pScopeTree->CloseView(m_nViewID);
|
|
ASSERT(hr == S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
void CAMCView::OnDestroy()
|
|
{
|
|
TRACE_METHOD(CAMCView, OnDestroy);
|
|
|
|
// send the view destroy notification to all observers.
|
|
SC sc;
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnViewDestroyed, this);
|
|
if(sc)
|
|
sc.TraceAndClear();
|
|
|
|
if (IsPersisted())
|
|
{
|
|
if(m_pDocument != NULL)
|
|
m_pDocument->SetModifiedFlag(TRUE);
|
|
SetDirty();
|
|
}
|
|
|
|
CDocument* pDoc = GetDocument();
|
|
ASSERT(pDoc != NULL);
|
|
|
|
// if we were in ListPad-mode....
|
|
// this must be detached before destroying the Scopetree,
|
|
// because we need to send a notify to the snapin,
|
|
// which we get from the hnode.
|
|
if (m_pListCtrl->IsListPad())
|
|
{
|
|
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
|
|
if(sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
// make sure to stop running scripts if we have a web browser
|
|
if( HasWebBrowser() )
|
|
{
|
|
// no assert - may be already destroyed in DeleteEmptyView
|
|
//ASSERT( m_pWebViewCtrl != NULL );
|
|
if ( m_pWebViewCtrl != NULL )
|
|
{
|
|
m_pWebViewCtrl->DestroyWindow();
|
|
m_pWebViewCtrl = NULL;
|
|
}
|
|
}
|
|
|
|
// make sure to stop running scripts if we have a view extension
|
|
if ( m_fViewExtended )
|
|
{
|
|
// no assert - may be already destroyed in DeleteEmptyView
|
|
// ASSERT( m_pViewExtensionCtrl != NULL );
|
|
if ( m_pViewExtensionCtrl != NULL )
|
|
{
|
|
m_pViewExtensionCtrl->DestroyWindow();
|
|
m_pViewExtensionCtrl = NULL;
|
|
}
|
|
}
|
|
|
|
if (m_pTreeCtrl != NULL)
|
|
{
|
|
HNODE hNode = GetSelectedNode();
|
|
if (hNode)
|
|
m_pTreeCtrl->OnDeSelectNode(hNode);
|
|
|
|
m_pTreeCtrl->DeleteScopeTree();
|
|
}
|
|
|
|
IScopeTree* const pScopeTree = GetScopeTreePtr();
|
|
ASSERT(pScopeTree != NULL);
|
|
if (pScopeTree != NULL)
|
|
{
|
|
HRESULT hr = pScopeTree->DeleteView(m_nViewID);
|
|
ASSERT(hr == S_OK);
|
|
}
|
|
|
|
CView::OnDestroy();
|
|
}
|
|
|
|
void CAMCView::OnUpdateFileSnapinmanager(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->Enable ();
|
|
}
|
|
|
|
void CAMCView::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnSize);
|
|
|
|
CView::OnSize(nType, cx, cy);
|
|
|
|
if (nType != SIZE_MINIMIZED)
|
|
RecalcLayout();
|
|
}
|
|
|
|
SC CAMCView::ScToggleDescriptionBar()
|
|
{
|
|
TRACE_METHOD(CAMCView, ScToggleDescriptionBar);
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
SetDescBarVisible (!IsDescBarVisible());
|
|
SetDirty();
|
|
|
|
/*
|
|
* Don't defer this layout. This may be called by the Customize View
|
|
* dialog which wants to see its updates in real time. It will be
|
|
* sitting in a modal message loop so we won't get a chance to precess
|
|
* our idle task.
|
|
*/
|
|
RecalcLayout();
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
SC CAMCView::ScToggleStatusBar()
|
|
{
|
|
TRACE_METHOD(CAMCView, ScToggleStatusBar);
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScToggleStatusBar"));
|
|
|
|
CChildFrame* pFrame = GetParentFrame();
|
|
sc = ScCheckPointers (pFrame, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
pFrame->ToggleStatusBar();
|
|
|
|
SetStatusBarVisible (!IsStatusBarVisible());
|
|
SetDirty();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
SC CAMCView::ScToggleTaskpadTabs()
|
|
{
|
|
TRACE_METHOD(CAMCView, ScToggleTaskpadTabs);
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
SetTaskpadTabsAllowed (!AreTaskpadTabsAllowed());
|
|
SetDirty();
|
|
|
|
/*
|
|
* Don't defer this layout. This message will be sent by the
|
|
* Customize View dialog which wants to see its updates in
|
|
* real time. It will be sitting in a modal message loop so
|
|
* we won't get a chance to precess our idle task.
|
|
*/
|
|
RecalcLayout();
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
SC CAMCView::ScToggleScopePane()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScToggleScopePane"));
|
|
|
|
sc = ScShowScopePane (!IsScopePaneVisible());
|
|
if (sc)
|
|
return (sc);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
void CAMCView::OnActionMenu(CPoint point, LPCRECT prcExclude)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnActionMenu);
|
|
|
|
UINT fHitTestFlags = 0;
|
|
HTREEITEM hTreeItem = m_pTreeCtrl->GetSelectedItem( );
|
|
|
|
ASSERT_VALID (this);
|
|
|
|
/*
|
|
* BUG: 99643
|
|
* Right now there is inconsistency between what you get by action menu & right click
|
|
* on a location in taskpad. The action menu always assumes it is tree or if result
|
|
* pane it is list or ocx or web or background. So if a taskpad is selected it assumes
|
|
* the corresponding list item is selected or tree item is selected or background.
|
|
* But right click on taskpad calls CAMCView::OnContextMenu which determines nothing
|
|
* is selected and does nothing. This needs to be addressed.
|
|
*/
|
|
|
|
ASSERT(eActivePaneNone != m_eCurrentActivePane);
|
|
|
|
if (eActivePaneScope == m_eCurrentActivePane)
|
|
{
|
|
if (hTreeItem != NULL)
|
|
{
|
|
HNODE hNode = (HNODE)m_pTreeCtrl->GetItemData(hTreeItem);
|
|
OnContextMenuForTreeItem(INDEX_INVALID, hNode, point, CCT_SCOPE, hTreeItem, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
else
|
|
{
|
|
OnContextMenuForTreeBackground(point, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (HasListOrListPad())
|
|
{
|
|
int cSel = m_pListCtrl->GetSelectedCount();
|
|
int nIndex = -1;
|
|
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
if (cSel == 0)
|
|
lvData = LVDATA_BACKGROUND;
|
|
else if (cSel == 1)
|
|
nIndex = _GetLVSelectedItemData(&lvData);
|
|
else if (cSel > 1)
|
|
lvData = LVDATA_MULTISELECT;
|
|
|
|
|
|
ASSERT(lvData != LVDATA_ERROR);
|
|
if (lvData == LVDATA_ERROR)
|
|
return;
|
|
|
|
if (lvData == LVDATA_BACKGROUND)
|
|
{
|
|
// Find out which pane has focus to set the CMINFO_DO_SCOPEPANE_MENU flag.
|
|
HNODE hNode = GetSelectedNode();
|
|
DATA_OBJECT_TYPES ePaneType = (GetParentFrame()->GetActiveView() == m_pTreeCtrl) ? CCT_SCOPE : CCT_RESULT;
|
|
|
|
OnContextMenuForTreeItem(INDEX_BACKGROUND, hNode, point, ePaneType, hTreeItem, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
return;
|
|
}
|
|
else if (lvData == LVDATA_MULTISELECT)
|
|
{
|
|
OnContextMenuForListItem(INDEX_MULTISELECTION, NULL, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
else
|
|
{
|
|
if (IsVirtualList())
|
|
{
|
|
OnContextMenuForListItem(nIndex, (HRESULTITEM)NULL, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
else
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle (lvData);
|
|
|
|
if (pri != NULL)
|
|
{
|
|
if (pri->IsScopeItem())
|
|
OnContextMenuForTreeItem(nIndex, pri->GetScopeNode(), point, CCT_RESULT, NULL, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
else
|
|
OnContextMenuForListItem(nIndex, lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The active window may be a web page or task pad or ocx.
|
|
|
|
LPARAM lvData = LVDATA_ERROR;
|
|
|
|
if (HasOCX())
|
|
{
|
|
lvData = LVDATA_CUSTOMOCX;
|
|
OnContextMenuForListItem(INDEX_OCXPANE, (HRESULTITEM)lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
else if (HasWebBrowser())
|
|
{
|
|
lvData = LVDATA_CUSTOMWEB;
|
|
OnContextMenuForListItem(INDEX_WEBPANE, (HRESULTITEM)lvData, point, MMC_CONTEXT_MENU_ACTION, prcExclude, false/*bAllowDefaultItem*/);
|
|
}
|
|
else
|
|
{
|
|
// Some unknown window has the focus.
|
|
ASSERT(FALSE && "Unknown window has the focus");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SC CAMCView::ScUpOneLevel()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
TRACE_METHOD(CAMCView, ScUpOneLevel);
|
|
|
|
DECLARE_SC (sc, _T("CAMCView::ScUpOneLevel"));
|
|
sc = E_FAIL;
|
|
|
|
if (m_pTreeCtrl)
|
|
{
|
|
HTREEITEM htiParent = m_pTreeCtrl->GetParentItem (m_pTreeCtrl->GetSelectedItem());
|
|
|
|
if (htiParent)
|
|
{
|
|
m_pTreeCtrl->SelectItem(htiParent);
|
|
m_pTreeCtrl->EnsureVisible(htiParent);
|
|
sc = S_OK;
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
void CAMCView::OnViewMenu(CPoint point, LPCRECT prcExclude)
|
|
{
|
|
TRACE_METHOD(CAMCView, OnViewMenu);
|
|
|
|
OnContextMenuForListItem (INDEX_BACKGROUND, NULL, point,
|
|
MMC_CONTEXT_MENU_VIEW, prcExclude,
|
|
false /*bAllowDefaultItem*/);
|
|
}
|
|
|
|
void CAMCView::OnDrawClipboard()
|
|
{
|
|
if (m_htiCut)
|
|
{
|
|
m_pTreeCtrl->SetItemState(m_htiCut, 0, TVIS_CUT);
|
|
}
|
|
else
|
|
{
|
|
m_pListCtrl->CutSelectedItems(FALSE);
|
|
}
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::OnSettingChange
|
|
*
|
|
* PURPOSE: Handles WM_SETTINGCHANGE. Recalculates the layout. The
|
|
* result folder tab control needs this, for instance.
|
|
*
|
|
* PARAMETERS:
|
|
* UINT uFlags :
|
|
* LPCTSTR lpszSection :
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
|
|
{
|
|
DeferRecalcLayout();
|
|
}
|
|
|
|
void CAMCView::OnUpdatePasteBtn()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnUpdatePasteBtn"));
|
|
|
|
HNODE hNode = NULL;
|
|
LPARAM lvData = NULL;
|
|
bool bScope = FALSE;
|
|
|
|
sc = ScGetFocusedItem(hNode, lvData, bScope);
|
|
if (sc)
|
|
return;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(hNode, pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
sc = pNC->UpdatePasteButton(hNode, bScope, lvData);
|
|
if (sc)
|
|
return;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void CAMCView::OnContextHelp()
|
|
{
|
|
ScContextHelp();
|
|
}
|
|
|
|
|
|
SC CAMCView::ScContextHelp ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
|
|
m_fSnapinDisplayedHelp = false;
|
|
SC sc = SendGenericNotify(NCLBK_CONTEXTHELP);
|
|
|
|
// if snap-in hasn't called us to display a topic
|
|
// and it has not handled the notification then
|
|
// display MMC topic by default
|
|
if (!m_fSnapinDisplayedHelp && (sc.ToHr() != S_OK))
|
|
sc = ScHelpTopics ();
|
|
|
|
if (sc)
|
|
TraceError (_T("CAMCView::ScContextHelp"), sc);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
void CAMCView::OnSnapInHelp()
|
|
{
|
|
SendGenericNotify(NCLBK_SNAPINHELP);
|
|
}
|
|
|
|
void CAMCView::OnSnapinAbout()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnSnapinAbout"));
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
sc = ScCheckPointers((void*) hNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
INodeCallback *pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
sc = pNC->ShowAboutInformation(hNode);
|
|
if (sc)
|
|
return;
|
|
|
|
return;
|
|
}
|
|
|
|
void CAMCView::OnHelpTopics()
|
|
{
|
|
ScHelpTopics();
|
|
}
|
|
|
|
|
|
SC CAMCView::ScHelpWorker (LPCTSTR pszHelpTopic)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScShowSnapinHelpTopic"));
|
|
USES_CONVERSION;
|
|
|
|
/*
|
|
* generation of the help collection might take a while, so display
|
|
* a wait cursor
|
|
*/
|
|
CWaitCursor wait;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
CAMCDoc* pdoc = GetDocument();
|
|
|
|
// Point helpdoc info to current console file path
|
|
if (pdoc->GetPathName().IsEmpty())
|
|
pdoc->GetHelpDocInfo()->m_pszFileName = NULL;
|
|
else
|
|
pdoc->GetHelpDocInfo()->m_pszFileName = T2COLE(pdoc->GetPathName());
|
|
|
|
/*
|
|
* smart pointer for automatic deletion of the help file name
|
|
*/
|
|
CCoTaskMemPtr<WCHAR> spszHelpFile;
|
|
|
|
sc = pNC->Notify (0, NCLBK_GETHELPDOC,
|
|
reinterpret_cast<LPARAM>(pdoc->GetHelpDocInfo()),
|
|
reinterpret_cast<LPARAM>(&spszHelpFile));
|
|
|
|
if (sc)
|
|
return (sc);
|
|
|
|
CAMCApp* pAMCApp = AMCGetApp();
|
|
if (NULL == pAMCApp)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
sc = pAMCApp->ScShowHtmlHelp(W2T(spszHelpFile), (DWORD_PTR) pszHelpTopic);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
SC CAMCView::ScHelpTopics ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
return (ScHelpWorker (NULL));
|
|
}
|
|
|
|
|
|
SC CAMCView::ScShowSnapinHelpTopic (LPCTSTR pszHelpTopic)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
CString strTopicPath;
|
|
|
|
// Add protocol prefix to topic string
|
|
if (pszHelpTopic != NULL)
|
|
{
|
|
strTopicPath = _T("ms-its:");
|
|
strTopicPath += pszHelpTopic;
|
|
}
|
|
|
|
SC sc = ScHelpWorker (strTopicPath);
|
|
|
|
if (!sc)
|
|
m_fSnapinDisplayedHelp = true;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::UpdateSnapInHelpMenus
|
|
//
|
|
// Synopsis: Update the following Help menu items
|
|
// a) Help on <Snapin> (if snapin does not support HTML help)
|
|
// b) About <Snapin> (if snapin supports about object)
|
|
//
|
|
// Arguments: [pMenu] - The help popup menu.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void CAMCView::UpdateSnapInHelpMenus(CMenu* pMenu)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::UpdateSnapInHelpMenus"));
|
|
sc = ScCheckPointers(pMenu);
|
|
if (sc)
|
|
return;
|
|
|
|
ASSERT_VALID (this);
|
|
|
|
HNODE hNode = GetSelectedNode();
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(hNode, pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
goto Error;
|
|
|
|
// Empty block for goto's
|
|
{
|
|
// First Make sure this is not a dummy substitute snapin.
|
|
bool bDummySnapin = false;
|
|
sc = pNC->IsDummySnapin (hNode, bDummySnapin);
|
|
if (sc)
|
|
goto Error;
|
|
|
|
if (bDummySnapin)
|
|
goto Error;
|
|
|
|
// Get the snapin name for "Help on <SnapinName>" or "About <SnapinName>" menus
|
|
CCoTaskMemPtr<WCHAR> spszName;
|
|
CString strMenu;
|
|
|
|
// Try to get name of snap-in for custom menu item
|
|
bool bSnapinNameValid = false;
|
|
sc = pNC->GetSnapinName(hNode, &spszName, bSnapinNameValid);
|
|
if (sc)
|
|
goto Error;
|
|
|
|
ASSERT( spszName != NULL || bSnapinNameValid );
|
|
|
|
USES_CONVERSION;
|
|
|
|
// if snapin supports html help, don't give it it's own help command
|
|
bool bStandardHelpExists = false;
|
|
sc = pNC->DoesStandardSnapinHelpExist(hNode, bStandardHelpExists);
|
|
if (sc)
|
|
goto Error;
|
|
|
|
if (bStandardHelpExists)
|
|
{
|
|
pMenu->DeleteMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND);
|
|
}
|
|
else
|
|
{
|
|
if (bSnapinNameValid)
|
|
{
|
|
// "Help on <SnapinName>"
|
|
LoadString(strMenu, IDS_HELP_ON);
|
|
AfxFormatString1(strMenu, IDS_HELP_ON, OLE2T(spszName));
|
|
}
|
|
else
|
|
{
|
|
// ""Help on Snap-in"
|
|
LoadString(strMenu, IDS_HELP_ON_SNAPIN);
|
|
}
|
|
|
|
// Either add or modify the custom help menu item
|
|
if (pMenu->GetMenuState(ID_HELP_SNAPINHELP, MF_BYCOMMAND) == (UINT)-1)
|
|
{
|
|
pMenu->InsertMenu(ID_HELP_HELPTOPICS, MF_BYCOMMAND|MF_ENABLED, ID_HELP_SNAPINHELP, strMenu);
|
|
}
|
|
else
|
|
{
|
|
pMenu->ModifyMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND|MF_ENABLED, ID_HELP_SNAPINHELP, strMenu);
|
|
}
|
|
}
|
|
|
|
/* Now add the About <Snapin> menu*/
|
|
bool bAboutExists = false;
|
|
SC scNoTrace = pNC->DoesAboutExist(hNode, &bAboutExists);
|
|
if ( (scNoTrace.IsError()) || (!bAboutExists) )
|
|
{
|
|
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
|
|
return;
|
|
}
|
|
|
|
if (bSnapinNameValid)
|
|
{
|
|
// "About on <SnapinName>"
|
|
AfxFormatString1(strMenu, IDS_ABOUT_ON, OLE2T(spszName));
|
|
}
|
|
else
|
|
{
|
|
// Cant get name just delete & return
|
|
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
|
|
return;
|
|
}
|
|
|
|
if (pMenu->GetMenuState(ID_SNAPIN_ABOUT, MF_BYCOMMAND) == (UINT)-1)
|
|
{
|
|
pMenu->InsertMenu(-1, MF_BYPOSITION|MF_ENABLED, ID_SNAPIN_ABOUT, strMenu);
|
|
}
|
|
else
|
|
{
|
|
pMenu->ModifyMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND|MF_ENABLED, ID_SNAPIN_ABOUT, strMenu);
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
return;
|
|
Error:
|
|
pMenu->DeleteMenu(ID_HELP_SNAPINHELP, MF_BYCOMMAND);
|
|
pMenu->DeleteMenu(ID_SNAPIN_ABOUT, MF_BYCOMMAND);
|
|
goto Cleanup;
|
|
}
|
|
|
|
#ifdef IMPLEMENT_LIST_SAVE // See nodemgr.idl (t-dmarm)
|
|
/*
|
|
* Displays errors from the list save function and cleans up the file if necessary
|
|
*/
|
|
|
|
void CAMCView::ListSaveErrorMes(EListSaveErrorType etype, HANDLE hfile, LPCTSTR lpFileName)
|
|
{
|
|
CString strMessage;
|
|
|
|
switch (etype)
|
|
{
|
|
|
|
case LSaveCantCreate:
|
|
//"ERROR: Unable to create file."
|
|
FormatString1 (strMessage, IDS_LISTSAVE_ER1, lpFileName);
|
|
break;
|
|
|
|
case LSaveCantWrite:
|
|
// ERROR: Created file but encountered an error while writing to it
|
|
FormatString1 (strMessage, IDS_LISTSAVE_ER2, lpFileName);
|
|
break;
|
|
|
|
case LSaveReadOnly:
|
|
//"ERROR: File to be overwritten is read only."
|
|
FormatString1 (strMessage, IDS_LISTSAVE_ER3, lpFileName);
|
|
break;
|
|
|
|
default:
|
|
// Should not make it here
|
|
ASSERT(0);
|
|
}
|
|
MMCMessageBox (strMessage);
|
|
}
|
|
|
|
|
|
// Saves a list and performs necessary dialog boxes and error checking
|
|
SC CAMCView::ScSaveList()
|
|
{
|
|
DECLARE_SC(sc, _T("ScSaveList"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
sc = ScExportListWorker();
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScGetExportListFile
|
|
//
|
|
// Synopsis: Get the filename, flags for save list.
|
|
//
|
|
// Arguments: [strFileName] - File Name retval.
|
|
// [bUnicode] - Unicode or ansi.
|
|
// [bTabDelimited] - Tab or Comma delimited.
|
|
// [bSelectedRowsOnly] - selected items only or all items.
|
|
//
|
|
// Returns: SC, S_FALSE if user cancels dialog.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScGetExportListFile (CString& strFileName,
|
|
bool& bUnicode,
|
|
bool& bTabDelimited,
|
|
bool& bSelectedRowsOnly)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScGetExportListFile"));
|
|
|
|
CString strFilter;
|
|
LoadString(strFilter, IDS_ANSI_FILE_TYPE);
|
|
|
|
#ifdef UNICODE
|
|
{ // limit the lifetime of strUniFilter
|
|
CString strUniFilter;
|
|
LoadString(strUniFilter, IDS_UNICODE_FILE_TYPE);
|
|
strFilter += strUniFilter;
|
|
}
|
|
#endif
|
|
|
|
// End of Filter char
|
|
strFilter += "|";
|
|
|
|
sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// See if there are any items selected else disable the "Selected items only" check-box.
|
|
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
|
|
int iItem = ctlList.GetNextItem( -1,LVNI_SELECTED);
|
|
|
|
bool bSomeRowSelected = (-1 != iItem);
|
|
|
|
// Create the dialog. File extensions are not localized.
|
|
CSaveFileDialog dlgFile(false, _T("txt"), NULL,
|
|
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING,
|
|
strFilter, bSomeRowSelected);
|
|
|
|
// Display the dialog
|
|
if (dlgFile.DoModal() == IDCANCEL)
|
|
return S_FALSE; // S_FALSE if user cancels dialog.
|
|
|
|
// Create a wait cursor and redraw the screen (necessary in saving big files)
|
|
CWaitCursor wait;
|
|
AfxGetMainWnd()->RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW );
|
|
|
|
// Retrieve the filename
|
|
strFileName = dlgFile.GetPathName();
|
|
bSelectedRowsOnly = (dlgFile.Getflags() & SELECTED);
|
|
|
|
switch (dlgFile.GetFileType())
|
|
{
|
|
case FILE_ANSI_TEXT:
|
|
bTabDelimited = true; // Tab delimited.
|
|
bUnicode = false;
|
|
break;
|
|
|
|
case FILE_ANSI_CSV:
|
|
bTabDelimited = false; // Comma delimited.
|
|
bUnicode = false;
|
|
break;
|
|
|
|
#ifdef UNICODE
|
|
case FILE_UNICODE_TEXT:
|
|
bTabDelimited = true; // tab delimited.
|
|
bUnicode = true;
|
|
break;
|
|
|
|
case FILE_UNICODE_CSV:
|
|
bTabDelimited = false; // comma delimited.
|
|
bUnicode = true;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
sc = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScCreateExportListFile
|
|
//
|
|
// Synopsis: Create a file with given name & path. Write unicode marker if needed.
|
|
//
|
|
// Arguments: [strFileName] - file to create.
|
|
// [bUnicode] - unicode or ansi file.
|
|
// [bShowErrorDialogs] - Show error dialogs or not.
|
|
// [hFile] - Retval, handle to file.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScCreateExportListFile(const CString& strFileName, bool bUnicode,
|
|
bool bShowErrorDialogs, HANDLE& hFile)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScCreateExportListFile"));
|
|
|
|
// Create a file according to specs
|
|
hFile = CreateFile(strFileName, GENERIC_WRITE,
|
|
0, NULL, CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
DWORD dwAttrib = GetFileAttributes(strFileName);
|
|
|
|
// If it did not fail and the file is read-only
|
|
// Not required. Used to determine if the file being overwritten is read only and display appropriate message
|
|
if ((dwAttrib != 0xFFFFFFFF) &&
|
|
(dwAttrib & FILE_ATTRIBUTE_READONLY))
|
|
{
|
|
if (bShowErrorDialogs)
|
|
ListSaveErrorMes(LSaveReadOnly, hFile, strFileName);
|
|
|
|
return (sc = E_FAIL);
|
|
}
|
|
|
|
// Creation failed
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
if (bShowErrorDialogs)
|
|
ListSaveErrorMes(LSaveCantCreate, NULL, strFileName);
|
|
sc.FromWin32(::GetLastError());
|
|
return sc;
|
|
}
|
|
|
|
/*
|
|
* for Unicode files, write the Unicode prefix
|
|
*/
|
|
if (bUnicode)
|
|
{
|
|
const WCHAR chPrefix = 0xFEFF;
|
|
const DWORD cbToWrite = sizeof (chPrefix);
|
|
DWORD cbWritten;
|
|
|
|
if (!WriteFile (hFile, &chPrefix, cbToWrite, &cbWritten, NULL) ||
|
|
(cbToWrite != cbWritten))
|
|
{
|
|
CloseHandle(hFile);
|
|
DeleteFile( strFileName );
|
|
|
|
if (bShowErrorDialogs)
|
|
ListSaveErrorMes(LSaveCantWrite, hFile, strFileName);
|
|
|
|
return (sc = E_FAIL);
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScExportListWorker
|
|
//
|
|
// Synopsis: Prompt for a file name & write the ListView data to it.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScExportListWorker()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScExportListWorker"));
|
|
|
|
CString strFileName;
|
|
bool bUnicode = false;
|
|
bool bTabDelimited = false;
|
|
bool bSelectedRowsOnly = false;
|
|
|
|
sc = ScGetExportListFile(strFileName, bUnicode, bTabDelimited, bSelectedRowsOnly);
|
|
|
|
if (sc.ToHr() == S_FALSE) // if user cancels dialog.
|
|
return sc;
|
|
|
|
sc = ScWriteExportListData(strFileName, bUnicode, bTabDelimited, bSelectedRowsOnly);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScWriteExportListData
|
|
//
|
|
// Synopsis: Write ListView data to given file.
|
|
//
|
|
// Arguments: [strFileName] - File to create & write to.
|
|
// [bUnicode] - Unicode or ansi.
|
|
// [bTabDelimited] - Tab or Comma separated values.
|
|
// [bSelectedRowsOnly] - like Selected rows only.
|
|
// [bShowErrorDialogs] - Show error dialogs or not.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScWriteExportListData (const CString& strFileName,
|
|
bool bUnicode,
|
|
bool bTabDelimited,
|
|
bool bSelectedRowsOnly,
|
|
bool bShowErrorDialogs /*true*/)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScWriteExportListData"));
|
|
|
|
// Get number of rows and columns
|
|
const int cRows = m_pListCtrl->GetItemCount();
|
|
const int cCols = m_pListCtrl->GetColCount();
|
|
|
|
// If there are no columns inserted then there cannot be any
|
|
// items inserted into the listview. So error out.
|
|
|
|
if (cCols <= 0)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
HANDLE hFile = NULL;
|
|
sc = ScCreateExportListFile(strFileName, bUnicode, bShowErrorDialogs, hFile);
|
|
if (sc)
|
|
{
|
|
if (NULL != hFile)
|
|
{
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
// Retrieve the flags
|
|
CString strEol( _T("\r\n") );
|
|
|
|
LPCTSTR pszSeparator = _T("\t");
|
|
if (!bTabDelimited)
|
|
pszSeparator = _T(",");
|
|
|
|
// Determine how many columns must be printed
|
|
int printcols = 1;
|
|
|
|
struct ColInfo
|
|
{
|
|
CString strColName;
|
|
BOOL bHidden;
|
|
};
|
|
|
|
ColInfo* rgColumns = NULL;
|
|
int* pnColOrder = NULL;
|
|
|
|
// If it is LVS_REPORT, get the list of column names, order
|
|
// and hidden or not flag.
|
|
if ( (m_pListCtrl->GetViewMode() == LVS_REPORT) ||
|
|
(m_pListCtrl->GetViewMode() == MMCLV_VIEWSTYLE_FILTERED) )
|
|
{
|
|
printcols = cCols;
|
|
|
|
// Allocate mem to store col names, order, hidden states
|
|
rgColumns = new ColInfo[printcols];
|
|
if (! rgColumns)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
pnColOrder = new int[printcols];
|
|
if (! pnColOrder)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
CHeaderCtrl* pHeader = m_pListCtrl->GetHeaderCtrl();
|
|
sc = ScCheckPointers(pHeader, E_UNEXPECTED);
|
|
if (sc)
|
|
goto Error;
|
|
|
|
// Get the order
|
|
if (!Header_GetOrderArray(pHeader->GetSafeHwnd(), printcols, pnColOrder))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
// Get the name and hidden state of cols
|
|
for (int i = 0; i < printcols ; i++)
|
|
{
|
|
TCHAR szColName[MAX_PATH * 2];
|
|
HDITEM hdItem;
|
|
|
|
hdItem.mask = HDI_TEXT | HDI_LPARAM;
|
|
hdItem.pszText = szColName;
|
|
hdItem.cchTextMax = countof (szColName);
|
|
|
|
if (pHeader->GetItem (i, &hdItem))
|
|
{
|
|
CHiddenColumnInfo hci (hdItem.lParam);
|
|
|
|
rgColumns[i].strColName = hdItem.pszText;
|
|
rgColumns[i].bHidden = hci.fHidden;
|
|
}
|
|
else
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < printcols ; i++)
|
|
{
|
|
// Print the column name according to the order
|
|
|
|
if (rgColumns[pnColOrder[i]].bHidden)
|
|
continue;
|
|
|
|
if ( (!Write2File(hFile, rgColumns[pnColOrder[i]].strColName, bUnicode)) ||
|
|
((i < printcols - 1) && (!Write2File(hFile, pszSeparator, bUnicode))))
|
|
{
|
|
goto CantWriteError;
|
|
}
|
|
}
|
|
|
|
// Write an EOL character if necessary
|
|
if (!Write2File(hFile, strEol, bUnicode))
|
|
{
|
|
goto CantWriteError;
|
|
}
|
|
}
|
|
|
|
{
|
|
// Data for use in the writing stage
|
|
CString strData;
|
|
CListCtrl& ctlList = m_pListCtrl->GetListCtrl();
|
|
|
|
// Set iNextType to 0 if all items will be saved or LVNI_SELECTED if only selected ones will be saved
|
|
int iNextType = 0;
|
|
if (bSelectedRowsOnly)
|
|
iNextType = LVNI_SELECTED;
|
|
|
|
// Find the first item in the list
|
|
int iItem = ctlList.GetNextItem( -1,iNextType);
|
|
|
|
// Iterate until there are no more items to save
|
|
while (iItem != -1)
|
|
{
|
|
for(int ind2 = 0; ind2 < printcols ; ind2++)
|
|
{
|
|
if (rgColumns)
|
|
{
|
|
// If not hidden get the item
|
|
if (rgColumns[pnColOrder[ind2]].bHidden)
|
|
continue;
|
|
else
|
|
strData = ctlList.GetItemText( iItem, pnColOrder[ind2]);
|
|
}
|
|
else
|
|
strData = ctlList.GetItemText( iItem, ind2);
|
|
|
|
// Write the text and if necessary a comma
|
|
// If either one fails, then delete the file and return
|
|
if ( (!Write2File(hFile, strData, bUnicode)) ||
|
|
((ind2 < printcols - 1) && (!Write2File(hFile, pszSeparator, bUnicode))))
|
|
{
|
|
goto CantWriteError;
|
|
|
|
}
|
|
}
|
|
|
|
// Write an EOL character if necessary
|
|
if (!Write2File(hFile, strEol, bUnicode))
|
|
{
|
|
goto CantWriteError;
|
|
}
|
|
// Find the next item to save
|
|
iItem = ctlList.GetNextItem( iItem, iNextType);
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (rgColumns)
|
|
delete[] rgColumns;
|
|
|
|
if (pnColOrder)
|
|
delete[] pnColOrder;
|
|
|
|
CloseHandle(hFile);
|
|
return (sc);
|
|
|
|
CantWriteError:
|
|
if (bShowErrorDialogs)
|
|
ListSaveErrorMes(LSaveCantWrite, hFile, strFileName);
|
|
|
|
Error:
|
|
DeleteFile( strFileName );
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Write out a string to the given file
|
|
// Used as a separate function to preserve memory
|
|
// Returns true if successful, false otherwise
|
|
bool CAMCView::Write2File(HANDLE hfile, LPCTSTR strwrite, BOOL fUnicode)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Write2File"));
|
|
|
|
// parameter check;
|
|
sc = ScCheckPointers( strwrite );
|
|
if (sc)
|
|
return false;
|
|
|
|
// Initializes Macro
|
|
USES_CONVERSION;
|
|
|
|
// The number of bytes written
|
|
DWORD cbWritten;
|
|
DWORD cbToWrite;
|
|
|
|
if (fUnicode)
|
|
{
|
|
// Convert the string to Unicode and write it to hfile
|
|
LPCWSTR Ustring = T2CW( strwrite );
|
|
cbToWrite = wcslen (Ustring) * sizeof (WCHAR);
|
|
WriteFile(hfile, Ustring, cbToWrite, &cbWritten, NULL);
|
|
}
|
|
else
|
|
{
|
|
// Convert the string to ANSI and write it to hfile
|
|
const unsigned char* Astring = (const unsigned char*) T2CA( strwrite );
|
|
cbToWrite = _mbsnbcnt (Astring, _mbslen (Astring));
|
|
WriteFile(hfile, Astring, cbToWrite, &cbWritten, NULL);
|
|
}
|
|
|
|
// Make sure that the correct number of bytes were written
|
|
return (cbWritten == cbToWrite);
|
|
}
|
|
#endif // IMPLEMENT_LIST_SAVE See nodemgr.idl (t-dmarm)
|
|
|
|
// Refreshes all panes and HTML
|
|
void CAMCView::OnRefresh()
|
|
{
|
|
HWND hwnd = ::GetFocus();
|
|
|
|
if (IsVerbEnabled(MMC_VERB_REFRESH))
|
|
{
|
|
ScConsoleVerb(evRefresh);
|
|
}
|
|
else if (HasWebBrowser())
|
|
{
|
|
ScWebCommand(eWeb_Refresh);
|
|
}
|
|
::SetFocus(hwnd);
|
|
}
|
|
|
|
void CAMCView::OnVerbAccelKey(UINT nID)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::OnVerbAccelKey"));
|
|
|
|
switch (nID)
|
|
{
|
|
case ID_MMC_CUT:
|
|
if (IsVerbEnabled(MMC_VERB_CUT))
|
|
sc = ScConsoleVerb(evCut);
|
|
break;
|
|
|
|
case ID_MMC_COPY:
|
|
if (IsVerbEnabled(MMC_VERB_COPY))
|
|
sc = ScConsoleVerb(evCopy);
|
|
break;
|
|
|
|
case ID_MMC_PASTE:
|
|
if (IsVerbEnabled(MMC_VERB_PASTE))
|
|
{
|
|
// Check if the dataobject in clipboard can be
|
|
// pasted into the selected node.
|
|
// Then only we send MMCN_PASTE notification to snapin.
|
|
|
|
HNODE hNode = NULL;
|
|
LPARAM lvData = NULL;
|
|
bool bScope = FALSE;
|
|
sc = ScGetFocusedItem(hNode, lvData, bScope);
|
|
if (sc)
|
|
break;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, hNode, E_UNEXPECTED);
|
|
if (sc)
|
|
break;
|
|
|
|
bool bPasteAllowed = false;
|
|
sc = pNC->QueryPasteFromClipboard(hNode, bScope, lvData, bPasteAllowed);
|
|
|
|
if (sc)
|
|
break;
|
|
|
|
if (bPasteAllowed)
|
|
sc = ScConsoleVerb(evPaste);
|
|
}
|
|
break;
|
|
|
|
case ID_MMC_PRINT:
|
|
if (IsVerbEnabled(MMC_VERB_PRINT))
|
|
sc = ScConsoleVerb(evPrint);
|
|
break;
|
|
|
|
case ID_MMC_RENAME:
|
|
if (IsVerbEnabled(MMC_VERB_RENAME))
|
|
sc = ScConsoleVerb(evRename);
|
|
break;
|
|
|
|
case ID_MMC_REFRESH:
|
|
OnRefresh();
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (sc)
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Handle accelerator keys shared by result and scope panes
|
|
//
|
|
BOOL CAMCView::OnSharedKeyDown(WORD wVKey)
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
|
|
if (::GetKeyState(VK_CONTROL) < 0)
|
|
{
|
|
switch (wVKey)
|
|
{
|
|
case 'C':
|
|
case 'c':
|
|
case VK_INSERT:
|
|
OnVerbAccelKey(ID_MMC_COPY); // Ctrl-C, Ctrl-Insert
|
|
break;
|
|
|
|
case 'V':
|
|
case 'v':
|
|
OnVerbAccelKey(ID_MMC_PASTE); // Ctrl-V
|
|
break;
|
|
|
|
case 'X':
|
|
case 'x':
|
|
OnVerbAccelKey(ID_MMC_CUT); // Ctrl-X
|
|
break;
|
|
|
|
default:
|
|
bReturn = FALSE;
|
|
}
|
|
}
|
|
else if (::GetKeyState(VK_SHIFT) < 0)
|
|
{
|
|
switch (wVKey)
|
|
{
|
|
case VK_DELETE:
|
|
OnVerbAccelKey(ID_MMC_CUT); // Shift-Delete
|
|
break;
|
|
|
|
case VK_INSERT:
|
|
OnVerbAccelKey(ID_MMC_PASTE); // Shift -Insert
|
|
break;
|
|
|
|
default:
|
|
bReturn = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
switch (wVKey)
|
|
{
|
|
case VK_F2:
|
|
OnVerbAccelKey(ID_MMC_RENAME); // F2
|
|
break;
|
|
|
|
default:
|
|
bReturn = FALSE;
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScConsoleVerb
|
|
//
|
|
// Synopsis: Execute the Console verb.
|
|
//
|
|
// Arguments: [nVerb] - The verb to be executed.
|
|
//
|
|
// Note: The verb is executed in the context of
|
|
// currently focused item (scope or result).
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScConsoleVerb (int nVerb)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
ASSERT_VALID (this);
|
|
|
|
DECLARE_SC (sc, _T("CAMCView::ScConsoleVerb"));
|
|
|
|
HNODE hNode = NULL;
|
|
LPARAM lvData = 0;
|
|
bool bScope = false;
|
|
|
|
// Get the focused item to process the console verb.
|
|
sc = ScGetFocusedItem(hNode, lvData, bScope);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScProcessConsoleVerb(hNode, bScope, lvData, nVerb);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScProcessConsoleVerb
|
|
//
|
|
// Synopsis: Execute the Console verb with given context.
|
|
//
|
|
// Arguments: [hNode] - The tree node context.
|
|
// [bScope] - Scope or Result pane.
|
|
// [lvData] - LPARAM of result item (if result pane has focus).
|
|
// [nVerb] - The verb to be executed.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScProcessConsoleVerb(HNODE hNode, bool bScope, LPARAM lvData, int nVerb)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScProcessConsoleVerb"));
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
ASSERT_VALID (this);
|
|
|
|
// To maintain compatibility with MMC1.2 (This is init to LVERROR which
|
|
// nodemgr process differently).
|
|
if (bScope)
|
|
lvData = 0;
|
|
|
|
if (lvData == LVDATA_BACKGROUND)
|
|
{
|
|
switch (nVerb)
|
|
{
|
|
case evCut:
|
|
case evCopy:
|
|
case evDelete:
|
|
case evRename:
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
NCLBK_NOTIFY_TYPE nclbk = NCLBK_NONE;
|
|
|
|
switch (nVerb)
|
|
{
|
|
case evCut: nclbk = NCLBK_CUT; break;
|
|
case evCopy: nclbk = NCLBK_COPY; break;
|
|
case evDelete: nclbk = NCLBK_DELETE; break;
|
|
case evProperties: nclbk = NCLBK_PROPERTIES; break;
|
|
case evPrint: nclbk = NCLBK_PRINT; break;
|
|
|
|
case evPaste:
|
|
{
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = pNC->Paste(hNode, bScope, lvData);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScPaste ();
|
|
if (sc)
|
|
return sc;
|
|
|
|
break;
|
|
}
|
|
|
|
case evRefresh:
|
|
// if web page on view, send it a refresh first
|
|
if (HasWebBrowser())
|
|
sc = ScWebCommand(eWeb_Refresh);
|
|
if (sc)
|
|
return sc;
|
|
|
|
nclbk = NCLBK_REFRESH;
|
|
break;
|
|
|
|
case evRename:
|
|
// Enable edit for the item.
|
|
if (bScope == TRUE)
|
|
{
|
|
if (sc = ScCheckPointers(m_pTreeCtrl, E_UNEXPECTED))
|
|
return sc;
|
|
|
|
HTREEITEM hti = m_pTreeCtrl->GetSelectedItem();
|
|
if (sc = ScCheckPointers(hti, E_UNEXPECTED))
|
|
return sc;
|
|
|
|
m_pTreeCtrl->EditLabel(hti);
|
|
}
|
|
else
|
|
{
|
|
if ( sc = ScCheckPointers(m_pListCtrl, E_UNEXPECTED))
|
|
return sc;
|
|
|
|
CAMCListView* pListView = m_pListCtrl->GetListViewPtr();
|
|
if (NULL == pListView)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
|
|
int iItem = _GetLVSelectedItemData(&lvData);
|
|
ASSERT(iItem >= 0);
|
|
CListCtrl& listCtrl = pListView->GetListCtrl();
|
|
listCtrl.EditLabel(iItem);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
|
|
if (nclbk != NCLBK_NONE)
|
|
{
|
|
// Ask the nodemgr to process the verb.
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
if (pNC == NULL)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
|
|
sc = pNC->Notify(hNode, nclbk, bScope, lvData);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
if (nclbk == NCLBK_CUT)
|
|
sc = ScCut (bScope ? m_pTreeCtrl->GetSelectedItem() : 0);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScListViewSelectionActivate
|
|
//
|
|
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
|
|
// of view of selected items and MMCN_SELECT. This is not
|
|
// the same as the MFC concept of "active view". There are a couple
|
|
// of views that cannot be active in this sense, such as the taskpad
|
|
// and tab views.
|
|
// When the active view (according to this definition) changes, this
|
|
// function is called. Thus, ScTreeViewSelectionActivate and
|
|
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
|
|
// are always called in pairs when the activation changes, one to handle
|
|
// deactivation, and one to handle activation.
|
|
//
|
|
// Consider the following scenario
|
|
// 1) The tree view has (MFC/windows style) focus.
|
|
// 2) The user clicks on the taskpad view
|
|
// Result - selection activation does not change from the tree. All verbs
|
|
// still correspond to the selected tree item.
|
|
// 3) The user clicks on the folder view
|
|
// Result - once again, selection activation does not chang
|
|
// 4) The user clicks on one of the result views eg the list
|
|
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
|
|
// Thus verbs and the toolbar now correspond to the selected list item(s).
|
|
// 5) The user clicks on the taskpad view.
|
|
// Result - as in step 2, nothing happens
|
|
// 6) The user clicks on the result view
|
|
// Result - because the active view has not changed, nothing happens.
|
|
//
|
|
// Arguments: [bActivate] - [in]
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScListViewSelectionActivate(bool bActivate)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScListViewSelectionActivate"));
|
|
|
|
if (m_pListCtrl == NULL)
|
|
return sc;
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
sc = ScCheckPointers(pNC, E_UNEXPECTED);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
return sc;
|
|
}
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = FALSE;
|
|
selInfo.m_bDueToFocusChange = TRUE;
|
|
|
|
#ifdef DBG
|
|
if (bActivate == TRUE)
|
|
{
|
|
ASSERT(m_bProcessMultiSelectionChanges == false);
|
|
}
|
|
#endif // DBG
|
|
|
|
/*
|
|
* The below block can never execute. When m_bProcessMultiSelectionChanges is
|
|
* set to true messages are posted to handle multiselection changes. So the
|
|
* handler OnProcessMultiSelectionChanges should have processed the message and the
|
|
* m_bProcessMultiSelectionChanges should have been reset by now. If there is
|
|
* some unknown way to make de-activate the listview before processing the message
|
|
* then below block will be executed that will send de-select notification.
|
|
*
|
|
* The below block sends a de-select multi-select items.
|
|
*/
|
|
if (m_bProcessMultiSelectionChanges)
|
|
{
|
|
ASSERT(false); // Would like to know when this block is hit.
|
|
|
|
ASSERT(bActivate == false);
|
|
|
|
m_bProcessMultiSelectionChanges = false;
|
|
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
// Focus change so appropriately enable std-toolbar buttons
|
|
// back, forward, export-list, up-one-level, show/hide-scope, help
|
|
sc = ScUpdateStandardbarMMCButtons();
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
bool bSelect = bActivate;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Multi select
|
|
//
|
|
|
|
int cSelected = m_pListCtrl->GetSelectedCount();
|
|
|
|
if (cSelected > 1)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, bSelect, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
m_bLastSelWasMultiSel = bSelect;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Zero or Single select
|
|
//
|
|
|
|
if (cSelected == 0)
|
|
{
|
|
selInfo.m_bBackground = TRUE;
|
|
selInfo.m_lCookie = LVDATA_BACKGROUND;
|
|
}
|
|
else
|
|
{
|
|
#include "pushwarn.h"
|
|
#pragma warning(disable: 4552) // ">=" operator has no effect
|
|
VERIFY(_GetLVSelectedItemData(&selInfo.m_lCookie) >= 0);
|
|
#include "popwarn.h"
|
|
}
|
|
|
|
ASSERT(cSelected >= 0);
|
|
ASSERT(cSelected <= 1);
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, bSelect, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
} while (0);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
void CAMCView::OnShowWindow(BOOL bShow, UINT nStatus)
|
|
{
|
|
CView::OnShowWindow(bShow, nStatus);
|
|
}
|
|
|
|
int CAMCView::_GetLVItemData(LPARAM *plParam, UINT flags)
|
|
{
|
|
HWND hwnd = m_pListCtrl->GetListViewHWND();
|
|
int iItem = ::SendMessage(hwnd, LVM_GETNEXTITEM, (WPARAM) (int) -1,
|
|
MAKELPARAM(flags, 0));
|
|
if (iItem >= 0)
|
|
{
|
|
if (IsVirtualList())
|
|
{
|
|
*plParam = iItem;
|
|
}
|
|
else
|
|
{
|
|
LV_ITEM lvi;
|
|
ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.iItem = iItem;
|
|
lvi.mask = LVIF_PARAM;
|
|
|
|
#include "pushwarn.h"
|
|
#pragma warning(disable: 4553) // "==" operator has no effect
|
|
VERIFY(::SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&lvi) == TRUE);
|
|
#include "popwarn.h"
|
|
|
|
*plParam = lvi.lParam;
|
|
}
|
|
}
|
|
|
|
return iItem;
|
|
}
|
|
|
|
int CAMCView::_GetLVFocusedItemData(LPARAM *plParam)
|
|
{
|
|
return (_GetLVItemData (plParam, LVNI_FOCUSED));
|
|
}
|
|
|
|
int CAMCView::_GetLVSelectedItemData(LPARAM *plParam)
|
|
{
|
|
return (_GetLVItemData (plParam, LVNI_SELECTED));
|
|
}
|
|
|
|
|
|
void CAMCView::SetListViewMultiSelect(BOOL bMultiSelect)
|
|
{
|
|
long lStyle = m_pListCtrl->GetListStyle();
|
|
if (bMultiSelect == FALSE)
|
|
lStyle |= LVS_SINGLESEL;
|
|
else
|
|
lStyle &= ~LVS_SINGLESEL;
|
|
|
|
m_pListCtrl->SetListStyle(lStyle);
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnItemDeselected
|
|
*
|
|
* PURPOSE: Tree observer method. Called when a tree item is deselected.
|
|
*
|
|
* PARAMETERS:
|
|
* HNODE hNode : The node that was deselected.
|
|
*
|
|
* NOTE: This function can be merged with the next.
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnItemDeselected(HNODE hNode)
|
|
{
|
|
DECLARE_SC (sc, TEXT("CAMCView::ScOnItemDeselected"));
|
|
|
|
DeSelectResultPane(hNode);
|
|
|
|
if (!hNode)
|
|
return sc;
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
|
|
// Ask the SnapIn to cleanup any items it has inserted.
|
|
INodeCallback* spNodeCallBack = GetNodeCallback();
|
|
ASSERT(spNodeCallBack != NULL);
|
|
|
|
selInfo.m_bScope = TRUE;
|
|
selInfo.m_pView = NULL;
|
|
|
|
Dbg(DEB_USER6, _T("T1. CAMCTreeView::OnDeSelectNode<1, 0>\n"));
|
|
sc = ScNotifySelect (spNodeCallBack, hNode, false /*fMultiSelect*/, false, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::DeSelectResultPane
|
|
*
|
|
* PURPOSE: Deselects the result pane and sets the view type to invalid.
|
|
*
|
|
* PARAMETERS:
|
|
* HNODE hNodeSel :
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
void
|
|
CAMCView::DeSelectResultPane(HNODE hNodeSel)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::DeSelectResultPane"));
|
|
|
|
if (m_spTaskPadHost.GetInterfacePtr() != NULL)
|
|
{
|
|
CTaskPadHost *pTaskPadHost = dynamic_cast<CTaskPadHost *>(m_spTaskPadHost.GetInterfacePtr());
|
|
m_spTaskPadHost = NULL;
|
|
}
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
if (hNodeSel == 0)
|
|
return;
|
|
|
|
// If there was no list view being displayed return.
|
|
if (HasListOrListPad())
|
|
{
|
|
// if we were in ListPad-mode, undo that.
|
|
if (m_pListCtrl->IsListPad())
|
|
{
|
|
sc = m_pListCtrl->ScAttachToListPad (NULL, NULL);
|
|
if(sc)
|
|
sc.TraceAndClear(); //ignore
|
|
}
|
|
|
|
// If we are in edit mode cancel it.
|
|
m_pListCtrl->GetListCtrl().EditLabel(-1);
|
|
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = FALSE;
|
|
|
|
/*
|
|
* The below block can never execute. When m_bProcessMultiSelectionChanges is
|
|
* set to true messages are posted to handle multiselection changes. So the
|
|
* handler OnProcessMultiSelectionChanges should have processed the message and the
|
|
* m_bProcessMultiSelectionChanges should have been reset by now. If there is
|
|
* some unknown way to make select different node (to deselect result pane)
|
|
* before processing the message then below block will be executed that will
|
|
* send de-select notification.
|
|
*
|
|
* The below block sends a de-select multi-select items.
|
|
*/
|
|
if (m_bProcessMultiSelectionChanges)
|
|
{
|
|
ASSERT(false); // Would like to know when this block is hit.
|
|
|
|
m_bProcessMultiSelectionChanges = false;
|
|
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
else
|
|
{
|
|
UINT cSel = m_pListCtrl->GetSelectedCount();
|
|
if (cSel == 1)
|
|
{
|
|
if (cSel)
|
|
{
|
|
int iItem = _GetLVSelectedItemData(&selInfo.m_lCookie);
|
|
ASSERT(iItem != -1);
|
|
sc = ScNotifySelect (pNC, hNodeSel, false /*fMultiSelect*/, false, &selInfo);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
}
|
|
}
|
|
else if (cSel > 1)
|
|
{
|
|
sc = ScNotifySelect (pNC, hNodeSel, true /*fMultiSelect*/, false, 0);
|
|
if (sc)
|
|
sc.TraceAndClear(); // ignore & continue;
|
|
|
|
m_bLastSelWasMultiSel = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If it is OCX or Web send de-select notifications.
|
|
sc = ScSpecialResultpaneSelectionActivate(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT CAMCView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
// NATHAN
|
|
case WM_NOTIFYFORMAT:
|
|
{
|
|
int id = ::GetDlgCtrlID ((HWND)wParam);
|
|
//if (m_pTreeCtrl == NULL || ((HWND)wParam != m_pTreeCtrl->m_hWnd))
|
|
if (id == IDC_ListView)
|
|
return NFR_UNICODE;
|
|
}
|
|
break;
|
|
#ifdef DBG
|
|
case WM_KEYUP:
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case VK_SHIFT:
|
|
case VK_CONTROL:
|
|
// We removed some code that will work if m_bProcessMultiSelectionChanges
|
|
// is true. I dont see any way the bool being true. Still let us have below
|
|
// assert. If this gets fired then we should call OnProcessMultiSelectionChanges.
|
|
ASSERT(m_bProcessMultiSelectionChanges == false);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
return CView::WindowProc(message, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ChangePane
|
|
*
|
|
* Moves the activation from pane to pane. The (forward) tab order is
|
|
*
|
|
* Scope pane (either tree or favorites)
|
|
* Result pane
|
|
* Task view (if visible)
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
|
|
class CTabOrderEntry
|
|
{
|
|
public:
|
|
CView* const m_pView;
|
|
const bool m_bValid; // is this entry valid
|
|
|
|
CTabOrderEntry(CView *pView)
|
|
: m_pView (pView),
|
|
m_bValid ((pView != NULL) && IsWindowVisible (pView->m_hWnd))
|
|
{}
|
|
};
|
|
|
|
|
|
void CAMCView::ChangePane(AMCNavDir eDir)
|
|
{
|
|
ASSERT_VALID (this);
|
|
|
|
CFrameWnd* pFrame = GetParentFrame();
|
|
CView* pActiveView = pFrame->GetActiveView();
|
|
HWND hWndActive = ::GetFocus();
|
|
|
|
|
|
CTabOrderEntry rgOrderEntry[] =
|
|
{
|
|
CTabOrderEntry(GetPaneView(ePane_ScopeTree)), // tree has focus
|
|
CTabOrderEntry(GetPaneView(ePane_Results)), // results has focus - note the value of INDEX_RESULTS_PANE below.
|
|
CTabOrderEntry(m_pViewExtensionCtrl), // view extension web page has focus
|
|
CTabOrderEntry(m_pResultFolderTabView), // result tab control has focus
|
|
};
|
|
|
|
/*
|
|
* this is the index of the result pane entry in rgOrderEntry,
|
|
* used for default focus placement if something unexpected happens
|
|
*/
|
|
const int INDEX_RESULTS_PANE = 1;
|
|
ASSERT (rgOrderEntry[INDEX_RESULTS_PANE].m_pView == GetPaneView(ePane_Results));
|
|
|
|
// Get the navigator if one exists. If so, use it and bail.
|
|
CAMCNavigator* pNav = dynamic_cast<CAMCNavigator*>(pActiveView);
|
|
if (pNav && pNav->ChangePane(eDir))
|
|
return;
|
|
|
|
int cEntries = (sizeof(rgOrderEntry) / sizeof(rgOrderEntry[0]));
|
|
|
|
// get the currently active entry.
|
|
for(int i = 0; i< cEntries; i++)
|
|
{
|
|
if( (rgOrderEntry[i].m_pView == pActiveView) )
|
|
break;
|
|
}
|
|
|
|
ASSERT(i < cEntries);
|
|
if(i>= cEntries)
|
|
{
|
|
// if we don't know where we are, a bit of defensive coding puts the focus back
|
|
// on the results pane, ie into a known state.
|
|
i = INDEX_RESULTS_PANE;
|
|
}
|
|
|
|
int iPrev = i;
|
|
|
|
// at this point we've found the right entry.
|
|
int increment = (eDir==AMCNAV_PREV) ? -1 : 1;
|
|
int sanityCount = 0;
|
|
while(true)
|
|
{
|
|
i = (i+increment+cEntries) % cEntries;
|
|
if(rgOrderEntry[i].m_bValid)
|
|
break;
|
|
|
|
sanityCount++;
|
|
if(sanityCount == cEntries)
|
|
{
|
|
ASSERT(0 && "Something's seriously messed up!!");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// update the active view
|
|
if (i != iPrev)
|
|
pFrame->SetActiveView(rgOrderEntry[i].m_pView);
|
|
else
|
|
{
|
|
// if view retains focus and has a navigator,
|
|
// tell navigator to take the focus
|
|
if (pNav)
|
|
pNav->TakeFocus(eDir);
|
|
}
|
|
|
|
// if there is a special focus handler, call it.
|
|
CFocusHandler *pFocusHandler = dynamic_cast<CFocusHandler *>(rgOrderEntry[i].m_pView);
|
|
if(pFocusHandler != NULL)
|
|
{
|
|
pFocusHandler->OnKeyboardFocus (LVIS_FOCUSED | LVIS_SELECTED,
|
|
LVIS_FOCUSED | LVIS_SELECTED);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void CAMCView::OnNextPane()
|
|
{
|
|
ChangePane(AMCNAV_NEXT);
|
|
}
|
|
|
|
void CAMCView::OnPrevPane()
|
|
{
|
|
ChangePane(AMCNAV_PREV);
|
|
}
|
|
|
|
void CAMCView::OnUpdateNextPane(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->Enable(TRUE);
|
|
}
|
|
|
|
void CAMCView::OnUpdatePrevPane(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->Enable(TRUE);
|
|
}
|
|
|
|
|
|
void RestrictPointToWindow (CWnd* pwnd, CPoint* ppt)
|
|
{
|
|
CRect rectWnd;
|
|
|
|
pwnd->GetClientRect (rectWnd);
|
|
|
|
if (ppt->x < rectWnd.left)
|
|
ppt->x = rectWnd.left;
|
|
else if (ppt->x > rectWnd.right)
|
|
ppt->x = rectWnd.right;
|
|
|
|
if (ppt->y < rectWnd.top)
|
|
ppt->y = rectWnd.top;
|
|
else if (ppt->y > rectWnd.bottom)
|
|
ppt->y = rectWnd.bottom;
|
|
}
|
|
|
|
|
|
void CAMCView::OnShiftF10()
|
|
{
|
|
CRect rect;
|
|
CWnd* pwndFocus = GetFocus();
|
|
CListCtrl& lc = m_pListCtrl->GetListCtrl();
|
|
|
|
ASSERT_VALID (this);
|
|
|
|
if (pwndFocus == &lc)
|
|
{
|
|
int iItem = lc.GetNextItem (-1, LVNI_SELECTED);
|
|
CPoint pt = 0;
|
|
|
|
if (iItem != -1)
|
|
{
|
|
VERIFY (lc.GetItemRect (iItem, rect, LVIR_ICON));
|
|
pt = rect.CenterPoint ();
|
|
}
|
|
else
|
|
{
|
|
CHeaderCtrl* pHeader = m_pListCtrl->GetHeaderCtrl();
|
|
|
|
if (pHeader != NULL && pHeader->IsWindowVisible())
|
|
{
|
|
pHeader->GetClientRect(&rect);
|
|
pt.y = rect.Height();
|
|
ASSERT (pt.y >= 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* make sure the context menu doesn't show up outside the window
|
|
*/
|
|
RestrictPointToWindow (&lc, &pt);
|
|
|
|
m_pListCtrl->GetListViewPtr()->ClientToScreen(&pt);
|
|
OnListContextMenu(pt);
|
|
}
|
|
|
|
else if (pwndFocus == m_pTreeCtrl)
|
|
{
|
|
HTREEITEM hTreeItem = m_pTreeCtrl->GetSelectedItem();
|
|
if (hTreeItem == NULL)
|
|
return;
|
|
|
|
m_pTreeCtrl->GetItemRect (hTreeItem, rect, TRUE);
|
|
|
|
CPoint ptClient (rect.left, rect.bottom-1);
|
|
|
|
/*
|
|
* make sure the context menu doesn't show up outside the window
|
|
*/
|
|
RestrictPointToWindow (m_pTreeCtrl, &ptClient);
|
|
|
|
CPoint ptScreen = ptClient;
|
|
|
|
m_pTreeCtrl->ClientToScreen(&ptScreen);
|
|
OnTreeContextMenu(ptScreen, ptClient, hTreeItem);
|
|
}
|
|
}
|
|
|
|
void CAMCView::OnUpdateShiftF10(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->Enable(TRUE);
|
|
}
|
|
|
|
|
|
BOOL CAMCView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if (nHitTest == HTCLIENT && pWnd == this && !IsTracking())
|
|
{
|
|
CPoint pt (GetMessagePos());
|
|
ScreenToClient (&pt);
|
|
|
|
if (m_rectVSplitter.PtInRect (pt))
|
|
{
|
|
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
return CWnd::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
|
|
|
|
|
|
SC CAMCView::ScCut (HTREEITEM htiCut)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScCut"));
|
|
|
|
CMainFrame* pMain = AMCGetMainWnd();
|
|
sc = ScCheckPointers (pMain, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
pMain->SetWindowToNotifyCBChange(m_hWnd);
|
|
|
|
if (htiCut)
|
|
m_pTreeCtrl->SetItemState (htiCut, TVIS_CUT, TVIS_CUT);
|
|
else
|
|
m_pListCtrl->CutSelectedItems (TRUE);
|
|
|
|
m_htiCut = htiCut;
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
SC CAMCView::ScPaste ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCView::ScPaste"));
|
|
|
|
if (!m_htiCut)
|
|
m_pListCtrl->CutSelectedItems(FALSE);
|
|
|
|
CMainFrame* pMain = AMCGetMainWnd();
|
|
sc = ScCheckPointers (pMain, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
pMain->SetWindowToNotifyCBChange(NULL);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT CAMCView::SendGenericNotify(NCLBK_NOTIFY_TYPE nclbk)
|
|
{
|
|
BOOL bScope = TRUE;
|
|
MMC_COOKIE lCookie = 0;
|
|
int iItem = -1;
|
|
|
|
ASSERT_VALID (this);
|
|
|
|
if (m_pListCtrl && m_pListCtrl->GetListViewHWND() == ::GetFocus())
|
|
{
|
|
iItem = _GetLVSelectedItemData(&lCookie);
|
|
if (iItem != -1)
|
|
bScope = FALSE;
|
|
}
|
|
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
if (pNC == NULL)
|
|
return E_FAIL;
|
|
|
|
HNODE hNodeSel = GetSelectedNode();
|
|
ASSERT(hNodeSel != NULL);
|
|
if (hNodeSel == NULL)
|
|
return E_FAIL;
|
|
|
|
// selection notifications should use ScNotifySelect()
|
|
ASSERT ((nclbk != NCLBK_SELECT) && (nclbk != NCLBK_MULTI_SELECT));
|
|
|
|
return pNC->Notify(hNodeSel, nclbk, bScope, lCookie);
|
|
}
|
|
|
|
void CAMCView::SaveStartingSelectedNode()
|
|
{
|
|
m_htiStartingSelectedNode = m_pTreeCtrl->GetSelectedItem();
|
|
}
|
|
|
|
bool CAMCView::HasNodeSelChanged()
|
|
{
|
|
return (m_pTreeCtrl->GetSelectedItem() != m_htiStartingSelectedNode);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: OnSysKeyDown
|
|
//
|
|
// Synopsis: Handles WM_SYSKEYDOWN message.
|
|
// CAMCTreeView::OnSysKeyDown handles the Tree view so
|
|
// here we handle only the list view (or Result pane)
|
|
//
|
|
// Returns: none
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
void CAMCView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
switch (nChar)
|
|
{
|
|
case VK_LEFT:
|
|
ScWebCommand(eWeb_Back);
|
|
break;
|
|
|
|
case VK_RIGHT:
|
|
ScWebCommand(eWeb_Forward);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnAppCommand
|
|
*
|
|
* WM_APPCOMMAND handler for CAMCView. This is used to handle to forward
|
|
* and backward buttons on the IntelliMouse Explorer and the Microsoft
|
|
* Natural Keyboards
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
LRESULT CAMCView::OnAppCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::OnAppCommand"));
|
|
|
|
switch (GET_APPCOMMAND_LPARAM (lParam))
|
|
{
|
|
case APPCOMMAND_BROWSER_BACKWARD:
|
|
sc = ScWebCommand (eWeb_Back);
|
|
if (sc)
|
|
break;
|
|
|
|
return (TRUE); // handled here
|
|
|
|
case APPCOMMAND_BROWSER_FORWARD:
|
|
sc = ScWebCommand (eWeb_Forward);
|
|
if (sc)
|
|
break;
|
|
|
|
return (TRUE); // handled here
|
|
|
|
case APPCOMMAND_BROWSER_REFRESH:
|
|
OnRefresh ();
|
|
return (TRUE); // handled here
|
|
}
|
|
|
|
return (Default());
|
|
}
|
|
|
|
|
|
void CAMCView::OnPaletteChanged(CWnd* pwndFocus)
|
|
{
|
|
// if displaying a web page, forward the palette change to the shell
|
|
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
|
|
{
|
|
if (m_pWebViewCtrl->m_hWnd != NULL)
|
|
{
|
|
HWND hwndShell = ::GetWindow(m_pWebViewCtrl->m_hWnd, GW_CHILD);
|
|
|
|
if (hwndShell != NULL)
|
|
::SendMessage(hwndShell, WM_PALETTECHANGED, (WPARAM)pwndFocus->m_hWnd, (LPARAM)0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CAMCView::OnQueryNewPalette()
|
|
{
|
|
// if displaying a web page, forward the palette query to the shell
|
|
if (HasWebBrowser() && m_pWebViewCtrl != NULL)
|
|
{
|
|
if (m_pWebViewCtrl->m_hWnd != NULL)
|
|
{
|
|
HWND hwndShell = ::GetWindow(m_pWebViewCtrl->m_hWnd, GW_CHILD);
|
|
|
|
if (hwndShell != NULL)
|
|
return ::SendMessage(hwndShell, WM_QUERYNEWPALETTE, (WPARAM)0, (LPARAM)0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL CAMCView::OwnsResultList(HTREEITEM hti)
|
|
{
|
|
if (hti == NULL)
|
|
return (false);
|
|
|
|
// if result list is active
|
|
if (HasListOrListPad())
|
|
{
|
|
// Get selected node and query node
|
|
HNODE hnodeSelected = GetSelectedNode();
|
|
HNODE hnode = m_pTreeCtrl ? m_pTreeCtrl->GetItemNode(hti) : NULL;
|
|
|
|
if (hnodeSelected && hnode)
|
|
{
|
|
INodeCallback* pNC = GetNodeCallback();
|
|
ASSERT(pNC != NULL);
|
|
|
|
// See if the selected node uses the query node as a target
|
|
// S_OK - yes
|
|
// S_FALSE - uses a different target node
|
|
// E_FAIL - doesn't use a target node
|
|
HRESULT hr = pNC->IsTargetNodeOf(hnodeSelected, hnode);
|
|
if (hr == S_OK)
|
|
return TRUE;
|
|
else if (hr == S_FALSE)
|
|
return FALSE;
|
|
else
|
|
return (hnodeSelected == hnode);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnSysColorChange
|
|
*
|
|
* WM_SYSCOLORCHANGE handler for CAMCView.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::OnSysColorChange()
|
|
{
|
|
CView::OnSysColorChange();
|
|
|
|
/*
|
|
* the list control isn't a window but rather a wrapper on a window,
|
|
* so we need to manually forward on the WM_SYSCOLORCHANGE
|
|
*/
|
|
m_pListCtrl->OnSysColorChange();
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* TrackerCallback function
|
|
*
|
|
* Called by CViewTracker when tracking of splitter bar is completed. This
|
|
* function applies the changes if the AcceptChange flag is set.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CALLBACK TrackerCallback(
|
|
TRACKER_INFO* pInfo,
|
|
bool bAcceptChange,
|
|
bool bSyncLayout)
|
|
{
|
|
DECLARE_SC (sc, _T("TrackerCallback"));
|
|
|
|
if (bAcceptChange)
|
|
{
|
|
CAMCView* pView = dynamic_cast<CAMCView*>(pInfo->pView);
|
|
sc = ScCheckPointers (pView, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
// Set new width and recompute layout
|
|
pView->m_PaneInfo[CConsoleView::ePane_ScopeTree].cx = pInfo->rectTracker.left;
|
|
pView->SetDirty();
|
|
|
|
if (bSyncLayout)
|
|
{
|
|
Trace (tagSplitterTracking, _T("Synchronous layout"));
|
|
pView->RecalcLayout();
|
|
pView->UpdateWindow();
|
|
}
|
|
else
|
|
{
|
|
Trace (tagSplitterTracking, _T("Deferred layout"));
|
|
pView->DeferRecalcLayout();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* PtInWindow
|
|
*
|
|
* Test if point is in a window (pt is in screen coordinates)
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
BOOL PtInWindow(CWnd* pWnd, CPoint pt)
|
|
{
|
|
if (!pWnd->IsWindowVisible())
|
|
return FALSE;
|
|
|
|
CRect rect;
|
|
pWnd->GetWindowRect(&rect);
|
|
|
|
return rect.PtInRect(pt);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::ScJiggleListViewFocus
|
|
*
|
|
* Bug 345402: Make sure the focus rect is on the list control (if it
|
|
* actually has the focus) to wake up any accessibility tools that might
|
|
* be watching for input and focus changes.
|
|
*
|
|
* We post a message here rather than doing it synchronously so we can
|
|
* allow any other processing in the list (like sorting) to happen
|
|
* before we put the focus on the 1st item. If we didn't wait until after
|
|
* the sort, the item we put the focus on might not be the first item
|
|
* in the list.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
SC CAMCView::ScJiggleListViewFocus ()
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
PostMessage (m_nJiggleListViewFocusMsg);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
LRESULT CAMCView::OnJiggleListViewFocus (WPARAM, LPARAM)
|
|
{
|
|
CAMCListView* pListView = m_pListCtrl->GetListViewPtr();
|
|
|
|
/*
|
|
* If the focus is on the list control, make sure that at least one item
|
|
* has the focus rect. Doing this will wake up any accessibility tools
|
|
* that might be watching (Bug 345402).
|
|
*/
|
|
if ((GetFocusedPane() == ePane_Results) &&
|
|
(GetResultView() == pListView))
|
|
{
|
|
pListView->OnKeyboardFocus (LVIS_FOCUSED, LVIS_FOCUSED);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::OnDeferRecalcLayout
|
|
*
|
|
* CAMCView::m_nDeferRecalcLayoutMsg registered message handler for CAMCView.
|
|
*
|
|
* Parameters:
|
|
* bDoArrange - if non-zero need to call Arrange on list-view so that
|
|
* common-control can layout items properly.
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
LRESULT CAMCView::OnDeferRecalcLayout (WPARAM bDoArrange, LPARAM)
|
|
{
|
|
Trace (tagLayout, _T("CAMCView::OnDeferRecalcLayout"));
|
|
RecalcLayout();
|
|
|
|
if (bDoArrange && m_pListCtrl)
|
|
{
|
|
int nViewMode = m_pListCtrl->GetViewMode();
|
|
|
|
// Arrange is only for large & small icon modes.
|
|
if ( (nViewMode == MMCLV_VIEWSTYLE_ICON) ||
|
|
(nViewMode == MMCLV_VIEWSTYLE_SMALLICON) )
|
|
m_pListCtrl->Arrange(LVA_DEFAULT);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
//############################################################################
|
|
//############################################################################
|
|
//
|
|
// Implementation of class CViewTemplate
|
|
//
|
|
//############################################################################
|
|
//############################################################################
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CViewTemplateList::Persist
|
|
*
|
|
* PURPOSE: Used when loading XML. Persist enough information to create a view
|
|
* The rest of view peristence is dome by CAMCView
|
|
*
|
|
* PARAMETERS:
|
|
* CPersistor& persistor - persistor to load from
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
void CViewTemplateList::Persist(CPersistor& persistor)
|
|
{
|
|
// the view should be stored instead
|
|
ASSERT (persistor.IsLoading());
|
|
// delegate to the base class
|
|
XMLListCollectionBase::Persist(persistor);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CViewTemplateList::OnNewElement
|
|
*
|
|
* PURPOSE: Called by XMLListCollectionBase to request persisting of new element
|
|
* Each new element is created and persisted in this function.
|
|
*
|
|
* PARAMETERS:
|
|
* CPersistor& persistor - persisto from which the element should be loaded
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
void CViewTemplateList::OnNewElement(CPersistor& persistor)
|
|
{
|
|
CBookmark bm;
|
|
int iViewId = -1;
|
|
// load information byte for new view
|
|
CPersistor persistorView(persistor, CAMCView::_GetXMLType());
|
|
persistorView.Persist(bm, XML_NAME_ROOT_NODE);
|
|
persistorView.PersistAttribute(XML_ATTR_VIEW_ID, iViewId);
|
|
|
|
// store information to the list
|
|
m_ViewsList.push_back(ViewTempl_Type(iViewId, ViewTemplB_Type(bm, persistorView)));
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScUpdateStandardbarMMCButtons
|
|
//
|
|
// Synopsis: Appropriately enable/disable std-toolbar buttons
|
|
// that are owned by MMC (not verb buttons that snapins own) like
|
|
// back, forward, export-list, up-one-level, show/hide-scope, help.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScUpdateStandardbarMMCButtons()
|
|
{
|
|
DECLARE_SC (sc, _T("CAMCView::ScUpdateStandardbarMMCButtons"));
|
|
|
|
// Get the standard toolbar and change the states.
|
|
CStandardToolbar* pStdToolbar = GetStdToolbar();
|
|
if (NULL == pStdToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
CAMCDoc *pDoc = GetDocument();
|
|
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// If view is not customizable then hide the "Show/Hide scope tree" button.
|
|
sc = pStdToolbar->ScEnableScopePaneBtn(IsScopePaneAllowed() && pDoc->AllowViewCustomization());
|
|
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
sc = pStdToolbar->ScEnableContextHelpBtn(true);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
|
|
sc = pStdToolbar->ScEnableExportList(GetListSize() > 0 /*Enable only if LV has items*/);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
|
|
// Enable/Disable Up-One Level button.
|
|
BOOL bEnableUpOneLevel = !m_pTreeCtrl->IsRootItemSel();
|
|
sc = pStdToolbar->ScEnableUpOneLevel(bEnableUpOneLevel);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
// Now update history related buttons.
|
|
sc = ScCheckPointers(m_pHistoryList, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_pHistoryList->MaintainWebBar();
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScUpdateMMCMenus
|
|
//
|
|
// Synopsis: Show or Hide MMC menus depending on if they are allowed
|
|
// or not. Should do this only if our view owns the menus
|
|
// that is we are the active view. (Action/View/Favs)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScUpdateMMCMenus ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScUpdateMMCMenus"));
|
|
|
|
CMainFrame* pMainFrame = AMCGetMainWnd();
|
|
sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (this != pMainFrame->GetActiveAMCView())
|
|
return (sc = S_OK); // we are not active view so it is ok.
|
|
|
|
// We are active view so tell mainframe to update the menus.
|
|
sc = pMainFrame->ScShowMMCMenus(m_ViewData.IsStandardMenusAllowed());
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScCreateToolbarObjects
|
|
//
|
|
// Synopsis: Create the CAMCViewToolbars that manages all toolbar data
|
|
// for this view & CStandardToolbar objects.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScCreateToolbarObjects ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScCreateToolbarObjects"));
|
|
|
|
CMainFrame *pMainFrame = AMCGetMainWnd();
|
|
sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Create the toolbars for this view.
|
|
CMMCToolBar *pMainToolbar = pMainFrame->GetMainToolbar();
|
|
sc = ScCheckPointers(pMainToolbar, E_OUTOFMEMORY);
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_spAMCViewToolbars.CreateInstance();
|
|
sc = ScCheckPointers(m_spAMCViewToolbars, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_ViewData.SetAMCViewToolbarsMgr(m_spAMCViewToolbars);
|
|
sc = m_spAMCViewToolbars->ScInit(pMainToolbar, this);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// This CAMCViewToolbars is interested in view activation/de-activation/destruction events.
|
|
AddObserver( (CAMCViewObserver&) (*m_spAMCViewToolbars) );
|
|
|
|
// Main toolbar UI is interested in the active CAMCViewToolbars.
|
|
m_spAMCViewToolbars->AddObserver( *static_cast<CAMCViewToolbarsObserver *>(pMainToolbar) );
|
|
|
|
// MMC application is interested in the toolbar event, since it needs to inform the script
|
|
CAMCApp *pCAMCApp = AMCGetApp();
|
|
if ( pCAMCApp )
|
|
m_spAMCViewToolbars->AddObserver( *static_cast<CAMCViewToolbarsObserver *>(pCAMCApp) );
|
|
|
|
// Create standard toolbar.
|
|
m_spStandardToolbar = std::auto_ptr<CStandardToolbar>(new CStandardToolbar());
|
|
sc = ScCheckPointers(m_spStandardToolbar.get(), E_OUTOFMEMORY);
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_ViewData.SetStdVerbButtons(m_spStandardToolbar.get());
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* class CMMCViewFrame
|
|
*
|
|
*
|
|
* PURPOSE: The COM 0bject that exposes the Frame interface off the View object.
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
class CMMCViewFrame :
|
|
public CMMCIDispatchImpl<Frame>,
|
|
public CTiedComObject<CAMCView>
|
|
{
|
|
typedef CAMCView CMyTiedObject;
|
|
typedef CMMCViewFrame ThisClass;
|
|
|
|
public:
|
|
BEGIN_MMC_COM_MAP(ThisClass)
|
|
END_MMC_COM_MAP()
|
|
|
|
//Frame interface
|
|
public:
|
|
MMC_METHOD0( Maximize );
|
|
MMC_METHOD0( Minimize );
|
|
MMC_METHOD0( Restore );
|
|
|
|
MMC_METHOD1( get_Left, LPINT );
|
|
MMC_METHOD1( put_Left, INT );
|
|
|
|
MMC_METHOD1( get_Right, LPINT );
|
|
MMC_METHOD1( put_Right, INT );
|
|
|
|
MMC_METHOD1( get_Top, LPINT );
|
|
MMC_METHOD1( put_Top, INT );
|
|
|
|
MMC_METHOD1( get_Bottom, LPINT );
|
|
MMC_METHOD1( put_Bottom, INT );
|
|
};
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetFrame
|
|
*
|
|
* PURPOSE: Returns a pointer to the COM object that implements the
|
|
* Frame interface.
|
|
*
|
|
* PARAMETERS:
|
|
* Frame **ppFrame :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::Scget_Frame(Frame **ppFrame)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetFrame") );
|
|
|
|
if(!ppFrame)
|
|
{
|
|
sc = E_POINTER;
|
|
return sc;
|
|
}
|
|
|
|
// init out parameter
|
|
*ppFrame = NULL;
|
|
|
|
// create a CMMCApplicationFrame if not already done so.
|
|
sc = CTiedComObjectCreator<CMMCViewFrame>::ScCreateAndConnect(*this, m_spFrame);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if(m_spFrame == NULL)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
return sc;
|
|
}
|
|
|
|
// addref the pointer for the client.
|
|
m_spFrame->AddRef();
|
|
*ppFrame = m_spFrame;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
| Frame interface |
|
|
\***************************************************************************/
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScMaximize
|
|
*
|
|
* PURPOSE: Maximizes frame window of the view
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScMaximize ()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScMaximize"));
|
|
|
|
CChildFrame *pFrame = GetParentFrame();
|
|
|
|
sc = ScCheckPointers(pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
pFrame->ShowWindow(SW_MAXIMIZE);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScMinimize
|
|
*
|
|
* PURPOSE: Minimizes frame window of the view
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScMinimize ()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScMinimize"));
|
|
|
|
CChildFrame *pFrame = GetParentFrame();
|
|
|
|
sc = ScCheckPointers(pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
pFrame->ShowWindow(SW_MINIMIZE);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScRestore
|
|
*
|
|
* PURPOSE: Restores frame window of the view
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScRestore ()
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScRestore"));
|
|
|
|
CChildFrame *pFrame = GetParentFrame();
|
|
|
|
sc = ScCheckPointers(pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
pFrame->ShowWindow(SW_RESTORE);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetFrameCoord
|
|
*
|
|
* PURPOSE: Helper method. Returns specified coordinate of the parent frame
|
|
*
|
|
* PARAMETERS:
|
|
* LPINT pCoord - storage for return value
|
|
* coord_t eCoord - which coordinate to return (LEFT, TOP, etc)
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScGetFrameCoord ( LPINT pCoord, coord_t eCoord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetFrameCoord"));
|
|
|
|
// get & check frame ptr
|
|
CChildFrame *pFrame = GetParentFrame();
|
|
sc = ScCheckPointers(pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CWnd *pParent = pFrame->GetParent();
|
|
sc = ScCheckPointers (pParent, E_FAIL);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
// get coordinates of frame window relative to its parent
|
|
CWindowRect rcFrame (pFrame);
|
|
pParent->ScreenToClient(rcFrame);
|
|
|
|
// assign to result
|
|
sc = ScGetRectCoord (rcFrame, pCoord, eCoord);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScSetFrameCoord
|
|
*
|
|
* PURPOSE: Helper method. Sets specified coordinate of the parent frame
|
|
*
|
|
* PARAMETERS:
|
|
* INT coord - new value to set
|
|
* coord_t eCoord - which coordinate to modify (LEFT, TOP, etc)
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScSetFrameCoord ( INT coord, coord_t eCoord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSetFrameCoord"));
|
|
|
|
CChildFrame *pFrame = GetParentFrame();
|
|
sc = ScCheckPointers(pFrame, E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CWnd *pParent = pFrame->GetParent();
|
|
sc = ScCheckPointers (pParent, E_FAIL);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
// get coordinates of frame window relative to its parent
|
|
CWindowRect rcFrame (pFrame);
|
|
pParent->ScreenToClient(rcFrame);
|
|
|
|
// change the rectangle's specified coordinate
|
|
sc = ScSetRectCoord (rcFrame, coord, eCoord);
|
|
if (sc)
|
|
return (sc);
|
|
|
|
// move the window
|
|
pFrame->MoveWindow (rcFrame);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScGetRectCoord
|
|
*
|
|
* PURPOSE: Helper method. Returns specified coordinate of the given rectangle
|
|
*
|
|
* PARAMETERS:
|
|
* const RECT& rect - rectangle to query
|
|
* LPINT pCoord - storage for return value
|
|
* coord_t eCoord - which coordinate to return (LEFT, TOP, etc)
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScGetRectCoord ( const RECT& rect, LPINT pCoord, coord_t eCoord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScGetRectCoord"));
|
|
|
|
// check parameters
|
|
sc = ScCheckPointers(pCoord);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// assign to result
|
|
switch (eCoord)
|
|
{
|
|
case LEFT: *pCoord = rect.left; break;
|
|
case RIGHT: *pCoord = rect.right; break;
|
|
case TOP: *pCoord = rect.top; break;
|
|
case BOTTOM: *pCoord = rect.bottom; break;
|
|
|
|
default:
|
|
*pCoord = 0;
|
|
sc = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScSetRectCoord
|
|
*
|
|
* PURPOSE: Helper method. Sets specified coordinate of the given rectangle
|
|
*
|
|
* PARAMETERS:
|
|
* RECT& rect - rectangle to modify
|
|
* INT coord - new value to set
|
|
* coord_t eCoord - which coordinate to modify (LEFT, TOP, etc)
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::ScSetRectCoord ( RECT& rect, INT coord, coord_t eCoord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSetRectCoord"));
|
|
|
|
// assign coordinate
|
|
switch (eCoord)
|
|
{
|
|
case LEFT: rect.left = coord; break;
|
|
case RIGHT: rect.right = coord; break;
|
|
case TOP: rect.top = coord; break;
|
|
case BOTTOM: rect.bottom = coord; break;
|
|
default: sc = E_INVALIDARG; break;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_Left
|
|
*
|
|
* PURPOSE: Implements Frame.Left property's Get method for view
|
|
*
|
|
* PARAMETERS:
|
|
* LPINT pCoord - storage for return value
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scget_Left ( LPINT pCoord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Left"));
|
|
|
|
sc = ScGetFrameCoord( pCoord, LEFT );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_Left
|
|
*
|
|
* PURPOSE: Implements Frame.Left property's Put method for view
|
|
*
|
|
* PARAMETERS:
|
|
* INT coord - value to set
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scput_Left ( INT coord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_Left"));
|
|
|
|
sc = ScSetFrameCoord( coord, LEFT );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_Right
|
|
*
|
|
* PURPOSE: Implements Frame.Right property's Get method for view
|
|
*
|
|
* PARAMETERS:
|
|
* LPINT pCoord - storage for return value
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scget_Right ( LPINT pCoord)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Right"));
|
|
|
|
sc = ScGetFrameCoord( pCoord, RIGHT );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_Right
|
|
*
|
|
* PURPOSE: Implements Frame.Right property's Put method for view
|
|
*
|
|
* PARAMETERS:
|
|
* INT coord - value to set
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scput_Right ( INT coord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_Right"));
|
|
|
|
sc = ScSetFrameCoord( coord, RIGHT );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_Top
|
|
*
|
|
* PURPOSE: Implements Frame.Top property's Get method for view
|
|
*
|
|
* PARAMETERS:
|
|
* LPINT pCoord - storage for return value
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scget_Top ( LPINT pCoord)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Top"));
|
|
|
|
sc = ScGetFrameCoord( pCoord, TOP );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_Top
|
|
*
|
|
* PURPOSE: Implements Frame.Top property's Put method for view
|
|
*
|
|
* PARAMETERS:
|
|
* INT coord - value to set
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scput_Top ( INT coord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_Top"));
|
|
|
|
sc = ScSetFrameCoord( coord, TOP );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scget_Bottom
|
|
*
|
|
* PURPOSE: Implements Frame.Bottom property's Get method for view
|
|
*
|
|
* PARAMETERS:
|
|
* LPINT pCoord - storage for return value
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scget_Bottom ( LPINT pCoord)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Bottom"));
|
|
|
|
|
|
sc = ScGetFrameCoord( pCoord, BOTTOM );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::Scput_Bottom
|
|
*
|
|
* PURPOSE: Implements Frame.Bottom property's Put method for view
|
|
*
|
|
* PARAMETERS:
|
|
* INT coord - value to set
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC CAMCView::Scput_Bottom ( INT coord )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scput_Bottom"));
|
|
|
|
sc = ScSetFrameCoord( coord, BOTTOM );
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScSetViewExtensionFrame
|
|
*
|
|
* PURPOSE:
|
|
*
|
|
* PARAMETERS:
|
|
* INT top :
|
|
* INT left :
|
|
* INT bottom :
|
|
* INT right :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScSetViewExtensionFrame(bool bShowListView, INT top, INT left, INT bottom, INT right)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScSetViewExtensionFrame"))
|
|
|
|
|
|
/*
|
|
* this method is only available while a view extension is active
|
|
*/
|
|
if (!m_fViewExtended)
|
|
return sc; // return silently. NOTE: This method will be removed shortly, as will the view extension hosted frame object,
|
|
// once mmc moves the mmcview behavior into the web host's element factory.
|
|
|
|
|
|
/*
|
|
* figure out the maximum bounding rectangle for the hosted view,
|
|
* mapped to view extension-relative coordinates
|
|
*/
|
|
CRect rectBound;
|
|
CalcMaxHostedFrameRect (rectBound);
|
|
|
|
#ifdef DBG
|
|
CString strDebugMsg;
|
|
strDebugMsg.Format (_T("CAMCView::ScSetViewExtFrameCoord bound=(l=%d,t=%d,r=%d,b=%d), new = (l=%d,t=%d,r=%d,b=%d)"),
|
|
rectBound.left, rectBound.top, rectBound.right, rectBound.bottom,
|
|
left, top, right, bottom
|
|
);
|
|
#endif
|
|
|
|
/*
|
|
* make sure the requested coordinate is withing the permitted area
|
|
*/
|
|
if (left < rectBound.left)
|
|
left = rectBound.left;
|
|
if (right > rectBound.right)
|
|
right = rectBound.right;
|
|
if (top < rectBound.top)
|
|
top = rectBound.top;
|
|
if (bottom > rectBound.bottom)
|
|
bottom = rectBound.bottom;
|
|
|
|
|
|
/*
|
|
* if we get here, the view extension-relative coordinate supplied
|
|
* is within the acceptable range, now we need to convert it to
|
|
* CAMCView-relative coordinates
|
|
*/
|
|
CPoint pointTopLeft(left, top);
|
|
CPoint pointBottomRight(right, bottom);
|
|
|
|
if ( GetExStyle() & WS_EX_LAYOUTRTL )
|
|
{
|
|
// IE does not change left/right order on the RTL locales
|
|
// thus we need to mirror it's coordinates
|
|
// see windows bug #195094 ntbugs9 11/30/00
|
|
pointTopLeft.x = rectBound.left + (rectBound.right - right);
|
|
pointBottomRight.x = rectBound.left + (rectBound.right - left);
|
|
}
|
|
|
|
MapHostedFramePtToViewPt (pointTopLeft);
|
|
MapHostedFramePtToViewPt (pointBottomRight);
|
|
|
|
/*
|
|
* set the coordinates
|
|
*/
|
|
CRect rectViewExtHostedFrame;
|
|
|
|
rectViewExtHostedFrame.left = pointTopLeft.x;
|
|
rectViewExtHostedFrame.right = pointBottomRight.x;
|
|
rectViewExtHostedFrame.top = pointTopLeft.y;
|
|
rectViewExtHostedFrame.bottom = pointBottomRight.y;
|
|
|
|
// move the window to the correct location
|
|
CWnd* pwndResult = GetPaneView(ePane_Results);
|
|
|
|
sc = ScCheckPointers(pwndResult);
|
|
if(sc)
|
|
return sc;
|
|
|
|
if (bShowListView)
|
|
pwndResult->ShowWindow(SW_SHOW);
|
|
|
|
::MoveWindow(*pwndResult, rectViewExtHostedFrame.left, rectViewExtHostedFrame.top,
|
|
rectViewExtHostedFrame.right - rectViewExtHostedFrame.left,
|
|
rectViewExtHostedFrame.bottom - rectViewExtHostedFrame.top,
|
|
TRUE /*bRepaint*/);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::CalcMaxHostedFrameRect
|
|
*
|
|
* Returns the maximum rectangle that can be occupied by a view extension's
|
|
* hosted frame, normalized around (0,0).
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::CalcMaxHostedFrameRect (CRect& rect)
|
|
{
|
|
/*
|
|
* start with the result frame rectangle and inset it a little so
|
|
* we'll see the client edge provided by the view extension's web
|
|
* host view
|
|
*/
|
|
rect = m_rectResultFrame;
|
|
rect.DeflateRect (m_sizEdge);
|
|
|
|
/*
|
|
* now normalize around (0,0)
|
|
*/
|
|
rect.OffsetRect (-rect.TopLeft());
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::MapViewPtToHostedFramePt
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::MapViewPtToHostedFramePt (CPoint& pt)
|
|
{
|
|
PointMapperWorker (pt, true);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::MapHostedFramePtToViewPt
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::MapHostedFramePtToViewPt (CPoint& pt)
|
|
{
|
|
PointMapperWorker (pt, false);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* CAMCView::MapHostedFramePtToViewPt
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void CAMCView::PointMapperWorker (CPoint& pt, bool fViewToHostedFrame)
|
|
{
|
|
int nMultiplier = (fViewToHostedFrame) ? -1 : 1;
|
|
|
|
/*
|
|
* adjust to the origin of the result frame rectangle and for the
|
|
* web host view's client edge
|
|
*/
|
|
pt.Offset (nMultiplier * (m_rectResultFrame.left + m_sizEdge.cx),
|
|
nMultiplier * (m_rectResultFrame.top + m_sizEdge.cy));
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CXMLWindowPlacement::Persist
|
|
*
|
|
* PURPOSE: Persists window placement settings
|
|
*
|
|
* PARAMETERS:
|
|
* CPersistor &persistor
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
\***************************************************************************/
|
|
void CXMLWindowPlacement::Persist(CPersistor &persistor)
|
|
{
|
|
// create wrapper to persist flag values as strings
|
|
CXMLBitFlags wpFlagsPersistor(m_rData.flags, mappedWPFlags, countof(mappedWPFlags));
|
|
// persist the wrapper
|
|
persistor.PersistAttribute( XML_ATTR_WIN_PLACEMENT_FLAGS, wpFlagsPersistor );
|
|
|
|
// persist show command as literal
|
|
// create wrapper to persist enumeration values as strings
|
|
CXMLEnumeration showCmdPersistor(m_rData.showCmd, mappedSWCommands, countof(mappedSWCommands));
|
|
// persist the wrapper
|
|
persistor.PersistAttribute( XML_ATTR_SHOW_COMMAND, showCmdPersistor );
|
|
|
|
persistor.Persist( XMLPoint( XML_NAME_MIN_POSITION, m_rData.ptMinPosition ) );
|
|
persistor.Persist( XMLPoint( XML_NAME_MAX_POSITION, m_rData.ptMaxPosition ) );
|
|
persistor.Persist( XMLRect( XML_NAME_NORMAL_POSITION, m_rData.rcNormalPosition ) );
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::Scget_Document
|
|
*
|
|
* PURPOSE: implements View.Document property in object model
|
|
*
|
|
* PARAMETERS:
|
|
* PPDOCUMENT ppDocument [out] document to which the view belongs
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::Scget_Document( PPDOCUMENT ppDocument )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_Document"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(ppDocument);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// get the document
|
|
CAMCDoc* pDoc = GetDocument();
|
|
sc = ScCheckPointers(pDoc, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// construct com object
|
|
sc = pDoc->ScGetMMCDocument(ppDocument);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
/*******************************************************\
|
|
| helper function to avoid too many stack allocations
|
|
\*******************************************************/
|
|
static tstring W2T_ForLoop(const std::wstring& str)
|
|
{
|
|
#if defined(_UNICODE)
|
|
return str;
|
|
#else
|
|
USES_CONVERSION;
|
|
return W2CA(str.c_str());
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::ScAddFolderTabs
|
|
*
|
|
* PURPOSE: Collects view extensions and taskpads and displays them as tabs
|
|
*
|
|
* PARAMETERS:
|
|
* HNODE hNode - selected scope node
|
|
* const CLSID &guidTabToSelect - tab to select
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::ScAddFolderTabs( HNODE hNode, const CLSID& guidTabToSelect )
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::ScAddFolderTabs"));
|
|
|
|
sc = ScCheckPointers(m_pResultFolderTabView, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// cleanup urls
|
|
m_ViewExtensionURLs.clear();
|
|
|
|
// cleanup view tabs before we do anything else
|
|
m_pResultFolderTabView->DeleteAllItems();
|
|
|
|
// get the callback
|
|
INodeCallback* pNodeCallBack = GetNodeCallback();
|
|
sc = ScCheckPointers(pNodeCallBack, m_pResultFolderTabView, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// collect view extensions
|
|
CViewExtCollection vecExtensions;
|
|
CViewExtInsertIterator itExtensions(vecExtensions, vecExtensions.begin());
|
|
|
|
sc = pNodeCallBack->GetNodeViewExtensions(hNode, itExtensions);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
vecExtensions.clear();
|
|
// continue anyway
|
|
}
|
|
|
|
// check if there is something to show
|
|
if(vecExtensions.size() == 0) // no tabs to show.
|
|
{
|
|
m_pResultFolderTabView->SetVisible(false);
|
|
}
|
|
else
|
|
{
|
|
bool bAddDefaultTab = true;
|
|
|
|
// add extensions
|
|
CViewExtCollection::iterator iterVE;
|
|
for(iterVE = vecExtensions.begin(); iterVE != vecExtensions.end(); ++iterVE)
|
|
{
|
|
tstring strName( W2T_ForLoop(iterVE->strName) );
|
|
m_pResultFolderTabView->AddItem(strName.c_str(), iterVE->viewID);
|
|
m_ViewExtensionURLs[iterVE->viewID] = W2T_ForLoop(iterVE->strURL);
|
|
// do not add the "normal" tab if we have a valid replacement for it
|
|
if (iterVE->bReplacesDefaultView)
|
|
bAddDefaultTab = false;
|
|
}
|
|
|
|
// add the default item.
|
|
if (bAddDefaultTab)
|
|
{
|
|
CStr strNormal;
|
|
strNormal.LoadString(GetStringModule(), IDS_NORMAL);
|
|
m_pResultFolderTabView->AddItem(strNormal, GUID_NULL);
|
|
}
|
|
|
|
// select required item and show tabs
|
|
int iIndex = m_pResultFolderTabView->SelectItemByClsid(guidTabToSelect);
|
|
if (iIndex < 0)
|
|
TraceError(_T("CAMCView::ScAddFolderTabs - failed to select requested folder"), SC(E_FAIL));
|
|
|
|
// no need for cotrol if we only have one tab
|
|
bool bMoreThanOneTab = (m_pResultFolderTabView->GetItemCount() > 1);
|
|
m_pResultFolderTabView->SetVisible(bMoreThanOneTab);
|
|
}
|
|
|
|
// lookup view extension URL
|
|
CViewExtensionURLs::iterator itVE = m_ViewExtensionURLs.find(guidTabToSelect);
|
|
LPCTSTR url = (itVE != m_ViewExtensionURLs.end()) ? itVE->second.c_str() : NULL;
|
|
|
|
// apply URL
|
|
sc = ScApplyViewExtension(url);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
RecalcLayout();
|
|
|
|
return sc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* METHOD: CAMCView::Scget_ControlObject
|
|
*
|
|
* PURPOSE: returns IDispatch of embeded OCX control
|
|
* implements View.ControlObject property
|
|
*
|
|
* PARAMETERS:
|
|
* PPDISPATCH ppControl [out] control's interface
|
|
*
|
|
* RETURNS:
|
|
* SC - result code
|
|
*
|
|
\***************************************************************************/
|
|
SC CAMCView::Scget_ControlObject( PPDISPATCH ppControl)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCView::Scget_ControlObject"));
|
|
|
|
// parameter check
|
|
sc = ScCheckPointers(ppControl);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// init out param
|
|
*ppControl = NULL;
|
|
|
|
// have a OCX view?
|
|
if ( (! HasOCX()) || (m_pOCXHostView == NULL))
|
|
return sc.FromMMC( MMC_E_NO_OCX_IN_VIEW );
|
|
|
|
// get the control's interface
|
|
CComQIPtr<IDispatch> spDispatch = m_pOCXHostView->GetIUnknown();
|
|
if (spDispatch == NULL)
|
|
return sc = E_NOINTERFACE;
|
|
|
|
// return the pointer
|
|
*ppControl = spDispatch.Detach();
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScTreeViewSelectionActivate
|
|
//
|
|
// Synopsis: Only the list(/Web/OCX) or the tree can be "active" from the point
|
|
// of view of selected items and MMCN_SELECT. This is not
|
|
// the same as the MFC concept of "active view". There are a couple
|
|
// of views that cannot be active in this sense, such as the taskpad
|
|
// and tab views.
|
|
// When the active view (according to this definition) changes, this
|
|
// function is called. Thus, ScTreeViewSelectionActivate and
|
|
// ScListViewSelectionActivate/ScSpecialResultpaneSelectionActivate
|
|
// are always called in pairs when the activation changes, one to handle
|
|
// deactivation, and one to handle activation.
|
|
//
|
|
// Consider the following scenario
|
|
// 1) The tree view has (MFC/windows style) focus.
|
|
// 2) The user clicks on the taskpad view
|
|
// Result - selection activation does not change from the tree. All verbs
|
|
// still correspond to the selected tree item.
|
|
// 3) The user clicks on the folder view
|
|
// Result - once again, selection activation does not chang
|
|
// 4) The user clicks on one of the result views eg the list
|
|
// Result - ScTreeViewSelectionActivate(false) and ScListViewSelectionActivate(true)
|
|
// Thus verbs and the toolbar now correspond to the selected list item(s).
|
|
// 5) The user clicks on the taskpad view.
|
|
// Result - as in step 2, nothing happens
|
|
// 6) The user clicks on the result view
|
|
// Result - because the active view has not changed, nothing happens.
|
|
//
|
|
// Arguments: [bActivate] - [in]
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScTreeViewSelectionActivate (bool bActivate)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScTreeViewSelectionActivate"));
|
|
|
|
sc = ScCheckPointers(m_pTreeCtrl, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// 1. Setup the SELECTINFO
|
|
SELECTIONINFO selInfo;
|
|
ZeroMemory(&selInfo, sizeof(selInfo));
|
|
selInfo.m_bScope = TRUE;
|
|
selInfo.m_pView = NULL;
|
|
selInfo.m_bDueToFocusChange = TRUE;
|
|
|
|
if (HasOCX())
|
|
{
|
|
selInfo.m_bResultPaneIsOCX = true;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMOCX;
|
|
}
|
|
else if (HasWebBrowser())
|
|
{
|
|
selInfo.m_bResultPaneIsWeb = TRUE;
|
|
selInfo.m_lCookie = LVDATA_CUSTOMWEB;
|
|
}
|
|
|
|
HTREEITEM htiSelected = m_pTreeCtrl->GetSelectedItem();
|
|
HNODE hSelectedNode = (htiSelected != NULL) ? m_pTreeCtrl->GetItemNode (htiSelected) : NULL;
|
|
|
|
// insure that this is the active view when we have the focus
|
|
ASSERT ( ( (bActivate) && (GetParentFrame()->GetActiveView () == m_pTreeCtrl) ) ||
|
|
( (!bActivate) && (GetParentFrame()->GetActiveView () != m_pTreeCtrl) ) );
|
|
|
|
if (hSelectedNode != NULL)
|
|
{
|
|
// Send select notification.
|
|
sc = ScNotifySelect ( GetNodeCallback(), hSelectedNode,
|
|
false /*fMultiSelect*/, bActivate, &selInfo);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
else if ( (htiSelected == NULL) && (bActivate) )
|
|
{
|
|
m_pTreeCtrl->SelectItem (m_pTreeCtrl->GetRootItem());
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScOnTreeViewActivated
|
|
//
|
|
// Synopsis: Observer implementation for tree-view activation.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScOnTreeViewActivated ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnTreeViewActivated"));
|
|
|
|
if (m_eCurrentActivePane == eActivePaneScope) // Scope pane is already active so return.
|
|
return sc;
|
|
|
|
#ifdef DBG
|
|
Trace (tagViewActivation, _T("Deactivate %s in result pane Activate Scope pane\n"),
|
|
HasListOrListPad() ? _T("ListView") : (HasOCX() ? _T("OCX") : _T("WebBrowser")));
|
|
#endif
|
|
|
|
if (m_eCurrentActivePane == eActivePaneResult)
|
|
{
|
|
// Send deactivate to result.
|
|
if (HasListOrListPad())
|
|
sc = ScListViewSelectionActivate (false);
|
|
else if (HasOCX() || HasWebBrowser())
|
|
sc = ScSpecialResultpaneSelectionActivate(false);
|
|
else
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
// Send select to scope.
|
|
m_eCurrentActivePane = eActivePaneScope;
|
|
sc = ScTreeViewSelectionActivate(true);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScOnListViewActivated
|
|
//
|
|
// Synopsis: Observer implementation for list-view activation.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScOnListViewActivated ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnListViewActivated"));
|
|
|
|
if (m_eCurrentActivePane == eActivePaneResult) // Result pane is already active so return.
|
|
return sc;
|
|
|
|
#ifdef DBG
|
|
Trace (tagViewActivation, _T("Deactivate Scope pane Activate ListView in Result pane\n"));
|
|
#endif
|
|
|
|
if (m_eCurrentActivePane == eActivePaneScope)
|
|
{
|
|
// Send deactivate to scope.
|
|
sc = ScTreeViewSelectionActivate(false);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
// Send activate to list.
|
|
m_eCurrentActivePane = eActivePaneResult;
|
|
ASSERT(HasListOrListPad());
|
|
|
|
sc = ScListViewSelectionActivate (true);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
*
|
|
* CAMCView::ScOnListViewItemUpdated
|
|
*
|
|
* PURPOSE: called when an item is updated. This method fires an event to all COM observers.
|
|
*
|
|
* PARAMETERS:
|
|
* int nIndex :
|
|
*
|
|
* RETURNS:
|
|
* SC
|
|
*
|
|
*+-------------------------------------------------------------------------*/
|
|
SC
|
|
CAMCView::ScOnListViewItemUpdated (int nIndex)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnListViewItemUpdated"));
|
|
|
|
// fire event
|
|
sc = ScFireEvent(CAMCViewObserver::ScOnListViewItemUpdated, this, nIndex);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScOnOCXHostActivated
|
|
//
|
|
// Synopsis: Observer implementation for ocx or web view activation.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCView::ScOnOCXHostActivated ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnOCXHostActivated"));
|
|
|
|
if (m_eCurrentActivePane == eActivePaneResult) // Result pane is already active so return.
|
|
return sc;
|
|
|
|
#ifdef DBG
|
|
Trace (tagViewActivation, _T("Deactivate Scope pane Activate %s in Result pane\n"),
|
|
HasOCX() ? _T("OCX") : _T("WebBrowser"));
|
|
#endif
|
|
|
|
if (m_eCurrentActivePane == eActivePaneScope)
|
|
{
|
|
// Send deactivate to scope.
|
|
sc = ScTreeViewSelectionActivate(false);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
}
|
|
|
|
// Send select to ocx or web view.
|
|
m_eCurrentActivePane = eActivePaneResult;
|
|
ASSERT(HasOCX() || HasWebBrowser());
|
|
|
|
sc = ScSpecialResultpaneSelectionActivate(true);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
return (sc);
|
|
}
|