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

1214 lines
27 KiB
C++

// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//***************************************************************************
//
// (c) 1996, 1997 by Microsoft Corporation
//
// ArrayGrid.cpp
//
// This file contains the implementation for the array grid that is
// displayed for cells containing arrays.
//
// a-larryf 08-May-97 Created.
//
//***************************************************************************
#include "precomp.h"
#include "globals.h"
#include "gc.h"
#include "gca.h"
#include "gridhdr.h"
#include "grid.h"
#include "resource.h"
#include "ArrayGrid.h"
#include "hmmverr.h"
#include "utils.h"
#include "DlgObjectEditor.h"
#define CX_COLUMN 200
BEGIN_MESSAGE_MAP(CArrayGrid, CGrid)
//{{AFX_MSG_MAP(CGrid)
ON_WM_CHAR()
//}}AFX_MSG_MAP
ON_COMMAND(ID_CMD_CREATE_VALUE, OnCmdCreateValue)
ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
CArrayGrid::CArrayGrid(BOOL bNumberRows)
{
m_psvc = NULL;
AddColumn(CX_COLUMN, _T("Value"));
m_bModified = FALSE;
NumberRows(bNumberRows, FALSE);
SetNullCellDrawMode(FALSE);
}
CArrayGrid::~CArrayGrid()
{
if (m_psvc != NULL) {
m_psvc->Release();
}
}
//************************************************************
// CArrayGrid::GetValueAt
//
// Copy a value from the safe array to the a variant.
//
// Parameters:
// SAFEARRAY* psa
// Pointer to the source SAFEARRAY containing the value.
//
// long lIndex
// The element's index.
//
// COleVariant& var
// The variant to copy the value to.
//
// Returns:
// SCODE
// S_OK if successful, E_FAIL if the operation could not
// be done because of an invalid type, etc.
//
//***************************************************************
SCODE CArrayGrid::GetValueAt(SAFEARRAY* psa, long lIndex, COleVariant& var)
{
var.Clear();
HRESULT hr;
VARTYPE vt = VtFromCimtype(m_cimtype);
switch(vt) {
case VT_BOOL:
hr = SafeArrayGetElement(psa, &lIndex, &var.boolVal);
var.vt = VT_BOOL;
break;
case VT_BSTR:
hr = SafeArrayGetElement(psa, &lIndex, &var.bstrVal);
var.vt = VT_BSTR;
break;
case VT_I2:
hr = SafeArrayGetElement(psa, &lIndex, &var.iVal);
var.vt = VT_I2;
break;
case VT_I4:
hr = SafeArrayGetElement(psa, &lIndex, &var.lVal);
var.vt = VT_I4;
break;
case VT_R4:
hr = SafeArrayGetElement(psa, &lIndex, &var.fltVal);
var.vt = VT_R4;
break;
case VT_R8:
hr = SafeArrayGetElement(psa, &lIndex, &var.dblVal);
var.vt = VT_R8;
break;
case VT_UI1:
hr = SafeArrayGetElement(psa, &lIndex, &var.bVal);
var.vt = VT_UI1;
break;
case VT_UNKNOWN:
hr = SafeArrayGetElement(psa, &lIndex, &var.punkVal);
if (SUCCEEDED(hr)) {
var.punkVal->AddRef();
var.vt = VT_UNKNOWN;
}
break;
default:
ASSERT(FALSE);
return E_FAIL;
break;
}
return S_OK;
}
//**************************************************************
// CArrayGrid::SaveValueAt
//
// Copy the value at the specified cell to the corresponding
// element in the safe array.
//
// Parameters:
// SAFEARRAY* psa
// Pointer to the destination safe array.
//
// long lRow
// The row index of the cell (the column index is assumed to
// be zero).
//
// Returns:
// SCODE
// S_OK if the value was copied successfully, FALSE otherwise.
//
//**************************************************************
SCODE CArrayGrid::SaveValueAt(SAFEARRAY* psa, long lRow)
{
CGridCell& gc = GetAt(lRow, 0);
COleVariant var;
CIMTYPE cimtype;
HRESULT hr;
gc.GetValue(var, cimtype);
VARTYPE vt = VtFromCimtype(cimtype);
if (var.vt == VT_NULL) {
switch(vt) {
case VT_BSTR:
var = "";
break;
default:
var.ChangeType(vt);
break;
}
}
switch(vt) {
case VT_BOOL:
hr = SafeArrayPutElement(psa, &lRow, &var.boolVal);
break;
case VT_BSTR:
hr = SafeArrayPutElement(psa, &lRow, var.bstrVal);
break;
case VT_I2:
hr = SafeArrayPutElement(psa, &lRow, &var.iVal);
break;
case VT_I4:
hr = SafeArrayPutElement(psa, &lRow, &var.lVal);
break;
case VT_R4:
hr = SafeArrayPutElement(psa, &lRow, &var.fltVal);
break;
case VT_R8:
hr = SafeArrayPutElement(psa, &lRow, &var.dblVal);
break;
case VT_UI1:
hr = SafeArrayPutElement(psa, &lRow, &var.bVal);
break;
case VT_UNKNOWN:
if (var.vt != VT_NULL) {
var.punkVal->AddRef();
hr = SafeArrayPutElement(psa, &lRow, var.punkVal);
}
break;
default:
ASSERT(FALSE);
break;
}
// !!!CR: Should test the "hr" value above at this point.
return S_OK;
}
//**************************************************************
// CArrayGrid::Save
//
// Copy the array from the grid into the variant.
//
// Parameters:
// None.
//
// Returns:
// SCODE
// S_OK if the copy is successful, otherwise E_FAIL if
// the grid contains an invalid value.
//
//**************************************************************
SCODE CArrayGrid::Save()
{
SCODE sc;
sc = SyncCellEditor();
if (FAILED(sc)) {
HmmvErrorMsg(IDS_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
return E_FAIL;
}
SAFEARRAY *psaDst;
LONG nRows = GetRows() - 1;
VARTYPE vt = VtFromCimtype(m_cimtype);
MakeSafeArray(&psaDst, vt, nRows);
m_pgcEdit->m_varValue.Clear();
m_pgcEdit->m_varValue.vt = VT_ARRAY | vt;
m_pgcEdit->m_varValue.parray = psaDst;
for (LONG lRow = 0; lRow < nRows; ++lRow) {
SaveValueAt(psaDst, lRow);
}
return S_OK;
}
//********************************************************
// CArrayGrid::Load
//
// Load the array from the variant into this grid.
//
// Parameters:
// [in] CGidCell* pgcEdit
// The grid cell to edit.
//
// Returns:
// Nothing.
//
//********************************************************
SCODE CArrayGrid::Load(CGridCell* pgcEdit)
{
m_pgcEdit = pgcEdit;
m_cimtype = pgcEdit->GetCimtype() & CIM_TYPEMASK;
m_bReadOnly = pgcEdit->IsReadonly();
m_bModified = FALSE;
COleVariant varValue;
CGridCell* pgc;
if (!m_bReadOnly) {
// Insert an "empty" row at the bottom if we allow editing.
AddRow();
}
if (pgcEdit->IsArray() && !pgcEdit->IsNull()) {
COleVariant var;
CIMTYPE cimtype;
// !!!CR: If getting the variant copies it, we should find a more
// !!!CR: efficient way to do this.
pgcEdit->GetValue(var, cimtype);
SAFEARRAY* psa = var.parray;
long lLBound;
long lUBound;
SafeArrayGetLBound(psa, 1, &lLBound);
SafeArrayGetUBound(psa, 1, &lUBound);
int nValues = lUBound - lLBound + 1;
int iRowDst = 0;
for (int iIndex=0; iIndex < nValues; ++iIndex) {
AddRow();
pgc = &GetAt(iRowDst, 0);
SCODE sc = GetValueAt(psa, iIndex, varValue);
if (FAILED(sc)) {
DeleteRowAt(iRowDst, FALSE);
continue;
}
++iRowDst;
pgc->SetValue(CELLTYPE_VARIANT, varValue, m_cimtype);
if (m_bReadOnly) {
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
}
pgc->SetModified(FALSE);
}
}
return S_OK;
}
//*******************************************************
// CArrayGrid::AddRow
//
// Add a row to the array grid.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//******************************************************
void CArrayGrid::AddRow()
{
int iEmptyRow = IndexOfEmptyRow();
if (iEmptyRow != NULL_INDEX) {
if (IsBooleanCell(iEmptyRow, 0)) {
CGridCell* pgcEmpty = &GetAt(iEmptyRow, 0);
if (pgcEmpty->IsNull()) {
SetBooleanCellValue(iEmptyRow, 0, FALSE);
RefreshCellEditor();
}
}
}
int nRows = GetRows();
InsertRowAt(nRows);
const CGcType& typeEdit = m_pgcEdit->type();
CGcType type;
type.SetCellType((CellType) typeEdit);
type.SetCimtype(((CIMTYPE) typeEdit) & ~CIM_FLAG_ARRAY);
CGridCell* pgc = &GetAt(nRows, 0);
pgc->SetToNull();
pgc->ChangeType(type);
int iLastRow = GetRows() - 1;
if (iLastRow >= 0) {
EnsureRowVisible(iLastRow);
}
RedrawWindow();
}
BOOL CArrayGrid::IsBooleanCell(int iRow, int iCol)
{
ASSERT(iRow != NULL_INDEX);
ASSERT(iCol != NULL_INDEX);
// Initialize the boolean value that we're editing to true
CGridCell* pgc = &GetAt(iRow, iCol);
CGcType type = pgc->type();
CIMTYPE cimtype = (CIMTYPE) type;
BOOL bIsBoolean = ((cimtype & ~CIM_FLAG_ARRAY) == CIM_BOOLEAN);
return bIsBoolean;
}
void CArrayGrid::SetBooleanCellValue(int iRow, int iCol, BOOL bValue)
{
ASSERT(iRow != NULL_INDEX);
ASSERT(iCol != NULL_INDEX);
ASSERT(IsBooleanCell(iRow, iCol));
// Initialize the boolean value that we're editing to true
CGridCell* pgc = &GetAt(iRow, iCol);
CGcType type = pgc->type();
CIMTYPE cimtype = (CIMTYPE) type;
COleVariant varValue;
varValue.ChangeType(VT_BOOL);
varValue.boolVal = bValue ? VARIANT_TRUE : VARIANT_FALSE;
pgc->SetValue(type, varValue);
}
BOOL CArrayGrid::OnCellKeyDown(int iRow, int iCol, UINT nChar, UINT nRepCnt, UINT nFlags)
{
int iSelectedRow;
int iSelectedCol;
GetSelectedCell(iSelectedRow, iSelectedCol);
if (iRow!=iSelectedRow || iCol!=iSelectedCol) {
OnCellClicked(iRow, iCol);
}
return FALSE;
}
//**********************************************************
// CArrayGrid::OnCellClickedEpilog
//
// The grid class calls this method when a cell is clicked.
//
// Parameters:
// int iRow
// The row index of the clicked cell.
//
// int iCol
// The column index of the clicked cell.
//
// Returns:
// Nothing.
//
//***********************************************************
void CArrayGrid::OnCellClicked(int iRow, int iCol)
{
OnCellDoubleClicked(iRow, iCol);
}
//********************************************************************
// CArrayGrid::OnCellFocusChange
//
// This virtual method is called by the CGrid base class to notify
// derived classes when the focus is about to change from one cell
// to another.
//
// Paramters:
// [in] int iRow
// The row index of the cell.
//
// [in] int iCol
// The column index of the cell. If iCol is NULL_INDEX and
// iRow is valid, then an entire row is being selected.
//
// [in] int iNextRow
// The next row that will be selected. This parameter is provided
// as a hint and is valid only if bGotFocus is FALSE.
//
// [in] int iNextCol
// The column index of the next cell that will get the focus when the
// current cell is loosing focus. This parameter is provided as a hint and
// is valid only if bGotFocus is FALSE.
//
// [in] BOOL bGotFocus
// TRUE if the cell is getting the focus, FALSE if the cell is
// about to loose the focus.
//
// Returns:
// TRUE if it is OK for the CGrid class to complete the focus change
// FALSE if the focus change should be aborted.
//
//*********************************************************************
BOOL CArrayGrid::OnCellFocusChange(int iRow, int iCol, int iNextRow, int iNextCol, BOOL bGotFocus)
{
SCODE sc;
if (!bGotFocus) {
sc = SyncCellEditor();
if (FAILED(sc)) {
HmmvErrorMsg(IDS_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
return FALSE;
}
if ((iRow != NULL_INDEX ) && (iCol != NULL_INDEX)) {
CGridCell* pgc = &GetAt(iRow, iCol);
if (pgc->IsNull()) {
// Null cells are now allowed.
int iEmptyRow = IndexOfEmptyRow();
if (iRow != iEmptyRow) {
return FALSE;
}
}
}
}
return TRUE;
}
//******************************************************
// CArrayGrid::OnCellDoubleClicked
//
// This method overrides CGrid equivallent so that a new
// row can be created when the used double-clicks the
// empty row at the bottom of the grid if it exists.
//
// Parameters:
// int iRow
// The row index.
//
// int iCol
// The column index.
//
// Returns:
// Nothing.
//
//*******************************************************
void CArrayGrid::OnCellDoubleClicked(int iRow, int iCol)
{
int iEmptyRow = IndexOfEmptyRow();
if (!m_bReadOnly && iRow==iEmptyRow) {
SCODE sc = SyncCellEditor();
if (FAILED(sc)) {
HmmvErrorMsg(IDS_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
return;
}
EndCellEditing();
SelectCell(iEmptyRow, 0, TRUE);
CGridCell* pgcEmpty = &GetAt(iEmptyRow, 0);
switch((CIMTYPE) pgcEmpty->type()) {
case CIM_OBJECT:
case CIM_DATETIME:
if (pgcEmpty->IsNull()) {
return;
}
break;
default:
if (pgcEmpty->IsNull()) {
pgcEmpty->SetDefaultValue();
RefreshCellEditor();
}
break;
}
// Add a new empty row with a null value.
if (((m_cimtype & ~CIM_FLAG_ARRAY))!=CIM_OBJECT || (m_psvc != NULL)) {
SelectCell(NULL_INDEX, NULL_INDEX);
AddRow();
RedrawCell(iEmptyRow, 0);
}
SelectCell(iRow, iCol);
}
}
//*********************************************************
// CArrayGrid::ClearEmptyRow()
//
// Clear the emtpy row to an empty string with CELLTYPE_VOID.
// Doing so gives the user the appearance of an empty cell that
// he or she can set the cursor on.
//
// This is useful after editing a new row and then aborting the
// edit.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//**********************************************************
void CArrayGrid::ClearEmptyRow()
{
int iEmptyRow = IndexOfEmptyRow();
if (iEmptyRow == NULL_INDEX) {
return;
}
CGcType type(CELLTYPE_VARIANT, CIM_STRING);
CGridCell& gc = GetAt(iEmptyRow, 0);
gc.SetValue(type, _T(""));
}
//**********************************************************
// CArrayGrid::OnRowHandleDoubleClicked
//
// Override the CGrid method to create a new row when the
// row handle of the empty row is double-clicked.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//**********************************************************
void CArrayGrid::OnRowHandleDoubleClicked(int iRow)
{
OnCellDoubleClicked(iRow, 0);
#if 0
int iEmptyRow = IndexOfEmptyRow();
if (iEmptyRow == NULL_INDEX || (iRow < iEmptyRow)) {
return;
}
AddRow();
CGridCell* pgc = &GetAt(iEmptyRow, 0);
if (pgc->RequiresSpecialEditing()) {
BeginCellEditing();
pgc->DoSpecialEditing();
if (pgc->IsNull()) {
DeleteRowAt(IndexOfEmptyRow(), TRUE);
ClearEmptyRow();
}
EndCellEditing();
SelectCell(iEmptyRow, 0);
RedrawCell(iEmptyRow, 0);
}
#endif //0
}
//*****************************************************************************
// CArrayGrid::OnCellChar
//
// This is a virtual method that the CGrid base class calls to notify derived
// classes that a WM_CHAR message was recieved.
//
// Parameters:
// int iRow
// The row index of the cell that the keystroke occurred in.
//
// int iCol
// The column index of the cell that the keystroke occurred in.
//
// UINT nChar
// The nChar parameter from window's OnKeyDown message.
//
// UINT nRepCnt
// The nRepCnt parameter from window's OnKeyDown message.
//
// UINT nFlags
// The nFlags parameter from window's OnKeyDown message.
//
// Returns:
// BOOL
// TRUE if this method handles the keydown message, FALSE otherwise.
//
//**********************************************************************
BOOL CArrayGrid::OnCellChar(int iRow, int iCol, UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Check to see if we are on the "empty" row at the bottom of the grid.
// If so, then create a new property.
EnsureRowVisible(iRow);
int iEmptyRow = IndexOfEmptyRow();
if (iEmptyRow != NULL_INDEX && iRow==iEmptyRow) {
AddRow();
CGridCell* pgc = &GetAt(iRow, iCol);
if (pgc->RequiresSpecialEditing()) {
BeginCellEditing();
pgc->DoSpecialEditing();
if (pgc->IsNull()) {
if (((CIMTYPE) pgc->type()) == CIM_OBJECT) {
DeleteRowAt(IndexOfEmptyRow(), TRUE);
ClearEmptyRow();
}
}
EndCellEditing();
SelectCell(iEmptyRow, 0);
RedrawCell(iEmptyRow, 0);
}
}
// We don't handle this event.
return FALSE;
}
//***********************************************************
// CArrayGrid::IndexOfEmptyRow
//
// Return the index of the empty row at the bottom of the grid.
// If the array is read-only, then return NULL_INDEX.
//
// Parameters:
// None.
//
// Returns:
// int
// The index of the empty row at the bottom of the grid
// or NULL_INDEX if there is no empty row.
//
//***********************************************************
int CArrayGrid::IndexOfEmptyRow()
{
if (m_bReadOnly) {
return NULL_INDEX;
}
else {
return GetRows() - 1;
}
}
//***********************************************************
// CArrayGrid::GetModified
//
// Check to see if the grid has been modified.
//
// Parameters:
// None.
//
// Returns:
// BOOL
// TRUE if the grid was modified, FALSE otherwise.
//
//************************************************************
BOOL CArrayGrid::GetModified()
{
return m_bModified;
}
//************************************************************
// CArrayGrid::SetModified
//
// Set the modified flag of all the grid cells to the given value.
//
// Parameters:
// BOOL bModified
// The new value to set the modified flag to.
//
// Returns:
// BOOL
// The previous value of the m_bModified flag.
//
//************************************************************
BOOL CArrayGrid::SetModified(BOOL bModified)
{
BOOL bInitialValue = m_bModified;
int nRows = m_bReadOnly ? GetRows() : GetRows() -1;
for (int iRow = 0; iRow < nRows; ++iRow) {
CGridCell* pgc = &GetAt(iRow, 0);
pgc->SetModified(bModified);
}
bModified = bModified;
return bInitialValue;
}
//*******************************************************************
// CArrayGrid::OnCellContentChange
//
// Override this virtual method in CGrid to detect changes to a grid
// cell.
//
// Parameters:
// int iRow
// The row index of the cell modified.
//
// int iCol
// The column index of the cell modified.
//
// Returns:
// Nothing.
//
//*******************************************************************
void CArrayGrid::OnCellContentChange(int iRow, int iCol)
{
if (!m_bReadOnly) {
int iEmptyRow = IndexOfEmptyRow();
if (iRow == iEmptyRow) {
SCODE sc = SyncCellEditor();
if (SUCCEEDED(sc)) {
CGridCell* pgc = &GetAt(iRow, iCol);
if (!pgc->IsNull() && (m_psvc != NULL)) {
AddRow();
}
}
}
}
m_bModified = TRUE;
}
//*****************************************************************************
// CArrayGrid::OnRowKeyDown
//
// This is a virtual method that the CGrid base class calls to notify derived
// classes that a key was pressed while the focus was set to a grid cell.
//
// Parameters:
// [in] int iRow
// The row index of the cell that the keystroke occurred in.
//
// [in] UINT nChar
// The nChar parameter from window's OnKeyDown message.
//
// [in] UINT nRepCnt
// The nRepCnt parameter from window's OnKeyDown message.
//
// [in] UINT nFlags
// The nFlags parameter from window's OnKeyDown message.
//
// Returns:
// BOOL
// TRUE if this method handles the keydown message, FALSE otherwise.
//
//**********************************************************************
BOOL CArrayGrid::OnRowKeyDown(
/* in */ int iRow,
/* in */ UINT nChar,
/* in */ UINT nRepCnt,
/* in */ UINT nFlags)
{
switch(nChar) {
case VK_DELETE:
if (m_bReadOnly) {
MessageBeep(MB_ICONEXCLAMATION);
}
else {
int iEmptyRow = IndexOfEmptyRow();
if ((iRow != NULL_INDEX) && (iRow != iEmptyRow)) {
DeleteRowAt(iRow);
m_bModified = TRUE;
}
}
return TRUE;
}
// We don't handle this event.
return FALSE;
}
//*******************************************************************
// CArrayGrid::CompareRows
//
// This is a virtual method override that compares two rows in the grid
// using the column index as the sort criteria.
//
// Parameters:
// int iRow1
// The index of the first row.
//
// int iRow2
// The index of the second row.
//
// int iSortColumn
// The column index.
//
// Returns:
// >0 if row 1 is greater than row 2
// 0 if row 1 equal zero
// <0 if row 1 is less than zero.
//
//********************************************************************
int CArrayGrid::CompareRows(int iRow1, int iRow2, int iSortColumn)
{
int iResult;
switch (iSortColumn) {
case 0:
// Sort first by name
iResult = CompareCells(iRow1, iRow2, 0);
return iResult;
}
return 0;
}
//*********************************************************************
// CPropGrid::GetCellEditContextMenu
//
// Get the context menu for the specified cell.
//
// Parameters:
// [in] int iRow
//
// [in] int iCol
// The column index for the specified cell.
//
// [out] CWnd*& pwndTarget
// The target window
//
// [out] CMenu& menu
// This CMenu object is loaded with the desired menu.
//
// [in] BOOL& bWantEditCommands
// TRUE if the caller wants the commands for editing a cell.
//
// Returns:
// BOOL
// TRUE if a context menu exists for the specified cell.
//
//********************************************************************
BOOL CArrayGrid::GetCellEditContextMenu(int iRow, int iCol, CWnd*& pwndTarget, CMenu& menu, BOOL& bWantEditCommands)
{
bWantEditCommands = FALSE;
VERIFY(menu.LoadMenu(IDR_ARRAYEDIT_MENU));
pwndTarget = this;
return TRUE;
}
//***********************************************************************
// CArrayGrid::ModifyCellEditContextMenu
//
// The cell editor calls this method just prior to displaying the context
// menu when the user right-clicks. This method gives classes derived from
// CGrid a chance to modify the context menu depending on the current situation.
//
// Parameters:
// [in] int iRow
// The row index of the cell that was right-clicked.
//
// [in] int iCol
// The column index of the cell that was right-clicked.
//
// [in/out] CMenu& menu
// A reference to the context menu that you can modify.
//
// Returns:
// Nothing.
//
//************************************************************************
void CArrayGrid::ModifyCellEditContextMenu(int iRow, int iCol, CMenu& menu)
{
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
if (iRow == IndexOfEmptyRow()) {
pPopup->RemoveMenu(ID_CMD_CREATE_VALUE, MF_BYCOMMAND);
}
return;
#if 0
// We may want to put the following code back in someday, so I didn't delete it yet.
BOOL bIsSystemProperty = FALSE;
COleVariant varPropName;
CIMTYPE cimtype = 0;
CGridCell& gc = GetAt(iRow, ICOL_PROP_NAME);
gc.GetValue(varPropName, cimtype);
BOOL bCanShowPropQualifiers = TRUE;
if (iRow == IndexOfEmptyRow()) {
bCanShowPropQualifiers = FALSE;
}
else
{
if (cimtype != CIM_STRING || varPropName.vt != VT_BSTR)
{
bCanShowPropQualifiers = FALSE;
}
else
{
if (IsSystemProperty(varPropName.bstrVal))
{
bCanShowPropQualifiers = FALSE;
}
}
}
pPopup->EnableMenuItem(ID_CMD_SHOW_SELECTED_PROP_ATTRIBUTES, bCanShowPropQualifiers ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
CGridCell *gcValue = NULL;
if (m_psvc == NULL) {
pPopup->RemoveMenu(ID_CMD_CREATE_VALUE, MF_BYCOMMAND);
}
else {
if(HasCol(ICOL_PROP_VALUE))
{
gcValue = &GetAt(iRow, ICOL_PROP_VALUE);
BOOL bCanCreateObject = gcValue->IsObject() && gcValue->IsNull();
BOOL bCanCreateArray = gcValue->IsArray() && gcValue->IsNull();
BOOL bIsReadonly = gcValue->IsReadonly();
if(gcValue && (bIsReadonly || !(bCanCreateObject || bCanCreateArray)))
{
pPopup->RemoveMenu(ID_CMD_CREATE_VALUE, MF_BYCOMMAND);
}
}
else
{
pPopup->RemoveMenu(ID_CMD_CREATE_VALUE, MF_BYCOMMAND);
}
}
if (iCol != ICOL_PROP_VALUE)
{
pPopup->RemoveMenu( ID_CMD_SET_CELL_TO_NULL, MF_BYCOMMAND);
}
else
{
BOOL bCanSetToNull = FALSE;
if (!(gc.GetFlags() & CELLFLAG_READONLY))
{
bCanSetToNull = TRUE;
}
pPopup->EnableMenuItem(ID_CMD_SET_CELL_TO_NULL, bCanSetToNull ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
}
// store for the cmd handlers.
m_curRow = &GetRowAt(iRow);
OnBuildContextMenu(pPopup, iRow);
#endif //0
}
void CArrayGrid::OnCmdCreateValue()
{
if (m_psvc == NULL) {
return;
}
int iRow = NULL_INDEX;
int iCol = NULL_INDEX;
if (!PointToCell(m_ptContextMenu, iRow, iCol)) {
return;
}
if (iCol != 0) {
return;
}
if (iRow != IndexOfEmptyRow()) {
return;
}
EndCellEditing();
SyncCellEditor();
SelectCell(iRow, 0);
AddRow();
CGridCell& gc = GetAt(iRow, 0);
BOOL bIsNull = gc.IsNull();
BOOL bIsArray = gc.IsArray();
BOOL bIsObject = gc.IsObject();
if (!bIsNull) {
return;
}
if (bIsArray) {
gc.EditArray();
}
else if (bIsObject) {
LPUNKNOWN lpunk = gc.GetObject();
if (lpunk != NULL) {
lpunk->Release();
return;
}
COleVariant varPropname;
CDlgObjectEditor dlg;
dlg.CreateEmbeddedObject(m_psvc, m_sClassname, &gc);
RedrawCell(iRow, 0);
}
}
//*******************************************************************
// CArrayGrid::OnContextMenu
//
// This method is called to display the context menu (right button menu).
//
// Parameters:
// CWnd*
//
// CPoint ptContextMenu
// The place where the right moust button was clicked.
//
// Returns:
// Nothing.
//
//*****************************************************************
void CArrayGrid::OnContextMenu(CWnd* pwnd, CPoint ptContextMenu)
{
// CG: This function was added by the Pop-up Menu component
m_ptContextMenu = ptContextMenu;
ScreenToClient(&m_ptContextMenu);
int iRow;
int iCol;
BOOL bClickedCell = PointToCell(m_ptContextMenu, iRow, iCol);
if (!bClickedCell) {
iCol = NULL_INDEX;
BOOL bClickedRowHandle = PointToRowHandle(m_ptContextMenu, iRow);
if (!bClickedRowHandle) {
iRow = NULL_INDEX;
}
}
if (iRow == IndexOfEmptyRow()) {
iRow = NULL_INDEX;
iCol = NULL_INDEX;
}
else {
return;
}
CMenu menu;
VERIFY(menu.LoadMenu(IDR_ARRAYEDIT_MENU1));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
if ((m_cimtype & ~CIM_FLAG_ARRAY) != CIM_OBJECT) {
pPopup->RemoveMenu( ID_CMD_SET_CELL_TO_NULL, MF_BYCOMMAND);
}
if (iRow == NULL_INDEX) {
pPopup->RemoveMenu(ID_CMD_CREATE_VALUE, MF_BYCOMMAND);
}
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, ptContextMenu.x, ptContextMenu.y,
this);
}
SCODE CArrayGrid::GetObjectClass(CString& sClassname, int iRow, int iCol)
{
sClassname = m_sClassname;
if (sClassname.IsEmpty()) {
return E_FAIL;
}
else {
return S_OK;
}
}
void CArrayGrid::SetObjectParams(IWbemServices* psvc, CString& sClassname)
{
if (m_psvc != NULL) {
m_psvc->Release();
}
if (psvc != NULL) {
psvc->AddRef();
}
m_psvc = psvc;
m_sClassname = sClassname;
}