📄 itemadddlg.cpp
字号:
// **************************************************************************
// itemadddlg.cpp
//
// Description:
// Implements a dialog class for adding OPC items. Allows user to browse for
// items and other handy things.
//
// DISCLAIMER:
// This programming example is provided "AS IS". As such Kepware, Inc.
// makes no claims to the worthiness of the code and does not warranty
// the code to be error free. It is provided freely and can be used in
// your own projects. If you do find this code useful, place a little
// marketing plug for Kepware in your code. While we would love to help
// every one who is trying to write a great OPC client application, the
// uniqueness of every project and the limited number of hours in a day
// simply prevents us from doing so. If you really find yourself in a
// bind, please contact Kepware's technical support. We will not be able
// to assist you with server related problems unless you are using KepServer
// or KepServerEx.
// **************************************************************************
#include "stdafx.h"
#include "opctestclient.h"
#include "itemadddlg.h"
#include "item.h"
#include "group.h"
#include "server.h"
// Registry sections;
static LPCTSTR lpszRegSection = _T("Add Items");
static LPCTSTR lpszAutoValidate = _T("Auto Validate");
static LPCTSTR lpszBrowseFlat = _T("Browse Flat");
// Default add item list size:
#define DEF_ITEM_LIST_SIZE 16
// Branch dummy item data:
#define NULL_ITEM_NAME _T("_QCNULL_DUMMY")
#define NULL_ITEM_DATA 0xFFFFFFFF
// Image list indices:
#define ILI_BRANCH 8
#define ILI_SELBRANCH 9
#define ILI_LEAF 3
// Access rights filter combo box indices:
#define CB_ACCESS_ANY 0
#define CB_ACCESS_READONLY 1
#define CB_ACCESS_WRITEONLY 2
#define CB_ACCESS_READWRITE 4
/////////////////////////////////////////////////////////////////////////////
// CKItemAddDlg dialog
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
BEGIN_MESSAGE_MAP (CKItemAddDlg, CDialog)
//{{AFX_MSG_MAP(CKItemAddDlg)
ON_BN_CLICKED (IDC_NEW, OnNew)
ON_NOTIFY (TVN_ITEMEXPANDING, IDC_BRANCHLIST, OnBranchExpanding)
ON_NOTIFY (TVN_SELCHANGED, IDC_BRANCHLIST, OnBranchSelected)
ON_CBN_SELCHANGE (IDC_FILTERACCESS, OnAccessFilterChange)
ON_EN_CHANGE (IDC_FILTERLEAF, OnLeafFilterChange)
ON_CBN_SELCHANGE (IDC_FILTERTYPE, OnVartypeFilterChange)
ON_BN_CLICKED (IDC_NEXT, OnNext)
ON_BN_CLICKED (IDC_PREVIOUS, OnPrevious)
ON_BN_CLICKED (IDC_VALIDATEITEM, OnValidateItem)
ON_EN_CHANGE (IDC_FILTERBRANCH, OnBranchFilterChange)
ON_NOTIFY (NM_DBLCLK, IDC_LEAFLIST, OnClickLeafList)
ON_EN_CHANGE (IDC_ITEMID, OnChange)
ON_BN_CLICKED (IDC_DELETE, OnDelete)
ON_BN_CLICKED (IDC_DUPLICATE, OnDuplicate)
ON_BN_CLICKED (IDC_ADD_LEAVES, OnAddLeaves)
ON_EN_CHANGE (IDC_ACCESSPATH, OnChange)
ON_BN_CLICKED (IDC_ACTIVE, OnChange)
ON_CBN_SELCHANGE (IDC_DATATYPE, OnChange)
ON_BN_CLICKED (IDC_AUTOVALIDATE, OnAutoValidate)
ON_WM_SHOWWINDOW ()
ON_BN_CLICKED (IDC_BROWSEFLAT, OnBrowseFlat)
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
// **************************************************************************
// CKItemAddDlg ()
//
// Description:
// Constructor.
//
// Parameters:
// CKGroup *pGroup Group to add item to.
// IOPCBrowseServerAddressSpace *pIBrowse Server browse interface.
// CWnd* pParent Parent window. If it is NULL,
// the dialog object抯 parent
// window is set to the main
// application window.
//
// Returns:
// none
// **************************************************************************
CKItemAddDlg::CKItemAddDlg (CKGroup *pGroup, IOPCBrowseServerAddressSpace *pIBrowse, CWnd *pParent /*=NULL*/)
: CDialog (CKItemAddDlg::IDD, pParent)
{
// Initialize member variables:
ASSERT (pGroup != NULL);
m_pGroup = pGroup;
m_pIBrowse = pIBrowse;
m_nListIndex = 0;
m_nSelIndex = 0;
m_bModified = false;
m_pIItemMgt = NULL;
// Load registry settings. These are settings we may want to use each time
// we add some items:
m_bAutoValidate = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszAutoValidate, FALSE);
m_bBrowseFlat = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszBrowseFlat, FALSE);
// Allocate memory for add item list:
try
{
m_cItemList.SetSize (DEF_ITEM_LIST_SIZE, DEF_ITEM_LIST_SIZE);
}
catch (...)
{
ASSERT (FALSE);
}
//{{AFX_DATA_INIT(CKItemAddDlg)
m_strAccessPath = ITEM_DEFAULT_ACCESSPATH;
m_bActive = ITEM_DEFAULT_ACTIVESTATE;
m_strItemID = ITEM_DEFAULT_ITEMID;
m_vtDataType = ITEM_DEFAULT_DATATYPE;
m_strFilterLeaf = _T("");
m_strFilterBranch = _T("");
//}}AFX_DATA_INIT
// Initialize bitmap buttons:
m_cNext.Initialize (IDB_NEXT, IDB_NEXTGRAY);
m_cPrev.Initialize (IDB_PREVIOUS, IDB_PREVIOUSGRAY);
m_cNew.Initialize (IDB_NEWITEM, IDB_NEWITEMGRAY);
m_cDuplicate.Initialize (IDB_DUPITEM, IDB_DUPITEMGRAY);
m_cDelete.Initialize (IDB_DELETEITEM, IDB_DELETEITEMGRAY);
m_cValidate.Initialize (IDB_VALIDATEITEM, IDB_VALIDATEITEMGRAY);
}
// **************************************************************************
// ~CKItemAddDlg ()
//
// Description:
// Destructor.
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKItemAddDlg::~CKItemAddDlg ()
{
// Save registry settings:
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszAutoValidate, m_bAutoValidate);
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszBrowseFlat, m_bBrowseFlat);
}
// **************************************************************************
// DoDataExchange ()
//
// Description:
// This method is called by the framework to exchange and validate dialog data.
//
// Parameters:
// CDataExchange *pDX A pointer to a CDataExchange object.
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::DoDataExchange (CDataExchange *pDX)
{
// Perform default processing:
CDialog::DoDataExchange (pDX);
// Exchange data between controls and associated member variables:
//{{AFX_DATA_MAP(CKItemAddDlg)
DDX_Text (pDX, IDC_ACCESSPATH, m_strAccessPath);
DDX_Check (pDX, IDC_ACTIVE, m_bActive);
DDX_Text (pDX, IDC_ITEMID, m_strItemID);
DDX_Text (pDX, IDC_FILTERLEAF, m_strFilterLeaf);
DDX_Text (pDX, IDC_FILTERBRANCH, m_strFilterBranch);
//}}AFX_DATA_MAP
DDX_Check (pDX, IDC_BROWSEFLAT, m_bBrowseFlat);
DDX_Check (pDX, IDC_AUTOVALIDATE, m_bAutoValidate);
// Transfer data type combo box index to vartype:
CComboBox *pCombo = (CComboBox *)GetDlgItem (IDC_DATATYPE);
// If save and validate, transfer data type combo box index to
// vartype member variable:
if (pDX->m_bSaveAndValidate)
{
CString strType;
pCombo->GetLBText (pCombo->GetCurSel (), strType);
m_vtDataType = VartypeFromString (strType);
}
// else use current member variable value to make combo box selection:
else
{
CString strType;
// Convert data type to combo box entry string:
switch (m_vtDataType & ~VT_ARRAY)
{
case VT_BOOL: strType = _T("Boolean"); break;
case VT_UI1: strType = _T("Byte"); break;
case VT_I1: strType = _T("Char"); break;
case VT_UI2: strType = _T("Word"); break;
case VT_I2: strType = _T("Short"); break;
case VT_UI4: strType = _T("DWord"); break;
case VT_I4: strType = _T("Long"); break;
case VT_R4: strType = _T("Float"); break;
case VT_R8: strType = _T("Double"); break;
case VT_BSTR: strType = _T("String"); break;
default: strType = _T("Native"); break;
}
// Update array flag data:
if ((m_vtDataType & VT_ARRAY) != 0)
strType += _T(" Array");
// Select combo box entry:
pCombo->SelectString (-1, strType);
}
}
/////////////////////////////////////////////////////////////////////////////
// CKItemAddDlg message handlers
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// OnInitDialog ()
//
// Description:
// Called immediately before the dialog box is displayed. Use opportunity
// to initialize controls.
//
// Parameters:
// none
//
// Returns:
// BOOL - TRUE.
// **************************************************************************
BOOL CKItemAddDlg::OnInitDialog ()
{
CDialog::OnInitDialog ();
// Limit the access path to 255 chars:
((CEdit *)GetDlgItem (IDC_ACCESSPATH))->LimitText (255);
// Allow 10 levels of 32 character names plus a tag name of 31 characters:
((CEdit *)GetDlgItem (IDC_ITEMID))->LimitText (10*32 + 31);
// Subclass image buttons:
m_cNext.SubclassDlgItem (IDC_NEXT, this);
m_cPrev.SubclassDlgItem (IDC_PREVIOUS, this);
m_cNew.SubclassDlgItem (IDC_NEW, this);
m_cDuplicate.SubclassDlgItem (IDC_DUPLICATE, this);
m_cDelete.SubclassDlgItem (IDC_DELETE, this);
m_cValidate.SubclassDlgItem (IDC_VALIDATEITEM, this);
// Create tool tips for the image buttons:
m_cToolTip.Create (this);
m_cToolTip.AddWindowTool (&m_cNext);
m_cToolTip.AddWindowTool (&m_cPrev);
m_cToolTip.AddWindowTool (&m_cNew);
m_cToolTip.AddWindowTool (&m_cDuplicate);
m_cToolTip.AddWindowTool (&m_cDelete);
m_cToolTip.AddWindowTool (&m_cValidate);
// Get our group's item management interface pointer for the group:
m_pIItemMgt = m_pGroup->GetIItemMgt ();
// Intialize our item browser:
InitializeBrowser ();
// Intialize control status:
UpdateStatus ();
// return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
return (TRUE);
}
// **************************************************************************
// OnShowWindow ()
//
// Description:
// This method is called by the framework when this dialog is about to be
// hidden or shown. Use opportunity to set focus.
//
// Parameters:
// BOOL bShow TRUE if the window is being shown; FALSE if
// the window is being hidden.
// UINT nStatus Specifies the status of the window being shown.
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::OnShowWindow (BOOL bShow, UINT nStatus)
{
// Perform default processing:
CDialog::OnShowWindow (bShow, nStatus);
// If showing dialog, set focus to item ID edit box:
if (bShow)
GetDlgItem (IDC_ITEMID)->SetFocus ();
}
// **************************************************************************
// OnOK ()
//
// Description:
// Override to perform the OK button action in a modal dialog box. Use
// opportunity to apply changes.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::OnOK ()
{
// Apply any outstanding changes:
if (OnApplyChange ())
{
// Terminate the list. Will allow us to process list using
// "while (element)" loop if we want:
if (m_nListIndex > 0)
m_cItemList.SetAtGrow (m_nListIndex, NULL);
// Perform default processing:
CDialog::OnOK ();
}
}
// **************************************************************************
// OnCancel ()
//
// Description:
// Override to perform the Cancel button or ESC key action. Use opportunity
// to free any items created.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::OnCancel ()
{
// Free any items we created:
for (int nIndex = 0; nIndex < m_nListIndex; nIndex++)
{
// Get next element in list:
CKItem *pItem = (CKItem *) m_cItemList.GetAt (nIndex);
ASSERT (pItem != NULL);
// Delete it:
delete pItem;
}
// Perform default processing:
CDialog::OnCancel ();
}
// **************************************************************************
// OnNew ()
//
// Description:
// New button event handler. Select a new item for edits.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::OnNew ()
{
// No item currently in list should be selected on new:
SelectItem (-1);
}
// **************************************************************************
// OnDuplicate ()
//
// Description:
// Duplicate button event handler. Duplicate the current item.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemAddDlg::OnDuplicate ()
{
// Validate selected item first, and see if it has an address with
// a dot bit format:
bool bDotBitAddress = false;
HRESULT hr = Validate (&bDotBitAddress);
// If current item is not valid, don't duplicate it. Instead,
// tell user something is wrong with selected item:
if (FAILED (hr))
{
// Define a string format for the validation return code:
CString strHR;
strHR.Format (_T("0x%08X"), hr);
// Create an error string using above format for return code::
CString strFailure;
strFailure.FormatMessage (IDS_VALIDATE_ITEM_FAILED, m_strItemID, strHR);
// Display a message box with error string:
AfxMessageBox (strFailure);
// Return now so we don't duplicate invalid item:
return;
}
// Create a duplicate item dialog. This will allow the user to specify
// how many duplicates to make::
CKDuplicateItemCountDlg dlg;
// Show as modal dialog. Duplicate item only if user hits "OK":
if (dlg.DoModal () == IDOK)
{
// 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;
// Postpone repaint until we are done. This will make things go
// faster and look smoother:
SetRedraw (false);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -