2025-04-27 07:49:33 -04:00

2397 lines
58 KiB
C++

// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//***************************************************************************
//
// (c) 1996, 1997 by Microsoft Corporation
//
// hmmvctl.cpp
//
// This file contains the implementation of the main view container as well
// as the generic view.
//
// a-larryf 17-Sept-96 Created.
//
//***************************************************************************
#include "precomp.h"
#include <initguid.h>
#include <afxcmn.h>
#include "hmmv.h"
#include "HmmvCtl.h"
#include "HmmvPpg.h"
#include "utils.h"
#include "resource.h"
#include "titlebar.h"
#include "globals.h"
#include "filters.h"
#include "mv.h"
#include "vwstack.h"
#include "sv.h"
#include "PolyView.h"
#include "hmomutil.h"
#include "htmlhelp.h"
#include <wbemcli.h>
#include "wbemRegistry.h"
#include "coloredt.h"
#include "DlgHelpBox.h"
#include "DlgExecQuery.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CGenericViewContext::~CGenericViewContext()
{
if (m_psv!=NULL && m_lContextHandle != NULL) {
m_psv->ReleaseContext(m_lContextHandle);
}
}
#define GENERIC_VIEW_INDEX 0
#define CY_TAB_FONT 15
#define CX_VIEW_DEFAULT_LEFT_MARGIN 8
#define CX_VIEW_DEFAULT_RIGHT_MARGIN 8
#define CY_VIEW_DEFAULT_TOP_MARGIN 8
#define CY_VIEW_DEFAULT_BOTTOM_MARGIN 8
#define CY_TITLE_DEFAULT_TOP_MARGIN 4
IMPLEMENT_DYNCREATE(CWBEMViewContainerCtrl, COleControl)
/////////////////////////////////////////////////////////////////////////////
// Message map
BEGIN_MESSAGE_MAP(CWBEMViewContainerCtrl, COleControl)
ON_WM_CONTEXTMENU()
//{{AFX_MSG_MAP(CWBEMViewContainerCtrl)
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_COMMAND(ID_CMD_SHOW_OBJECT_ATTRIBUTES, OnCmdShowObjectAttributes)
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CWBEMViewContainerCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CWBEMViewContainerCtrl)
DISP_PROPERTY_NOTIFY(CWBEMViewContainerCtrl, "StatusCode", m_sc, OnStatusCodeChanged, VT_I4)
DISP_PROPERTY_EX(CWBEMViewContainerCtrl, "ObjectPath", GetObjectPath, SetObjectPath, VT_VARIANT)
DISP_PROPERTY_EX(CWBEMViewContainerCtrl, "NameSpace", GetNameSpace, SetNameSpace, VT_BSTR)
DISP_PROPERTY_EX(CWBEMViewContainerCtrl, "StudioModeEnabled", GetStudioModeEnabled, SetStudioModeEnabled, VT_I4)
DISP_PROPERTY_EX(CWBEMViewContainerCtrl, "PropertyFilter", GetPropertyFilter, SetPropertyFilter, VT_I4)
DISP_FUNCTION(CWBEMViewContainerCtrl, "ShowInstances", ShowInstances, VT_EMPTY, VTS_BSTR VTS_VARIANT)
DISP_FUNCTION(CWBEMViewContainerCtrl, "SaveState", SaveState, VT_I4, VTS_I4 VTS_I4)
DISP_FUNCTION(CWBEMViewContainerCtrl, "QueryViewInstances", QueryViewInstances, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
DISP_STOCKPROP_READYSTATE()
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
/////////////////////////////////////////////////////////////////////////////
// Event map
BEGIN_EVENT_MAP(CWBEMViewContainerCtrl, COleControl)
//{{AFX_EVENT_MAP(CWBEMViewContainerCtrl)
EVENT_CUSTOM("GetIWbemServices", FireGetIWbemServices, VTS_BSTR VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT)
EVENT_CUSTOM("NOTIFYChangeRootOrNamespace", FireNOTIFYChangeRootOrNamespace, VTS_BSTR VTS_I4 VTS_I4)
EVENT_CUSTOM("RequestUIActive", FireRequestUIActive, VTS_NONE)
EVENT_STOCK_READYSTATECHANGE()
//}}AFX_EVENT_MAP
END_EVENT_MAP()
/////////////////////////////////////////////////////////////////////////////
// Property pages
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CWBEMViewContainerCtrl, 1)
PROPPAGEID(CWBEMViewContainerPropPage::guid)
END_PROPPAGEIDS(CWBEMViewContainerCtrl)
/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CWBEMViewContainerCtrl, "WBEM.ObjViewerCtrl.1",
0x5b3572ab, 0xd344, 0x11cf, 0x99, 0xcb, 0, 0xc0, 0x4f, 0xd6, 0x44, 0x97)
/////////////////////////////////////////////////////////////////////////////
// Type library ID and version
IMPLEMENT_OLETYPELIB(CWBEMViewContainerCtrl, _tlid, _wVerMajor, _wVerMinor)
/////////////////////////////////////////////////////////////////////////////
// Interface IDs
const IID BASED_CODE IID_DWBEMViewContainer =
{ 0x5b3572a9, 0xd344, 0x11cf, { 0x99, 0xcb, 0, 0xc0, 0x4f, 0xd6, 0x44, 0x97 } };
const IID BASED_CODE IID_DWBEMViewContainerEvents =
{ 0x5b3572aa, 0xd344, 0x11cf, { 0x99, 0xcb, 0, 0xc0, 0x4f, 0xd6, 0x44, 0x97 } };
/////////////////////////////////////////////////////////////////////////////
// Control type information
static const DWORD BASED_CODE _dwWBEMViewContainerOleMisc =
OLEMISC_SIMPLEFRAME |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CWBEMViewContainerCtrl, IDS_HMMV, _dwWBEMViewContainerOleMisc)
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::CWBEMViewContainerCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CWBEMViewContainerCtrl
BOOL CWBEMViewContainerCtrl::CWBEMViewContainerCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Verify that your control follows apartment-model threading rules.
// Refer to MFC TechNote 64 for more information.
// If your control does not conform to the apartment-model rules, then
// you must modify the code below, changing the 6th parameter from
// afxRegInsertable | afxRegApartmentThreading to 0.
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_HMMV,
IDB_HMMV,
afxRegInsertable | afxRegApartmentThreading,
_dwWBEMViewContainerOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::CWBEMViewContainerCtrl - Constructor
CWBEMViewContainerCtrl::CWBEMViewContainerCtrl()
{
m_bCreationFinished = FALSE;
InitializeIIDs(&IID_DWBEMViewContainer, &IID_DWBEMViewContainerEvents);
EnableSimpleFrame();
SetModifiedFlag(FALSE);
AfxEnableControlContainer();
m_htmlHelpInst = 0;
m_bDelayToolbarUpdate = FALSE;
m_bInStudioMode = TRUE;
m_bEmptyContainer = TRUE;
m_bSingleViewNeedsRefresh = FALSE;
m_bDidInitialDraw = FALSE;
m_bPathIsClass = TRUE;
m_bObjectIsNewlyCreated = FALSE;
m_bFiredReadyStateChange = FALSE;
m_lPropFilters = (PROPFILTER_SYSTEM | PROPFILTER_INHERITED | PROPFILTER_LOCAL);
// The instance paths from ShowInstances
m_varObjectPath = L"";
m_cxViewLeftMargin = CX_VIEW_DEFAULT_LEFT_MARGIN;
m_cxViewRightMargin = CX_VIEW_DEFAULT_RIGHT_MARGIN;
m_cyViewTopMargin = CY_VIEW_DEFAULT_TOP_MARGIN;
m_cyViewBottomMargin = CY_VIEW_DEFAULT_BOTTOM_MARGIN;
GetViewerFont(m_font, CY_TAB_FONT, FW_NORMAL);
m_pViewStack = new CViewStack(this);
m_pTitleBar = new CTitleBar;
m_pview = new CPolyView(this);
m_pdlgHelpBox = new CDlgHelpBox(this);
m_bDeadObject = FALSE; // An object is dead when a user chooses not to save it
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::~CWBEMViewContainerCtrl - Destructor
CWBEMViewContainerCtrl::~CWBEMViewContainerCtrl()
{
// These objects should have been freed in CWBEMViewContainerCtrl::OnDestroy
ASSERT(m_pview == NULL);
ASSERT(m_pViewStack == NULL);
ASSERT(m_pTitleBar == NULL);
#ifdef USE_HTML_HELP
if(m_htmlHelpInst)
{
FreeLibrary(m_htmlHelpInst);
m_htmlHelpInst = NULL;
}
#endif //USE_HTML_HELP
}
void CWBEMViewContainerCtrl::DrawBackground(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
CBrush brBACKGROUND(GetSysColor(COLOR_BACKGROUND));
CBrush br3DFACE(GetSysColor(COLOR_3DFACE));
pdc->FillRect(rcBounds, &br3DFACE);
}
void CWBEMViewContainerCtrl::CalcViewRect(CRect& rcView)
{
CRect rcClient;
GetClientRect(&rcClient);
rcView.top = rcClient.top + m_pTitleBar->GetDesiredBarHeight() + m_cyViewTopMargin;
rcView.left = rcClient.left + m_cxViewLeftMargin;
rcView.right = rcClient.right - m_cxViewRightMargin;
rcView.bottom = rcClient.bottom - m_cyViewBottomMargin;
}
void CWBEMViewContainerCtrl::CalcTitleRect(CRect& rcTitle)
{
CRect rcClient;
GetClientRect(&rcClient);
rcTitle.top = rcClient.top + CY_TITLE_DEFAULT_TOP_MARGIN;
rcTitle.left = rcClient.left + m_cxViewLeftMargin;
rcTitle.right = rcClient.right - m_cxViewRightMargin;
rcTitle.bottom = rcClient.top + m_pTitleBar->GetDesiredBarHeight();
}
void CWBEMViewContainerCtrl::OnDrawPreCreate(
CDC* pdc,
const CRect& rcBounds,
const CRect& rcInvalid)
{
CBrush brBackground;
brBackground.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
CBrush brBlack;
brBlack.CreateSolidBrush(::GetSysColor(COLOR_ACTIVEBORDER));
pdc->FillRect(rcInvalid, &brBackground);
CRect rcFrame = rcBounds;
rcFrame.InflateRect(-1, -1);
pdc->FrameRect(rcFrame, &brBlack);
return;
#if 0
// I attempted to draw a small image of the object view so that
// you would see something interesting at design time. However,
// people didn't like it, so I've commented out the code here.
CDC dcMem;
BOOL bDidCreate;
BOOL bDidLoad;
bDidCreate = dcMem.CreateCompatibleDC(pdc);
if (!bDidCreate) {
return;
}
CBitmap bm;
bDidLoad = bm.LoadBitmap(IDB_DESIGN_TIME);
BITMAP bitmap;
bm.GetBitmap(&bitmap);
CBitmap* pbmSave = dcMem.SelectObject(&bm);
int ixDst = 0;
int iyDst = 0;
if (bitmap.bmWidth < rcBounds.Width()) {
ixDst = (rcBounds.Width() - bitmap.bmWidth) / 2;
}
if (bitmap.bmHeight < rcBounds.Height()) {
iyDst = (rcBounds.Height() - bitmap.bmHeight) / 2;
}
pdc->BitBlt(ixDst, iyDst, rcBounds.Width(), rcBounds.Height(), &dcMem, 0, 0, SRCCOPY);
dcMem.SelectObject(pbmSave);
#endif //0
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::OnDraw - Drawing function
void CWBEMViewContainerCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!::IsWindow(m_hWnd)) {
OnDrawPreCreate(pdc, rcBounds, rcInvalid);
return;
}
COLORREF clrBack = RGB(0x0ff, 0, 0);
pdc->SetBkColor(clrBack);
DrawBackground(pdc, rcBounds, rcInvalid);
if (!m_bDidInitialDraw) {
m_bDidInitialDraw = TRUE;
if (m_pview->DidCreateWindow()) {
m_pview->ShowSingleView();
m_pTitleBar->NotifyObjectChanged();
}
}
// Redraw the portion of the titlebar that is invalid.
CRect rcTitleBar;
m_pTitleBar->GetWindowRect(rcTitleBar);
ScreenToClient(rcTitleBar);
BOOL bFixTitleBar = rcTitleBar.IntersectRect(&rcInvalid, &rcTitleBar);
if (bFixTitleBar) {
ClientToScreen(rcTitleBar);
m_pTitleBar->ScreenToClient(rcTitleBar);
m_pTitleBar->InvalidateRect(rcTitleBar);
}
CRect rcText = rcBounds;
rcText.bottom = rcText.top + 32;
rcText.top = rcText.top + 6;
rcText.left = rcText.left + 32 + 8 + 5 + 4;
rcText.right = rcText.right - 8;
if (m_pview->DidCreateWindow()) {
BOOL IsShowingMultiview = m_pview->IsShowingMultiview();
BOOL bMultiviewVisible = m_pview->GetMultiView()->IsWindowVisible();
BOOL bSingleviewVisible = m_pview->GetSingleView()->IsWindowVisible();
CRect rcView;
BOOL bFixView;
if (bMultiviewVisible) {
CMultiView* pmv = m_pview->GetMultiView();
pmv->GetWindowRect(rcView);
ScreenToClient(rcView);
bFixView = rcView.IntersectRect(&rcInvalid, &rcView);
if (bFixView) {
ClientToScreen(rcView);
pmv->ScreenToClient(rcView);
pmv->InvalidateRect(rcView);
}
}
if (bSingleviewVisible) {
CSingleView* psv = m_pview->GetSingleView();
psv->GetWindowRect(rcView);
ScreenToClient(rcView);
bFixView = rcView.IntersectRect(&rcInvalid, &rcView);
if (bFixView) {
ClientToScreen(rcView);
psv->ScreenToClient(rcView);
psv->InvalidateRect(rcView);
}
}
// m_pview->RedrawWindow();
}
if (!m_bFiredReadyStateChange) {
m_bFiredReadyStateChange = TRUE;
FireReadyStateChange();
}
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::DoPropExchange - Persistence support
void CWBEMViewContainerCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
CString sObjectPath;
PX_String(pPX, _T("ObjectPath"), sObjectPath, CString(_T("")));
m_varObjectPath = (const CString&) sObjectPath;
PX_String(pPX, _T("NameSpace"), m_sNameSpace, CString(_T("")));
PX_Bool(pPX, _T("StudioModeEnabled"), m_bInStudioMode, TRUE);
m_pview->SetStudioModeEnabled(m_bInStudioMode);
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl::OnResetState - Reset control to default state
void CWBEMViewContainerCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
}
/////////////////////////////////////////////////////////////////////////////
// CWBEMViewContainerCtrl message handlers
void CWBEMViewContainerCtrl::DoDataExchange(CDataExchange* pDX)
{
COleControl::DoDataExchange(pDX);
}
LRESULT CWBEMViewContainerCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
return COleControl::WindowProc(message, wParam, lParam);
}
void CWBEMViewContainerCtrl::SetObjectPath(const VARIANT FAR& varObjectPath)
{
BOOL bDelayToolbarUpdateT = m_bDelayToolbarUpdate;
m_bDelayToolbarUpdate = TRUE;
if (!::IsWindow(m_hWnd)) {
m_varObjectPath = varObjectPath;
return;
}
if (!m_pview->DidCreateWindow()) {
return;
}
m_bEmptyContainer = ::IsEmptyString(varObjectPath.bstrVal);
m_pViewStack->UpdateView();
ShowMultiView(FALSE, FALSE);
JumpToObjectPath(varObjectPath.bstrVal, TRUE);
m_bDelayToolbarUpdate = bDelayToolbarUpdateT;
if (!m_bDelayToolbarUpdate) {
m_pTitleBar->Refresh();
}
}
VARIANT CWBEMViewContainerCtrl::GetObjectPath()
{
CSingleView* psv = m_pview->GetSingleView();
long lPos;
lPos = psv->StartObjectEnumeration(OBJECT_CURRENT);
if (lPos >= 0) {
m_varObjectPath = psv->GetObjectPath(lPos);
}
return m_varObjectPath;
}
void CWBEMViewContainerCtrl::Clear(BOOL bRedrawWindow)
{
m_bDeadObject = FALSE; // An object is dead when a user chooses not to save it
if (m_pTitleBar != NULL) {
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, FALSE);
m_pTitleBar->EnableButton(ID_CMD_FILTERS, FALSE);
}
m_bObjectIsNewlyCreated = FALSE;
m_sNewInstClassPath.Empty();
if (m_hWnd != NULL) {
m_pview->RefreshView();
SetModifiedFlag(FALSE);
RedrawWindow();
}
else {
SetModifiedFlag(FALSE);
}
}
//**************************************************************
// CWBEMViewContainerCtrl::UpdateCreateDeleteButtonState
//
// Update the "enabled" state of the create and delete buttons to
// reflect the state of the underlying data and selection state.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//**************************************************************
void CWBEMViewContainerCtrl::UpdateCreateDeleteButtonState()
{
if (m_hWnd == NULL || m_pTitleBar==NULL) {
return;
}
BOOL bCanCreateInstance = FALSE;
BOOL bCanDeleteInstance = FALSE;
if (InStudioMode()) {
CSingleView* psv = m_pview->GetSingleView();
bCanCreateInstance = psv->QueryCanCreateInstance();
bCanDeleteInstance = m_pview->QueryCanDeleteInstance();
}
m_pTitleBar->EnableButton(ID_CMD_CREATE_INSTANCE, bCanCreateInstance);
m_pTitleBar->EnableButton(ID_CMD_DELETE_INSTANCE, bCanDeleteInstance);
}
//***********************************************************
// CWBEMViewContainerCtrl::ShowMultiView
//
// Switch to either the multiple instance view or to the current
// single object view depending on the parameter.
//
// Parameters:
// [in] BOOL bShowMultiView
// TRUE to select the MultiView, otherwise FALSE
//
// [in] BOOL bAddToHistory
// TRUE to add any view change to the view history.
//
//
// Returns:
// TRUE if the view switch was OK, FALSE if the user aborted the
// view switch by cancelling a data save, etc.
//
//***********************************************************
BOOL CWBEMViewContainerCtrl::ShowMultiView(BOOL bShowMultiView, BOOL bAddToHistory)
{
if (!::IsWindow(m_hWnd)) {
return FALSE;
}
BOOL bWasShowingMultiView = m_pview->IsShowingMultiview();
if (IsBoolEqual(bShowMultiView, bWasShowingMultiView)) {
// The view is the same, but we may want to add it to the history.
if (bAddToHistory) {
m_pViewStack->PushView();
}
return TRUE;
}
// Show the desired view.
if (bShowMultiView) {
m_pview->ShowMultiView();
}
else {
// If we are flipping from the multiview to an instance, we should check to
// see if the currently selected instance in the multiview matches the
// currently selected instance in the singleview, if not then use the
// path for the currently selected instance in the multiview to select an
// instance in the singleview.
CSingleView* psv = m_pview->GetSingleView();
CMultiView* pmv = m_pview->GetMultiView();
BOOL bIsShowingInstance = psv->IsShowingInstance();
if (!bIsShowingInstance) {
CString sPathSingleview;
SCODE sc = psv->GetCurrentObjectPath(sPathSingleview);
if (!m_bObjectIsNewlyCreated && sPathSingleview.IsEmpty()) {
CString sPathMultiview;
sc = pmv->GetCurrentObjectPath(sPathMultiview);
if (SUCCEEDED(sc)) {
psv->SelectObjectByPath(sPathMultiview);
m_pViewStack->UpdateView();
}
}
}
m_pview->ShowSingleView();
}
BOOL bIsShowingMultiView = m_pview->IsShowingMultiview();
BOOL bDidSwitchView = !IsBoolEqual(bWasShowingMultiView, bIsShowingMultiView);
// If the view was switched, update the toolbar, etc.
if (bDidSwitchView) {
if (bAddToHistory) {
m_pViewStack->PushView();
}
UpdateWindow();
}
return TRUE;
}
//******************************************************************
// CWBEMViewContainerCtrl::JumpToObjectPathFromMultiview
//
//
// Parameters:
// LPCTSTR szPath
// The HMOM object path.
//
// BOOL bSetMultiviewClass
// TRUE to change the class of the instances displayed in
// the multiview.
//
// BOOL bAddToHistory
// TRUE to add this jump to the view history.
//
// Returns:
// SCODE
// S_OK if the jump was completed, a failure code otherwise.
//
//******************************************************************
SCODE CWBEMViewContainerCtrl::JumpToObjectPathFromMultiview(LPCTSTR szPath, BOOL bSetMultiviewClass, BOOL bAddToHistory)
{
SCODE sc;
m_pViewStack->UpdateView();
CBSTR bsPath(szPath);
sc = JumpToObjectPath((BSTR) bsPath, bSetMultiviewClass, bAddToHistory);
if (FAILED(sc)) {
ShowMultiView(TRUE, FALSE);
}
return sc;
}
//******************************************************************
// CWBEMViewContainerCtrl::JumpToObjectPath
//
//
// Parameters:
// BSTR bstrObjectPath
// The HMOM object path.
//
// BOOL bSetMultiviewClass
// TRUE to change the class of the instances displayed in
// the multiview.
//
// BOOL bAddToHistory
// TRUE to add this jump to the view history.
//
// Returns:
// SCODE
// S_OK if the jump was completed, a failure code otherwise.
//
//******************************************************************
SCODE CWBEMViewContainerCtrl::JumpToObjectPath(BSTR bstrObjectPath, BOOL bSetMultiviewClass, BOOL bAddToHistory)
{
SCODE sc;
CString sCurPath;
CSingleView* psv = m_pview->GetSingleView();
long lPos = psv->StartObjectEnumeration(OBJECT_CURRENT);
if (lPos != -1) {
sCurPath = psv->GetObjectPath(lPos);
CBSTR bsCurPath(sCurPath);
if (IsEqualNoCase(bstrObjectPath, (BSTR) bsCurPath)) {
bAddToHistory = FALSE;
}
}
// First check to see if there are any changes and, if so,
// ask the user whether or not he or she wants to save them.
if (!m_bDeadObject) { // An object is dead when a user chooses not to save it
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
return sc;
}
}
sCurPath = bstrObjectPath;
sc = psv->SelectObjectByPath(sCurPath);
if (FAILED(sc)) {
return sc;
}
if (bSetMultiviewClass) {
CMultiView* pmv = m_pview->GetMultiView();
if (::IsEmptyString(bstrObjectPath)) {
pmv->ViewClassInstances((LPCTSTR) "");
}
else {
COleVariant varClass;
sc = ClassFromPath(varClass, bstrObjectPath);
if (SUCCEEDED(sc)) {
CString sClass;
sClass = varClass.bstrVal;
pmv->ViewClassInstances((LPCTSTR) sClass);
}
}
}
m_varObjectPath = bstrObjectPath;
if (bAddToHistory) {
if (*bstrObjectPath != 0) {
m_pViewStack->PushView();
}
}
ShowMultiView(FALSE, FALSE);
UpdateToolbar();
m_bDeadObject = FALSE;
return S_OK;
}
//********************************************************
// CWBEMViewContainerCtrl::OnSize
//
// Handle the WM_SIZE message. This is the main window for
// the control and thus the child windows of this control
// must be resized accordingly.
//
// Parameters:
// See the MFC documentation for OnSize.
//
// Returns:
// Nothing.
//
//*********************************************************
void CWBEMViewContainerCtrl::OnSize(UINT nType, int cx, int cy)
{
COleControl::OnSize(nType, cx, cy);
// If the window size is one pixel or less, IExplore locks up
// if we resize the child windows.
CRect rcView;
CalcViewRect(rcView);
if (!rcView.IsRectEmpty()) {
m_pview->MoveWindow(rcView);
}
if (m_pTitleBar && m_pTitleBar->m_hWnd) {
CRect rcTitle;
CalcTitleRect(rcTitle);
if (!rcTitle.IsRectEmpty()) {
m_pTitleBar->MoveWindow(rcTitle);
}
}
}
//**************************************************************
// CWBEMViewContainerCtrl::SaveState
//
// Save the sate of the generic view.
//
// Parameters:
// [in] long bPromptUser
// TRUE if the user should be prompted as to whether or
// not the state should be saved.
//
// [in] long bUserCanCancel
//
//
// Returns:
// SCODE
// S_OK if the state was saved, WBEM_S_FALSE if the user chose not to
// save the object, and WBEM_S E_FAIL if something went
// wrong or if the user canceled the save.
//
//**************************************************************
long CWBEMViewContainerCtrl::SaveState(long bPromptUser, long bUserCanCancel)
{
UINT nType = bUserCanCancel ? MB_YESNOCANCEL : MB_YESNO;
long lResult;
lResult = PublicSaveState(bPromptUser, nType);
return lResult;
}
long CWBEMViewContainerCtrl::PublicSaveState(BOOL bPromptUser, UINT nType)
{
ASSERT((nType == MB_YESNOCANCEL) || (nType == MB_YESNO) || (nType == MB_OKCANCEL));
// If the current object is not modified, there is nothing to do.
CSingleView* psv = m_pview->GetSingleView();
BOOL bNeedsSave = psv->QueryNeedsSave();
if (!bNeedsSave) {
// Control should never come here.
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, FALSE);
return S_OK;
}
if (bPromptUser) {
// Ask the user if a save should be done.
CString sFormat;
sFormat.LoadString(IDS_QUERY_SAVE_CHANGES);
CString sTitle;
sTitle = m_pview->GetObjectTitle(OBJECT_CURRENT);
_stprintf(m_szMessageBuffer, (LPCTSTR) sFormat, (LPCTSTR) sTitle);
nType |= MB_SETFOREGROUND;
int iPromptResult = HmmvMessageBox(this, m_szMessageBuffer, nType);
UpdateWindow();
CBSTR bsEmptyPath(_T(""));
CString sPath;
switch(iPromptResult) {
case IDYES:
break;
case IDNO:
// When an object save is canceled, the user is switching
// to a different object and the current version of the
// object must be discarded in the event that the user
// clicks the "go back" button or flips back to the
// singleview from the multiview.
if (m_pview->IsShowingSingleview()) {
m_bSingleViewNeedsRefresh = TRUE;
}
m_pViewStack->UpdateView();
m_bSingleViewNeedsRefresh = FALSE;
m_bDeadObject = TRUE; // An object is dead when a user chooses not to save it
// If the user says no to a save, discard the object.
m_pview->RefreshView(); // bug#55978
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, FALSE);// bug#55978
return WBEM_S_FALSE;
break;
case IDCANCEL:
return E_FAIL;
}
}
SCODE sc;
sc = m_pview->SaveData();
if (FAILED(sc)) {
return sc;
}
// After a successful save, it is necessary to update the
// multiple instance view so that it shows the current property
// values for the object. This is done by telling the multiview
// that the object has been deleted and then created.
CString sObjectPath;
CMultiView* pmv = m_pview->GetMultiView();
sc = psv->GetCurrentObjectPath(sObjectPath);
if (SUCCEEDED(sc)) {
pmv->ExternInstanceDeleted(sObjectPath);
pmv->ExternInstanceCreated(sObjectPath);
}
m_bObjectIsNewlyCreated = FALSE;
m_sNewInstClassPath.Empty();
// m_notify.SendEvent(NOTIFY_OBJECT_SAVE_SUCCESSFUL);
UpdateToolbar();
m_pViewStack->UpdateView();
return S_OK;
}
void CWBEMViewContainerCtrl::UpdateToolbar()
{
if (!m_bDelayToolbarUpdate) {
BOOL bNeedsSave = m_pview->QueryNeedsSave();
SetModifiedFlag(bNeedsSave);
m_pTitleBar->Refresh();
}
}
void CWBEMViewContainerCtrl::NotifyDataChange()
{
BOOL bNeedsSave = m_pview->QueryNeedsSave();
SetModifiedFlag(bNeedsSave);
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, bNeedsSave);
}
int CWBEMViewContainerCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
if (m_hWnd) {
CRect rcTitleBar;
rcTitleBar.SetRectEmpty();
m_pTitleBar->Create(this, WS_VISIBLE | WS_CHILD, rcTitleBar, GenerateWindowID());
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, FALSE);
m_pTitleBar->CheckButton(ID_CMD_SWITCH_VIEW, FALSE);
}
CRect rcView;
CalcViewRect(rcView);
BOOL bDidCreate;
bDidCreate = m_pview->Create(rcView);
if (!bDidCreate) {
return FALSE;
}
m_pview->SetFont(m_font);
ShowMultiView(FALSE, FALSE);
if (!m_sNameSpace.IsEmpty()) {
m_pview->SetNamespace(m_sNameSpace);
}
CString sPath;
sPath = m_varObjectPath.bstrVal;
if (!sPath.IsEmpty()) {
JumpToObjectPath(m_varObjectPath.bstrVal, TRUE);
}
m_pTitleBar->EnableButton(ID_CMD_CONTEXT_FORWARD, FALSE);
m_pTitleBar->EnableButton(ID_CMD_CONTEXT_BACK, FALSE);
m_pTitleBar->EnableButton(ID_CMD_CREATE_INSTANCE, FALSE);
m_pTitleBar->EnableButton(ID_CMD_DELETE_INSTANCE, FALSE);
m_pTitleBar->EnableButton(ID_CMD_FILTERS, FALSE);
m_pTitleBar->EnableButton(ID_CMD_SWITCH_VIEW, FALSE);
m_pTitleBar->EnableButton(ID_CMD_QUERY, FALSE);
m_pview->SetEditMode(m_bInStudioMode);
m_bCreationFinished = TRUE;
return 0;
}
void CWBEMViewContainerCtrl::OnDestroy()
{
delete m_pViewStack;
delete m_pview;
delete m_pTitleBar;
delete m_pdlgHelpBox;
m_pViewStack = NULL;
m_pview = NULL;
m_pTitleBar = NULL;
COleControl::OnDestroy();
}
//************************************************************
// CWBEMViewContainerCtrl::MultiViewButtonClicked
//
// This method is called when the multiple-instance view button
// is clicked. When this occurs, switch to the multiple instance
// view.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//*************************************************************
void CWBEMViewContainerCtrl::MultiViewButtonClicked()
{
CWaitCursor wait;
BOOL bSwitchViewChecked = m_pTitleBar->IsButtonChecked(ID_CMD_SWITCH_VIEW);
BOOL bWasShowingSingleView = m_pview->IsShowingSingleview();
BOOL bWasNewlyCreatedInst = FALSE;
CString sClassPath;
CSingleView* psv = m_pview->GetSingleView();
SCODE sc = S_OK;
if (m_pview->IsShowingSingleview()) {
// Save the state only if we are flipping from the
// singleview to the multiview. This prevents a
// the save from being done when a new object is
// pre-selected into the singleview prior to displaying
// it so that things appear quickly.
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
m_pTitleBar->CheckButton(ID_CMD_SWITCH_VIEW, FALSE);
return;
}
else if (sc == WBEM_S_FALSE) {
// The user chose not to save changes when flipping to the
// multiview. This means that we need to reselect the
// current path into the singleview so that we revert back
// to the initial state of the object.
CString sObjectPath;
sObjectPath = m_varObjectPath.bstrVal;
psv->SelectObjectByPath(sObjectPath);
}
if (m_bObjectIsNewlyCreated) {
bWasNewlyCreatedInst = TRUE;
sClassPath = m_sNewInstClassPath;
}
}
ShowMultiView(bSwitchViewChecked, FALSE);
if (bWasShowingSingleView && bWasNewlyCreatedInst) {
if (sc == WBEM_S_FALSE && !sClassPath.IsEmpty()) {
// The user chose not to save the newly created instance, so
// we need to select the class so that when the user sees the
// multiview, the create instance button will be enabled
// if appropriate.
psv->SelectObjectByPath(m_sNewInstClassPath);
m_pViewStack->UpdateView();
m_bObjectIsNewlyCreated = FALSE;
m_sNewInstClassPath.Empty();
}
}
else {
m_pViewStack->PushView();
}
m_pTitleBar->Refresh();
UpdateWindow();
return;
}
//**************************************************************
// CWBEMViewContainerCtrl::ShowInstances
//
// This is the automation interface for specifying a set of instances
// to view. Call this interface to select the multiple instance view
// and load it with a set of instances.
//
// Parameters:
// [in] LPCTSTR pszTitle
// The view title.
//
// const VARIANT FAR& varPathArray
// An variant array containing the HMOM paths to the instances.
//
// Returns:
// Nothing.
//
//****************************************************************
void CWBEMViewContainerCtrl::ShowInstances(LPCTSTR pszTitle, const VARIANT FAR& varPathArray)
{
m_bEmptyContainer = FALSE;
CMultiView* pmv = m_pview->GetMultiView();
try
{
// TODO: Add your dispatch handler code here
if (pmv == NULL) {
// If the multi-view control isn't available, there is nothing
// that can be done here.
ASSERT(FALSE);
}
// Show the MultiView
CWaitCursor wait;
pmv->ViewInstances(pszTitle, varPathArray);
m_pview->ShowMultiView();
if (m_bInStudioMode) {
m_pTitleBar->EnableButton(ID_CMD_SWITCH_VIEW, FALSE);
// We are switching to the multiple instance view, so set the button
// check state to appear as if it is pressed.
m_pTitleBar->CheckButton(ID_CMD_SWITCH_VIEW, TRUE);
}
m_pTitleBar->EnableButton(ID_CMD_FILTERS, FALSE);
m_pTitleBar->NotifyObjectChanged();
m_pview->RedrawWindow();
InvalidateControl();
m_pViewStack->PushView();
}
catch(CException* )
{
}
}
//********************************************************************
// CWBEMViewContainerCtrl::QueryViewInstances
//
//
// Parameters:
// LPCTSTR pszLabel
//
// LPCTSTR pszQueryType
//
// LPCTSTR pszQuery
//
// LPCTSTR pszClass
//
// Returns:
// Nothing.
//
//********************************************************************
void CWBEMViewContainerCtrl::QueryViewInstances(
LPCTSTR pszLabel,
LPCTSTR pszQueryType,
LPCTSTR pszQuery,
LPCTSTR pszClass)
{
try
{
CMultiView* pmv = m_pview->GetMultiView();
if (pmv == NULL || pmv->m_hWnd==NULL) {
// If the multi-view control isn't available, there is nothing
// that can be done here.
ASSERT(FALSE);
}
m_pViewStack->UpdateView();
// First check to see if there are any changes and, if so,
// ask the user whether or not he or she wants to save them.
SCODE sc;
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
return;
}
if (m_pview->IsShowingSingleview() && (sc == WBEM_S_FALSE)) {
m_pview->GetSingleView()->SelectObjectByPath(_T(""));
}
CWaitCursor wait;
COleVariant varTitle;
varTitle = pszLabel;
ASSERT(varTitle.vt == VT_BSTR);
pmv->QueryViewInstances(pszLabel, pszQueryType, pszQuery, pszClass);
m_pview->ShowMultiView();
if (m_bInStudioMode) {
m_pTitleBar->EnableButton(ID_CMD_SWITCH_VIEW, FALSE);
// We are switching to the multiple instance view, so set the button
// check state to appear as if it is pressed.
m_pTitleBar->CheckButton(ID_CMD_SWITCH_VIEW, TRUE);
}
else {
CSingleView* psv = m_pview->GetSingleView();
psv->SelectObjectByPath(_T(""));
}
m_pTitleBar->EnableButton(ID_CMD_FILTERS, FALSE);
m_pTitleBar->NotifyObjectChanged();
// Somehow the singleview is becoming visible when it shouldn't, so show the
// multiview again.
m_pview->ShowMultiView();
// InvalidateControl();
}
catch(CException* )
{
}
}
#if 0
// Disable global context menu per bug #4222
//***************************************************************
// CWBEMViewContainerCtrl::OnContextMenu
//
// This method displays the context menu. It is called from
// PretranslateMessage.
//
// Parameters:
// CWnd* pwnd
// Pointer to the window that the event that triggered the
// menu occurred in.
//
// CPoint ptScreen
// The point, in screen coordinates, where the context menu
// should be displayed.
//
// Returns:
// Nothing.
//
//*****************************************************************
void CWBEMViewContainerCtrl::OnContextMenu(CWnd* pwnd, CPoint ptScreen)
{
// CG: This function was added by the Pop-up Menu component
CPoint ptClient = ptScreen;
ScreenToClient(&ptClient);
// If the mouse was right-clicked outside the client rectangle do nothing.
CRect rcClient;
GetClientRect(rcClient);
if (!rcClient.PtInRect(ptClient)) {
return;
}
// If the mouse was right-clicked over the toolbar buttons, do nothing.
CRect rcTools;
m_pTitleBar->GetToolBarRect(rcTools);
m_pTitleBar->ClientToScreen(rcTools);
if (rcTools.PtInRect(ptScreen)) {
return;
}
CMenu menu;
VERIFY(menu.LoadMenu(CG_IDR_POPUP_HMMV_CTRL));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
pPopup->EnableMenuItem(ID_CMD_SHOW_OBJECT_ATTRIBUTES, MF_ENABLED);
CWnd* pWndPopupOwner = this;
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y,
pWndPopupOwner);
}
BOOL CWBEMViewContainerCtrl::PreTranslateMessage(MSG* pMsg)
{
BOOL bInvokeContextMenu = FALSE;
// Shift+F10: show pop-up menu.
switch(pMsg->message) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
switch(pMsg->wParam) {
case VK_F10:
if ((GetKeyState(VK_SHIFT) & ~1) != 0) {
bInvokeContextMenu = TRUE;
}
break;
case VK_TAB:
// When you see the tab key in your control's pretranslate
// message you know that IE is telling you to go ui active
// and allowing you to give your control focus because the
// user just tabbed into your control. A vb form
// behaves the same way.
SetFocus();
break;
}
break;
case WM_CONTEXTMENU:
bInvokeContextMenu = TRUE;
break;
}
if (bInvokeContextMenu) {
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
CPoint point = rect.TopLeft();
point.Offset(5, 5);
OnContextMenu(NULL, point);
return TRUE;
}
return COleControl::PreTranslateMessage(pMsg);
}
// End of context menu disabling
#endif //0
void CWBEMViewContainerCtrl::OnCmdShowObjectAttributes()
{
ASSERT(FALSE);
// ShowObjectAttributes();
}
void CWBEMViewContainerCtrl::OnStatusCodeChanged()
{
// TODO: Add notification handler code
SetModifiedFlag();
}
BSTR CWBEMViewContainerCtrl::GetNameSpace()
{
return m_sNameSpace.AllocSysString();
}
void CWBEMViewContainerCtrl::SetNameSpace(LPCTSTR lpszNameSpace)
{
//return; // VBSCRIPT_ERROR
BOOL bDelayToolbarUpdateSave = m_bDelayToolbarUpdate;
m_bDelayToolbarUpdate = TRUE;
m_sNameSpace = lpszNameSpace;
if (!::IsWindow(m_hWnd)) {
return;
}
if (!m_bEmptyContainer) {
m_pViewStack->PushView();
}
delete m_pViewStack;
m_pViewStack = new CViewStack(this);
CDisableViewStack DisableViewStack(m_pViewStack);
m_pview->SetNamespace(lpszNameSpace);
m_varObjectPath = "";
m_bEmptyContainer = TRUE;
ShowMultiView(FALSE, FALSE);
m_pTitleBar->Refresh();
m_bDelayToolbarUpdate = bDelayToolbarUpdateSave;
}
void CWBEMViewContainerCtrl::InvalidateControlRect(CRect* prc)
{
InvalidateControl(prc);
}
DWORD CWBEMViewContainerCtrl::GetActivationPolicy( )
{
return POINTERINACTIVE_ACTIVATEONENTRY |
POINTERINACTIVE_DEACTIVATEONLEAVE |
POINTERINACTIVE_ACTIVATEONDRAG;
}
//***********************************************************
// CWBEMViewContainerCtrl::GetCurrentClass
//
// Get a path to the current class. This is used when
// we need to know what the class is when creating a
// new instance.
//
// Parameters:
// COleVariant& varClass
//
// Returns:
// SCODE
// S_OK if successful, E_FAIL if there is no current class.
//
//**************************************************************
SCODE CWBEMViewContainerCtrl::GetCurrentClass(COleVariant& varClass)
{
CString sPath = m_pview->GetObjectPath(OBJECT_CURRENT);
if (sPath.IsEmpty()) {
return E_FAIL;
}
CBSTR bsPath(sPath);
BSTR bstrPath = (BSTR) bsPath;
SCODE sc = ClassFromPath(varClass, bstrPath);
return sc;
}
//************************************************************
// CWBEMViewContainerCtrl::CreateInstance
//
// Create an instance of the current class.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//*************************************************************
void CWBEMViewContainerCtrl::CreateInstance()
{
if (!InStudioMode()) {
ASSERT(FALSE); // Control should never come here.
return;
}
SCODE sc;
// Save the state of the current object before attempting to
// create a new one. Do nothing if the user cancels the save.
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
return;
}
CSingleView* psv = m_pview->GetSingleView();
BOOL bCanCreateInstance = psv->QueryCanCreateInstance();
if (!bCanCreateInstance) {
ASSERT(FALSE);
return;
}
// When an instance is created, the multiple instance and the custom
// view should be notified so that they can display the correct information.
//
// Maybe I should set a flag to indicate whether or not the new instance
// needs to be passed to the multiple instance view or custom view when
// switching views.
CString sClassPathSave;
sClassPathSave = m_sNewInstClassPath;
sc = psv->GetClassPath(m_sNewInstClassPath);
ASSERT(SUCCEEDED(sc));
sc = psv->CreateInstance(m_sNewInstClassPath);
if (SUCCEEDED(sc)) {
// !!!CR: We need to notify the multiple instance view when
// !!!CR: a new instance has been created, but since the
// !!!CR: instance hasn't been written to the database yet
// !!!CR: there is nothing to notify them of yet.
m_bObjectIsNewlyCreated = TRUE;
ShowMultiView(FALSE, FALSE);
SetModifiedFlag(TRUE);
m_pTitleBar->EnableButton(ID_CMD_SAVE_DATA, TRUE);
m_pTitleBar->Refresh();
UpdateCreateDeleteButtonState();
m_pViewStack->PushView();
}
else {
m_sNewInstClassPath = sClassPathSave;
}
psv->SetFocus();
UpdateWindow();
}
//****************************************************************
// CWBEMViewContainerCtrl::DeleteInstance
//
// Delete the currently selected instance amd coordinate the deletion with
// the child views.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//****************************************************************
void CWBEMViewContainerCtrl::DeleteInstance()
{
if (!InStudioMode()) {
ASSERT(FALSE); // Control should never come here.
return;
}
CMultiView* pmv = m_pview->GetMultiView();
CSingleView* psv = m_pview->GetSingleView();
SCODE sc;
CString sClassPath;
sc = psv->GetClassPath(sClassPath);
if (FAILED(sc)) {
sClassPath.Empty();
}
long lPos;
lPos = pmv->StartObjectEnumeration(OBJECT_CURRENT);
CString sPath;
sPath = m_pview->GetObjectPath(lPos);
CString sTitle;
sTitle = m_pview->GetObjectTitle(lPos);
// Prompt the user to verify that it is OK to delete the
// current object.
CString sFormat;
sFormat.LoadString(IDS_QUERY_DELETE_OBJECT);
CString sCaption;
if (::PathIsClass(sPath)) {
sCaption = _T("Deleting a Class");
}
else {
sCaption = _T("Deleting an Instance");
}
_stprintf(m_szMessageBuffer, (LPCTSTR) sFormat, (LPCTSTR) sTitle);
PreModalDialog( );
CWnd* pwndFocus = GetFocus();
int iMsgBoxStatus = ::MessageBox(m_hWnd, m_szMessageBuffer, (LPCTSTR) _T("Deleting an Instance"), MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION);
if (pwndFocus && ::IsWindow(pwndFocus->m_hWnd)) {
pwndFocus->SetFocus();
}
PostModalDialog();
UpdateWindow();
if (iMsgBoxStatus != IDYES) {
return;
}
sc = m_pview->DeleteInstance();
if (FAILED(sc)) {
return;
}
BOOL bDeletedCurrentView = m_pViewStack->PurgeView(sPath);
// Get the current view's concept of the currently selected instance.
// It may be the case that the current view doesn't have any instance
// selected - for example, a class might be selected.
//
// Note that when switching to a view, the single container should enable
// or disable the "delete instance" button depending on whether or not
// that view has a selected instance to delete.
//
// Views should notify the container when the current selection
// changes.
if (bDeletedCurrentView) {
m_pViewStack->RefreshView();
}
else {
if (!m_pview->IsShowingMultiview()) {
if (m_bObjectIsNewlyCreated) {
if (m_pViewStack->CanGoBack()) {
Clear(FALSE);
m_pViewStack->GoBack();
}
else {
Clear();
}
m_pViewStack->TrimStack();
return;
}
}
}
if (SUCCEEDED(sc)) {
// NotifyInstanceDeleted does not work, so instead we just tell
// the multiview control to refresh all of its data.
COleVariant varObjectPath;
varObjectPath = sPath;
NotifyInstanceDeleted(varObjectPath);
if (m_pview->IsShowingMultiview()) {
CSingleView* psv = m_pview->GetSingleView();
sPath = m_pview->GetObjectPath(OBJECT_CURRENT);
psv->SelectObjectByPath(sPath);
m_pViewStack->UpdateView();
}
else {
if (m_pViewStack->CanGoBack()) {
Clear(FALSE);
m_pViewStack->GoBack();
}
else {
Clear();
}
m_pViewStack->TrimStack();
}
}
if (m_pview->IsShowingMultiview()) {
long lPos = pmv->StartObjectEnumeration(OBJECT_FIRST);
if (lPos < 0 && !sClassPath.IsEmpty()) {
// The multiview is empty because we deleted the last item.
// We need to select the class into the singleview so that
// we can still create an instance.
psv->SelectObjectByPath(sClassPath);
ShowMultiView(TRUE, FALSE);
m_pViewStack->UpdateView();
}
}
UpdateToolbar();
}
//*****************************************************************************
// CWBEMViewContainerCtrl::NotifyContainerOfSelectionChange
//
// This method is called when the selection is changed in one of the child views
// and the child view fires this event.
//
// This method is necessary to allow the container to enable or disable the
// "delete instance" button.
//
// Parameters:
// int idView
// The view id so that the container knows whether or not the selection
// changed in the currently active view.
//
// Returns:
// Nothing.
//
//*****************************************************************************
void CWBEMViewContainerCtrl::NotifyContainerOfSelectionChange()
{
}
SCODE CWBEMViewContainerCtrl::ContextForward()
{
if (m_pViewStack->CanGoForward()) {
m_pViewStack->GoForward();
return S_OK;
}
else {
return E_FAIL;
}
}
SCODE CWBEMViewContainerCtrl::ContextBack()
{
if (m_pViewStack->CanGoBack()) {
BOOL bObjectWasNewlyCreated = m_bObjectIsNewlyCreated;
m_pViewStack->GoBack();
if (bObjectWasNewlyCreated) {
// If the object was newly created and the user opted not
// to save it, trim the context stack so that the user
// can't attempt to go back to the object that was discarded.
m_pViewStack->TrimStack();
}
return S_OK;
}
else {
return E_FAIL;
}
}
//***********************************************************************
// CWBEMViewContainerCtrl::QueryCanContextForward
//
// Check to see if it is OK to go forward a step on the view context stack.
// If the current object is modified, an attempt is made to save its state
// before approving the change in view context.
//
// Parameters:
// None.
//
// Returns:
// BOOL
// TRUE if it is OK to go forward to the "next" entry on the view
// stack. FALSE if there is no next entry or the user cancels saving
// the current object if it was modified.
//
//
//************************************************************************
BOOL CWBEMViewContainerCtrl::QueryCanContextForward()
{
SCODE sc;
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
// The user canceled the save, so abort the change of view context.
return FALSE;
}
return m_pViewStack->CanGoForward();
}
//***********************************************************************
// CWBEMViewContainerCtrl::QueryCanContextBack
//
// Check to see if it is OK to go back a step on the view context stack.
// If the current object is modified, an attempt is made to save its state
// before approving the change in view context.
//
// Parameters:
// None.
//
// Returns:
// BOOL
// TRUE if it is OK to go back to the "previous" entry on the view
// stack. FALSE if there is no next entry or the user cancels saving
// the current object if it was modified.
//
//
//************************************************************************
BOOL CWBEMViewContainerCtrl::QueryCanContextBack()
{
SCODE sc;
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
// The user canceled the save, so abort the change of view context.
return FALSE;
}
return m_pViewStack->CanGoBack();
}
long CWBEMViewContainerCtrl::GetStudioModeEnabled()
{
// TODO: Add your property handler here
return m_bInStudioMode;
}
void CWBEMViewContainerCtrl::SetStudioModeEnabled(long bInStudioMode)
{
// SetNotSupported
BOOL bWasInStudioMode = m_bInStudioMode;
m_bInStudioMode = bInStudioMode;
if ((bInStudioMode && !bWasInStudioMode) || (!bInStudioMode && bWasInStudioMode)) {
delete m_pViewStack;
m_pViewStack = new CViewStack(this);
delete m_pview;
m_pview = new CPolyView(this);
m_pview->SetStudioModeEnabled(bInStudioMode);
CRect rcView;
CalcViewRect(rcView);
BOOL bDidCreate;
bDidCreate = m_pview->Create(rcView);
if (!bDidCreate) {
InvalidateControl(); // Must do this!
return;
}
m_pview->SetFont(m_font);
ShowMultiView(FALSE, FALSE);
if (!m_sNameSpace.IsEmpty()) {
m_pview->SetNamespace(m_sNameSpace);
}
if (::IsWindow(m_pTitleBar->m_hWnd)) {
m_pTitleBar->LoadToolBar();
}
}
SetModifiedFlag();
InvalidateControl(); // Must do this!
}
void CWBEMViewContainerCtrl::GetContainerContext(CContainerContext& ctx)
{
ctx.m_bIsShowingMultiView = m_pview->IsShowingMultiview();
ctx.m_bObjectIsNewlyCreated = m_bObjectIsNewlyCreated;
ctx.m_bEmptyContainer = m_bEmptyContainer;
ctx.m_hwndFocus = ::GetFocus();
}
//***********************************************************
// CWBEMViewContainerCtrl::SetContainerContextPrologue
//
// This method is called to begin the restoration of the
// container's view context. It is the first call that is
// made to restore the context.
//
// Parameters:
// [in] CContainerContext& ctx
// The container context that was saved previously.
//
// Returns:
// SCODE
// S_OK if successful, E_FAIL if there was an attempt to
// restore the container to an invalid state. When E_FAIL
// is returned, the CViewStack will remove this context entry
// from the stack.
//
//************************************************************
SCODE CWBEMViewContainerCtrl::SetContainerContextPrologue(CContainerContext& ctx)
{
return S_OK;
}
//***********************************************************
// CWBEMViewContainerCtrl::SetContainerContextEpilogue
//
// This method is called to complete the restoration of the
// container's view context. It is called after SetContainerPrologue
// and the context for the generic view and multiview have been
// restored.
//
// Parameters:
// [in] CContainerContext& ctx
// The container context that was saved previously.
//
// Returns:
// SCODE
// S_OK if successful, E_FAIL if there was an attempt to
// restore the container to an invalid state. When E_FAIL
// is returned, the CViewStack will remove this context entry
// from the stack.
//
//************************************************************
SCODE CWBEMViewContainerCtrl::SetContainerContextEpilogue(CContainerContext& ctx)
{
m_bObjectIsNewlyCreated = ctx.m_bObjectIsNewlyCreated;
m_bEmptyContainer = ctx.m_bEmptyContainer;
m_pTitleBar->Refresh();
if (::IsWindow(ctx.m_hwndFocus) && ::IsWindowVisible(ctx.m_hwndFocus)) {
::SetFocus(ctx.m_hwndFocus);
}
return S_OK;
}
void CWBEMViewContainerCtrl::PushView()
{
m_pViewStack->PushView();
}
void CWBEMViewContainerCtrl::UpdateViewContext()
{
m_pViewStack->UpdateView();
}
DWORD CWBEMViewContainerCtrl::GetControlFlags( )
{
return clipPaintDC;
}
//************************************************************
// CWBEMViewContainerCtrl::SelectView
//
// Select a sub-view.
//
// Parameters:
// long lView
// The view position returned from the view enumerator.
//
// Returns:
// Nothing.
//
//************************************************************
void CWBEMViewContainerCtrl::SelectView(long lPosition)
{
SCODE sc;
long lPositionCurrent = m_pview->StartViewEnumeration(VIEW_CURRENT);
if (lPosition == lPositionCurrent) {
return;
}
sc = m_pview->SelectView(lPosition);
ASSERT(SUCCEEDED(sc));
m_pViewStack->PushView();
UpdateWindow();
}
void CWBEMViewContainerCtrl::PassThroughGetIHmmServices
(LPCTSTR lpctstrNamespace, VARIANT FAR* pvarUpdatePointer, VARIANT FAR* pvarServices, VARIANT FAR* pvarSC, VARIANT FAR* pvarUserCancel)
{
// TODO: Add your dispatch handler code here
FireGetIWbemServices(lpctstrNamespace, pvarUpdatePointer, pvarServices, pvarSC, pvarUserCancel);
}
void CWBEMViewContainerCtrl::RequestUIActive()
{
// TODO: Add your control notification handler code here
if(m_bCreationFinished)
OnActivateInPlace(TRUE,NULL);
FireRequestUIActive();
}
void CWBEMViewContainerCtrl::OnSetFocus(CWnd* pOldWnd)
{
COleControl::OnSetFocus(pOldWnd);
// Next statements are only logic I need to know how to draw myself
// when I lose focus. Your logic may be more complicated.
// You want to activate yourself.
if (!m_bUIActive)
{
m_bUIActive = TRUE;
RequestUIActive();
}
InvalidateControl(); // Must do this!
}
void CWBEMViewContainerCtrl::OnKillFocus(CWnd* pNewWnd)
{
COleControl::OnKillFocus(pNewWnd);
// TODO: Add your message handler code here
// Next statements are only logic I need to know how to draw myself
// when I lose focus. Your logic may be more complicated.
// You want to deactivate yourself.
m_bUIActive = FALSE;
OnActivateInPlace(FALSE,NULL); // Must do this!
InvalidateControl();
}
//**********************************************************
// CWBEMViewContainerCtrl::InvokeHelp
//
// Invoke help for the currently selected object.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//**********************************************************
void CWBEMViewContainerCtrl::OnHelp()
{
COleVariant varObjectPath;
CString sObjectPath;
long lPos;
if (m_pview->IsShowingSingleview()) {
CSingleView* psv = m_pview->GetSingleView();
lPos = psv->StartObjectEnumeration(OBJECT_CURRENT);
if (lPos >= 0) {
varObjectPath = psv->GetObjectPath(lPos);
sObjectPath = varObjectPath.bstrVal;
}
else {
sObjectPath = m_varObjectPath.bstrVal;
}
}
else {
CMultiView* pmv = m_pview->GetMultiView();
lPos = pmv->StartObjectEnumeration(OBJECT_CURRENT);
if (lPos >= 0) {
varObjectPath = pmv->GetObjectPath(lPos);
sObjectPath = varObjectPath.bstrVal;
}
else {
sObjectPath = m_varObjectPath.bstrVal;
}
}
m_pdlgHelpBox->ShowHelpForClass(this, sObjectPath);
}
void CWBEMViewContainerCtrl::InvokeHelp()
{
OnHelp();
return;
}
BOOL CWBEMViewContainerCtrl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
dwStyle |= WS_CLIPCHILDREN;
return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
BOOL CWBEMViewContainerCtrl::OnEraseBkgnd(CDC* pDC)
{
CRect rcClient;
GetClientRect(rcClient);
CBrush br(GetSysColor(COLOR_3DFACE));
pDC->FillRect(rcClient, &br);
return TRUE;
// return COleControl::OnEraseBkgnd(pDC);
}
BOOL CWBEMViewContainerCtrl::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
switch(pMsg->message) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
switch(pMsg->wParam) {
case VK_TAB:
// When you see the tab key in your control's pretranslate
// message you know that IE is telling you to go ui active
// and allowing you to give your control focus because the
// user just tabbed into your control. A vb form
// behaves the same way.
SetFocus();
return FALSE;
break;
}
break;
}
BOOL bDidTranslate;
bDidTranslate = COleControl::PreTranslateMessage(pMsg);
if (bDidTranslate) {
return bDidTranslate;
}
// bug #51022 - Should call PreTranslateMessage, not PreTranslateInput
return COleControl::PreTranslateMessage (pMsg);
}
long CWBEMViewContainerCtrl::GetPropertyFilter()
{
return m_lPropFilters;
}
//**********************************************************
// CWBEMViewContainerCtrl::SetPropertyFilters
//
// Invoke help for the currently selected object.
//
// Parameters:
// [in] lPropFilters
// PROPFILTER_SYSTEM 1
// PROPFILTER_INHERITED 2
// PROPFILTER_LOCAL 4
//
//
// Returns:
// Nothing.
//
//**********************************************************
void CWBEMViewContainerCtrl::SetPropertyFilter(long nNewValue)
{
m_lPropFilters = nNewValue;
if (m_pview != NULL) {
m_pview->SetPropertyFilters(nNewValue);
}
}
CWnd* CWBEMViewContainerCtrl::ReestablishFocus()
{
if (m_pview != NULL) {
CWnd* pwndFocusPrev = m_pview->SetFocus();
return pwndFocusPrev;
}
return NULL;
}
void CWBEMViewContainerCtrl::GetWbemServices(LPCTSTR szNamespace, VARIANT FAR* pvarUpdatePointer, VARIANT FAR* pvarServices, VARIANT FAR* pvarSc, VARIANT FAR* pvarUserCancel)
{
FireGetIWbemServices(szNamespace, pvarUpdatePointer, pvarServices, pvarSc, pvarUserCancel);
}
//**********************************************************
// CWBEMViewContainerCtrl::Query
//
// Display query dialog and run query
//
//
//**********************************************************
void CWBEMViewContainerCtrl::Query() {
// Save the state of the current object before attempting to
// run the query.
CWaitCursor wait;
BOOL bSwitchViewChecked = m_pTitleBar->IsButtonChecked(ID_CMD_SWITCH_VIEW);
BOOL bWasShowingSingleView = m_pview->IsShowingSingleview();
BOOL bWasNewlyCreatedInst = FALSE;
CString sClassPath;
CSingleView* psv = m_pview->GetSingleView();
SCODE sc = S_OK;
if (m_pview->IsShowingSingleview()) {
// Save the state only if we are flipping from the
// singleview to the multiview. This prevents a
// the save from being done when a new object is
// pre-selected into the singleview prior to displaying
// it so that things appear quickly.
sc = SaveState(TRUE, TRUE);
if (FAILED(sc)) {
m_pTitleBar->CheckButton(ID_CMD_SWITCH_VIEW, FALSE);
return;
}
else if (sc == WBEM_S_FALSE) {
// The user chose not to save changes when flipping to the
// multiview. This means that we need to reselect the
// current path into the singleview so that we revert back
// to the initial state of the object.
CString sObjectPath;
sObjectPath = m_varObjectPath.bstrVal;
psv->SelectObjectByPath(sObjectPath);
}
if (m_bObjectIsNewlyCreated) {
bWasNewlyCreatedInst = TRUE;
sClassPath = m_sNewInstClassPath;
}
}
//Now, execute the query
CDlgExecQuery dlg(this);
int iResult = (int) dlg.DoModal();
if (iResult == IDOK) {
CMultiView* pmv = m_pview->GetMultiView();
pmv->QueryViewInstances(dlg.m_sQueryName, _T("WQL"), dlg.m_sQueryString, _T(""));
ShowMultiView(TRUE, TRUE);
}
if (bWasShowingSingleView && bWasNewlyCreatedInst) {
if (sc == WBEM_S_FALSE && !sClassPath.IsEmpty()) {
// The user chose not to save the newly created instance, so
// we need to select the class so that when the user sees the
// multiview, the create instance button will be enabled
// if appropriate.
psv->SelectObjectByPath(m_sNewInstClassPath);
m_pViewStack->UpdateView();
m_bObjectIsNewlyCreated = FALSE;
m_sNewInstClassPath.Empty();
}
}
else {
m_pViewStack->PushView();
}
m_pTitleBar->Refresh();
UpdateWindow();
}