www.pudn.com > OPC_VC++.rar > OPCSample_cppDlg.cpp


// OPCSample_cppDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "OPCSample_cppDlg.h" 
#include "OPCSample_cpp.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// COPCSample_cppDlg dialog 
 
COPCSample_cppDlg::COPCSample_cppDlg(COPCSample_cppApp *p, CWnd* pParent /*=NULL*/) 
	: CDialog(COPCSample_cppDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(COPCSample_cppDlg) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
  pcApp = p; 
  pcBrowse=NULL; 
  pdwServerHandles=NULL; 
  pcApp->pcServer->QueryInterface(IID_IOPCBrowseServerAddressSpace,(LPVOID*)&pcBrowse); 
  pcApp->pcGroup->QueryInterface(IID_IOPCItemMgt, (LPVOID*)&pcItemMgt); 
} 
 
void COPCSample_cppDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(COPCSample_cppDlg) 
	DDX_Control(pDX, IDC_TREE, m_Tree); 
	DDX_Control(pDX, IDC_LIST, m_List); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(COPCSample_cppDlg, CDialog) 
	//{{AFX_MSG_MAP(COPCSample_cppDlg) 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelchangedTree) 
	ON_WM_TIMER() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// COPCSample_cppDlg message handlers 
#define DLG_TIMER_ID WM_TIMER + 2 
 
BOOL COPCSample_cppDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
 
  m_List.InsertColumn(0, "ItemID", LVCFMT_LEFT, 150); 
  m_List.InsertColumn(1, "Quality", LVCFMT_LEFT, 80); 
  m_List.InsertColumn(2, "Type", LVCFMT_LEFT, 50); 
  m_List.InsertColumn(3, "Value", LVCFMT_LEFT, 150); 
  InitializeTree(); 
  SetTimer(DLG_TIMER_ID, 250, NULL ); 
	 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void COPCSample_cppDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR COPCSample_cppDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
void COPCSample_cppDlg::InitializeTree()  
{ 
  // Fill the tree with the server's hierarchy 
  m_Tree.SetRedraw(FALSE); 
  m_List.SetRedraw(FALSE); 
  HTREEITEM  first=0; 
  UpdateData(); 
  m_Tree.DeleteAllItems(); 
  if( pcBrowse ) 
  { 
    IEnumString*  pEnumString = NULL; 
    CString       csAdd; 
 
    HRESULT hr = pcBrowse->BrowseOPCItemIDs(OPC_BRANCH,  
      csAdd.AllocSysString(),  
      VT_EMPTY,  
      OPC_READABLE | OPC_WRITEABLE,  
      &pEnumString); 
     
    if( hr == S_OK ) 
    { 
      LPWSTR pName = NULL; 
      ULONG count = 0; 
      while( (hr = pEnumString->Next(1, &pName, &count)) == S_OK ) 
      { 
        // CString does translation from UNICODE to native type 
        // (depends on the way the application is built) 
        CString name( pName );   
        HTREEITEM item = m_Tree.InsertItem( name ); 
        if( first == 0 ) 
          first = item; 
        InsertChildren( pName, item ); 
        CoTaskMemFree( pName ); 
      } 
      pEnumString->Release(); 
    } 
  } 
  m_Tree.SelectItem( first ); 
  m_Tree.SetRedraw(TRUE); 
  m_List.SetRedraw(TRUE); 
} 
 
void COPCSample_cppDlg::InsertChildren( LPWSTR child, HTREEITEM hParent ) 
{ 
  HRESULT hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_DOWN, (LPCWSTR)child ); 
  if( FAILED(hr) ) 
    return; 
  IEnumString*  pEnumString = NULL; 
  CString       csAdd; 
  hr = pcBrowse->BrowseOPCItemIDs( OPC_BRANCH,  
    csAdd.AllocSysString(), 
    VT_EMPTY, 
    OPC_READABLE|OPC_WRITEABLE, 
    &pEnumString); 
   
  if( hr == S_OK ) 
  { 
    LPWSTR pName = NULL; 
    ULONG count = 0; 
    while( (hr = pEnumString->Next(1, &pName, &count)) == S_OK ) 
    { 
      CString name( pName );  // translation 
      HTREEITEM item = m_Tree.InsertItem( name, hParent ); 
      InsertChildren( pName, item ); 
      CoTaskMemFree( pName ); 
    } 
    pEnumString->Release(); 
  } 
  hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_UP, L"" ); 
} 
 
void COPCSample_cppDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
  //set the group to inactive to avoid callbacks 
  HRESULT hr; 
  BOOL  boActive=FALSE; 
  DWORD dwRate; 
  hr = pcApp->pcGroup->SetState( NULL,&dwRate,&boActive,NULL,NULL,NULL,NULL); 
  if (!SUCCEEDED(hr)) 
  { 
    AfxMessageBox("Call of SetState failed"); 
  } 
  //remove all Tags from the group 
  HRESULT *pOPCErrors=NULL; 
  if (pdwServerHandles) 
  { 
    m_List.SetRedraw(FALSE); 
    DWORD count = m_List.GetItemCount(); 
 
    pcItemMgt->RemoveItems( count,//number 
                            pdwServerHandles,//server handles 
                            &pOPCErrors//errors 
                            ); 
    if (pOPCErrors) 
      CoTaskMemFree( pOPCErrors ); 
    pOPCErrors=NULL; 
    delete [] pdwServerHandles; 
    pdwServerHandles=NULL; 
    m_List.DeleteAllItems(); 
  } 
  //get all tags of this branch 
   
  HTREEITEM item = m_Tree.GetSelectedItem( ); 
  hr = BrowseHere( item );    // move browse position here 
  if( SUCCEEDED(hr) ) 
  { 
    // get the tags 
    IEnumString* pEnumString = NULL; 
    CString csAdd; 
    hr = pcBrowse->BrowseOPCItemIDs(OPC_LEAF, 
      csAdd.AllocSysString(), 
      VT_EMPTY, 
      OPC_READABLE|OPC_WRITEABLE, 
      &pEnumString); 
     
    if( hr == S_OK ) 
    { 
      LPWSTR *pName = new LPWSTR[500]; 
      LPWSTR pItemID = NULL; 
      DWORD count = 0; 
      hr = pEnumString->Next(500, pName, &count); 
      if (count) 
      { 
        Item* pcItem; 
        OPCITEMDEF *pidef = new OPCITEMDEF[count] ; 
        CString csItemID; 
        for ( int i = 0; i<(int)count; i++ ) 
        { 
          // CString does translation from UNICODE to native type 
          // (depends on the way the application is built) 
          pcItem = new Item; 
          pcItem->quality = QUAL_BAD; 
 
          pcBrowse->GetItemID(pName[i],&pItemID); 
          pcItem->name = pItemID; 
 
          pidef[i].szItemID = pcItem->name.AllocSysString(); 
          pidef[i].dwBlobSize = 0; 
          pidef[i].pBlob = NULL; 
          pidef[i].bActive = TRUE; 
          pidef[i].hClient = (OPCHANDLE)pcItem;  // pointer to item is its "handle" 
          pidef[i].szAccessPath = pcItem->cAccessPath.AllocSysString(); 
          pidef[i].vtRequestedDataType = VT_EMPTY; 
         
          CoTaskMemFree( pItemID ); 
          CoTaskMemFree( pName[i] ); 
 
        } 
        OPCITEMRESULT * pOPCResults=NULL; 
        hr = pcItemMgt->AddItems(count, pidef, &pOPCResults, &pOPCErrors); 
        if( SUCCEEDED( hr ) ) 
        { 
          CString csOut; 
          csOut.Empty(); 
          int item=0; 
           
          pdwServerHandles = new DWORD[count]; 
          for (i=0; i<(int)count;i++) 
          { 
            if (pOPCErrors[i]==S_OK) 
            { 
              pdwServerHandles[i] = pOPCResults[i].hServer;  // save the server handle 
 
              //insert the tag in the list 
              CString cs; 
              cs = pidef[i].szItemID; 
              m_List.InsertItem(item, (LPCSTR)cs); 
              cs = "no update"; 
              m_List.SetItem(item, 1, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 ); 
              cs.Format("%u",pOPCResults[i].vtCanonicalDataType); 
              m_List.SetItem(item, 2, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 ); 
              cs = "no update"; 
              m_List.SetItem(item, 3, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 ); 
 
              m_List.SetItemData(item, (DWORD)pidef[i].hClient); 
              item++; 
            } else 
            { 
              CString cs; 
              cs.Format("Result <%lu> from AddItems for Item <%s>\n", 
                        pOPCErrors[i],     
                        (LPCTSTR)pidef[i].szItemID); 
              csOut += cs; 
            } 
            SysFreeString( pidef[i].szItemID ); 
            SysFreeString( pidef[i].szAccessPath ); 
          } 
        } 
        if (pOPCErrors) 
          CoTaskMemFree( pOPCErrors ); 
        pOPCErrors=NULL; 
        if (pOPCResults) 
          CoTaskMemFree( pOPCResults ); 
        pOPCResults=NULL; 
        delete [] pidef; 
      } 
      pEnumString->Release(); 
      if (pResult) 
        *pResult = 1; 
      delete [] pName; 
    } 
  } 
  hr = S_OK; 
  while(hr==S_OK) 
    hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_UP, L"" ); 
   
  if( pResult ) 
    *pResult = 0; 
  m_List.SetRedraw(TRUE); 
  //set the group to active to get changed data 
  boActive=TRUE; 
  hr = pcApp->pcGroup->SetState( NULL,&dwRate,&boActive,NULL,NULL,NULL,NULL); 
  if (!SUCCEEDED(hr)) 
  { 
    AfxMessageBox("Call of SetState failed"); 
  } 
} 
 
//************************************************************************** 
// Recursive function that moves the browse position to this tree item 
HRESULT COPCSample_cppDlg::BrowseHere( HTREEITEM item ) 
{ 
  HRESULT hr = S_OK; 
  if( item != NULL ) 
  { 
    HTREEITEM parent = m_Tree.GetParentItem( item ); 
    hr = BrowseHere( parent ); 
    if( SUCCEEDED( hr ) ) 
    { 
      CString name( m_Tree.GetItemText( item ) ); 
      hr = pcBrowse->ChangeBrowsePosition( OPC_BROWSE_DOWN, name.AllocSysString() ); 
    } 
  } 
  return hr; 
} 
 
 
void COPCSample_cppDlg::OnTimer(UINT nIDEvent)  
{ 
  DWORD     count = m_List.GetItemCount(); 
  VARIANT   Value; 
  CString   cs, cs1, cs2; 
  Value.vt = VT_EMPTY; 
  if (count) 
  { 
    int foundItem = m_List.GetNextItem( -1, LVNI_ALL ); 
    while( foundItem != -1 ) 
    { 
      Item* pcItem = (Item*)m_List.GetItemData( foundItem ); 
      if (pcItem->boActual) 
      { 
        if (pcItem->quality==QUAL_BAD) 
        { 
          cs1 = "Bad"; 
        } else if (pcItem->quality==QUAL_UNCERTAIN) 
        { 
          cs1 = "Uncertain"; 
        } else if (pcItem->quality==QUAL_GOOD) 
        { 
          cs1 = "Good"; 
        } 
        cs2.Format(" (%u)",pcItem->quality); 
        cs = cs1 + cs2; 
        m_List.SetItem(foundItem, 1, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 ); 
         
        HRESULT hr = VariantChangeType(&Value, &pcItem->value, 0, VT_BSTR); 
        if (hr==S_OK) 
        { 
          cs = Value.bstrVal; 
        } else 
        { 
          cs.Format("Variant error 0x(%x)", hr); 
        } 
        m_List.SetItem(foundItem, 3, LVIF_TEXT, (LPCSTR)cs, 0, 0, 0, 0 ); 
        pcItem->boActual=FALSE; 
      } 
      foundItem = m_List.GetNextItem( foundItem, LVNI_ALL ); 
    } 
  } 
	CDialog::OnTimer(nIDEvent); 
}