📄 itemadddlg.cpp
字号:
// none
//
// Returns:
// bool - true if success.
// **************************************************************************
bool CKItemAddDlg::OnApplyChange ()
{
// No need to apply changes unless we are modified:
if (m_bModified)
{
CKItem *pItem = NULL;
// Make sure member variables have values currently displayed in
// associated controls:
UpdateData (true);
// If auto validating, validate item before applying changes.
if (m_bAutoValidate)
{
// Validate currently selected item:
HRESULT hr = Validate ();
// If item is invalid, then inform user of problem and give him
// option of continuing:
if (FAILED (hr))
{
// Define a string format for the validation return code:
CString strHR;
strHR.Format (_T("0x%08X"), hr);
// Define a string format for the validation return code:
CString strFailure;
strFailure.FormatMessage (IDS_VALIDATE_ITEM_FAILED_CONTINUE, m_strItemID, strHR);
// Show message bow with error string. Give user of option of
// continuing. If user clicks "NO", return now without applying
// changes:
if (AfxMessageBox (strFailure, MB_YESNO | MB_ICONQUESTION) == IDNO)
return (false);
}
}
// If we make it here, it is OK to apply changes.
// If selected index is the same as list control index, then we
// need to create a new item and add to the list:
if (m_nSelIndex == m_nListIndex)
{
try
{
// Create a new item object and add it to the list:
pItem = new CKItem (m_pGroup);
m_cItemList.SetAtGrow (m_nListIndex++, pItem);
}
catch (...)
{
ASSERT (FALSE);
}
}
// else we are modifying an item already in list:
else
{
pItem = (CKItem *) m_cItemList.GetAt (m_nSelIndex);
ASSERT (pItem != NULL);
}
// Set item properties:
pItem->SetAccessPath (m_strAccessPath);
pItem->SetActive (m_bActive);
pItem->SetDataType (m_vtDataType);
pItem->SetItemID (m_strItemID);
// Set modified flag:
m_bModified = false;
}
// Return true to indicate success:
return (true);
}
// **************************************************************************
// AutoIncrementID ()
//
// Description:
// Create a new item ID by incrementing current ID.
//
// Parameters:
// bool bDotBitAddress Set to true if item has "dot bit number"
// address format.
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::AutoIncrementID (bool bDotBitAddress)
{
static TCHAR szBuffer [DEFBUFFSIZE];
static TCHAR *pch = NULL;
// If the item ID is defined, we will modify it by incrementing:
if (!m_strItemID.IsEmpty ())
{
// Make a local copy of the current item ID:
lstrcpyn (szBuffer, m_strItemID, sizeof (szBuffer) / sizeof (TCHAR));
// Ensure it is null terminated:
szBuffer [DEFBUFFSIZE - 1] = '\0';
// Get a pointer to the last character of the string (search for
// NULL terminator, then back up a character):
pch = _tcschr (szBuffer, _T('\0'));
pch--;
// If it is a digit we can simply increment this address:
if (_istdigit (*pch))
{
int nNumber;
// Scan backwards from last character until we encounter
// a non-digit:
while (_istdigit (*pch) && pch != szBuffer)
pch--;
// Obtain the number we are peeling off (go to next character
// which will be the first digit, then convert text to right
// to an integer):
pch++;
nNumber = _ttol (pch);
// Increment the number:
nNumber++;
// If we are dealing with a "dot bit number" address,
// make sure we do not increment bit number beyond 15.
// Increment bit numbers to 15, then increment offset
// and make bit number 0.
// If bDotBitAddress is set, then character to the left
// of current pointer should be the "dot".
if (bDotBitAddress && *(pch - 1) == _T('.'))
{
// Assume dot specifier is a bit and increment 0 - 15.
// If nNumber is greater than 15, determine offset, and
// increment that instead of the bit number:
if (nNumber > 15)
{
// Roll offset ahead:
pch = _tcsrchr (szBuffer, _T('.'));
pch--;
// Peel back looking for the first non-digit:
while (_istdigit (*pch) && pch != szBuffer)
pch--;
// Go to next character and convert to integer. This will
// be the offset since _ttol will not use any characters to
// the right of the dot. Increment the result by one. This
// will be our new offset.
pch++;
nNumber = _ttol (pch) + 1;
// Replace old offset and bit number with incremented
// offset and bit number "00".
_stprintf (pch, _T("%d.00"), nNumber);
}
// Otherwise just replace the bit number with incremeted
// bit number:
else
_stprintf (pch, _T("%02d"), nNumber);
}
// If not a dot bit number address, make sure we do not lose
// any leading zeros (as in modbus addresses):
else
{
// We should currently be pointing at first character of
// trailing digit portion of address. Check to see if
// this is a zero.
if (*pch == _T('0'))
{
// We found a leading zero.
TCHAR *pZeros = pch;
int cnDigits = 0;
// Scan forwared until we find a non-zero character.
// Count each zero along the way:
while (*pZeros++ != _T('\0'))
cnDigits++;
// Replace the trailing digits of the adress with
// the new incremented number, keeping the same
// number of leading zeros:
_stprintf (pch, _T("%0*d"), cnDigits, nNumber);
}
// Else if no leading zeros, just replace the trailing
// digits with the new incremented number:
else
_stprintf (pch, _T("%d"), nNumber);
}
}
// else if last character is not a digit, append a good starting offset:
else
*(pch + 1) = '0';
// Update item ID:
m_strItemID = szBuffer;
// Update controls:
UpdateData (false);
// Set modifed flag:
m_bModified = true;
}
}
// **************************************************************************
// UpdateStatus ()
//
// Description:
// Update status of dialog controls based on current item selected.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::UpdateStatus ()
{
// Determine the focus so that if we disable the focused control
// we can move it.
HWND hWnd = ::GetFocus ();
// Enable the next button if the selected item has an item ID defined:
m_cNext.EnableWindow (m_nSelIndex < m_nListIndex - 1);
// Enable the previous button if the selected item has a previous button:
m_cPrev.EnableWindow (m_nSelIndex > 0);
// Enable the new button if there is a valid item ID entered
// (otherwise they are already editting a new item):
m_cNew.EnableWindow (!m_strItemID.IsEmpty ());
// Duplicate any item that has an item ID:
m_cDuplicate.EnableWindow (!m_strItemID.IsEmpty ());
// Enable the delete button if the item selected is not the one we
// are adding to the list:
m_cDelete.EnableWindow (m_nSelIndex < m_nListIndex);
// Enable validate item:
m_cValidate.EnableWindow (m_pIItemMgt && !m_strItemID.IsEmpty ());
// Update the browse controls:
m_pBranchList->EnableWindow (m_pIBrowse != NULL);
m_pLeafList->EnableWindow (m_pIBrowse != NULL);
GetDlgItem (IDC_ADD_LEAVES)->EnableWindow (m_pIBrowse != NULL);
GetDlgItem (IDC_FILTERACCESS)->EnableWindow (m_pIBrowse != NULL);
GetDlgItem (IDC_FILTERLEAF)->EnableWindow (m_pIBrowse != NULL);
GetDlgItem (IDC_FILTERTYPE)->EnableWindow (m_pIBrowse != NULL);
GetDlgItem (IDC_FILTERBRANCH)->EnableWindow (m_pIBrowse != NULL);
// Update the item count display:
CString strItemCount;
strItemCount.Format (_T("Item Count: %d"), m_nListIndex);
((CStatic *) GetDlgItem (IDC_ITEM_COUNT))->SetWindowText (strItemCount);
// Set the focus to the first control if the previous control with the
// focus just lost it:
if (hWnd && !::IsWindowEnabled (hWnd))
GetDlgItem (IDC_ITEMID)->SetFocus ();
}
// **************************************************************************
// InitializeBrowser ()
//
// Description:
// Initialize things related to the browser.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::InitializeBrowser ()
{
// Get pointers to our browse controls for easy access:
m_pBranchList = (CTreeCtrl *) GetDlgItem (IDC_BRANCHLIST);
ASSERT (m_pBranchList != NULL);
m_pLeafList = (CListCtrl *) GetDlgItem (IDC_LEAFLIST);
ASSERT (m_pLeafList != NULL);
// Initialize the image list for the branch control. These are the
// images that show up to the left of each item in list. The bitmap
// must use a purple background color, RGB (255, 0, 255), so that the
// CImageList object can construct a mask. The images are 16x16 pixels.
// Set the image list background color to CLR_NONE so masked pixels will
// be transparent.
//
// Image number Use
// 0-7 not used
// 8 Branch
// 9 Self branch
m_cBranchImageList.Create (IDB_GROUPIMAGES, 16, 3, RGB (255, 0, 255));
m_cBranchImageList.SetBkColor (CLR_NONE);
m_pBranchList->SetImageList (&m_cBranchImageList, TVSIL_NORMAL);
// Initialize the image list for the leaf control. These are the images
// that show up to the left of each item in list. The bitmap must use a
// purple background color, RGB (255, 0, 255), so that the CImageList
// object can construct a mask. The images are 14x14 pixels. Set the
// image list background color to CLR_NONE so masked pixels will be
// transparent.
//
// Image number Use
// 0-2 not used
// 3 Leaf
m_cLeafImageList.Create (IDB_ITEMIMAGES, 14, 2, RGB (255, 0, 255));
m_cLeafImageList.SetBkColor (CLR_NONE);
m_pLeafList->SetImageList (&m_cLeafImageList, LVSIL_SMALL);
// Insert a column for our leaf item list control:
CRect rc;
m_pLeafList->GetClientRect (&rc);
m_pLeafList->InsertColumn (0, _T(""), LVCFMT_LEFT, rc.Width ());
// Initialize filters:
m_strFilterBranch = "*";
((CEdit *) GetDlgItem (IDC_FILTERBRANCH))->SetWindowText (m_strFilterBranch);
m_strFilterLeaf = "*";
((CEdit *) GetDlgItem (IDC_FILTERLEAF))->SetWindowText (m_strFilterLeaf);
m_vtFilterType = VT_EMPTY;
((CComboBox *) GetDlgItem (IDC_FILTERTYPE))->SetCurSel (0);
m_dwFilterAccessRights = CB_ACCESS_ANY;
((CComboBox *) GetDlgItem (IDC_FILTERACCESS))->SetCurSel (CB_ACCESS_ANY);
// Intialize browse controls if browsing is supported, otherwise
// just disable the controls:
if (m_pIBrowse != NULL)
{
// Create a wait cursor object. This will cause the wait cursor,
// usually an hourglass, to be displayed. When this object goes
// out of scope, its destructor will restore the previous cursor
// type.
CWaitCursor wc;
HRESULT hr;
// Query the server name space:
hr = m_pIBrowse->QueryOrganization (&m_cOpcNameSpace);
if (SUCCEEDED (hr))
{
// Browse root level:
switch (m_cOpcNameSpace)
{
case OPC_NS_HIERARCHIAL:
case OPC_NS_FLAT:
BrowseRootLevel ();
break;
// Did the foundation add a new type?
default:
ASSERT (FALSE);
break;
}
}
// We will assume a hierarchial search if the server fails this request:
// (This allows us to work with any server that uses the ICONICS toolkit.)
else
{
TRACE (_T("OTC: Attempting agressive browsing since the server failed on QueryOrganization ()\r\n"));
m_cOpcNameSpace = OPC_NS_HIERARCHIAL;
BrowseRootLevel ();
}
}
}
// **************************************************************************
// BrowseRootLevel ()
//
// Description:
// Reset the browser to the root object.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::BrowseRootLevel ()
{
HRESULT hr = E_FAIL;
HTREEITEM hItem = NULL;
try
{
// If hierarchial namespace:
if (m_cOpcNameSpace == OPC_NS_HIERARCHIAL)
{
// Re-initialize server's browse position to the root:
do
{
// Use the OPC_BROWSE_UP rather than the OPC_BROWSE_TO which
// is only supported in OOPC version 2.0. We will have to
// browse up to root one level at a time. Function will
// fail when we are at root.
hr = m_pIBrowse->ChangeBrowsePosition (OPC_BROWSE_UP, L"\0");
} while (SUCCEEDED (hr));
// Insert our root level item:
hItem = m_pBranchList->InsertItem ((m_pGroup->GetParentServer ())->GetProgID (),
ILI_BRANCH, ILI_SELBRANCH, TVI_ROOT);
// Set the item data and add a dummy child branch:
m_pBranchList->SetItemData (hItem, DWORD (-1));
AddDummyBranch (hItem);
}
// Else flat namespace:
else
{
ASSERT (m_cOpcNameSpace == OPC_NS_FLAT);
// Insert our root level item (there is no need to add any dummy
// branches since a flat space will only have one level of leaves)
hItem = m_pBranchList->InsertItem ((m_pGroup->GetParentServer ())->GetProgID (),
ILI_BRANCH, ILI_SELBRANCH, TVI_ROOT);
}
// Select root item:
if (hItem)
m_pBranchList->SelectItem (hItem);
}
catch (...)
{
m_pIBrowse = NULL;
UpdateStatus ();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -