⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 document.cpp

📁 VisualC OPC Client Example C 程序开发
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// **************************************************************************
// document.cpp
//
// Description:
//	Implements a CDocument derived class.  This is the document part of our
//  MFC SDI document/view architecture.
//
// 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 "document.h"
#include "server.h"
#include "serverpropertysheet.h"
#include "group.h"
#include "grouppropertysheet.h"
#include "item.h"
#include "itemadddlg.h"

#define LARGE_ADDITEM_COUNT		64


/////////////////////////////////////////////////////////////////////////////
// CKDocument
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE (CKDocument, CDocument)

// **************************************************************************
BEGIN_MESSAGE_MAP (CKDocument, CDocument)
END_MESSAGE_MAP ()


/////////////////////////////////////////////////////////////////////////////
// CKDocument construction/destruction
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// CKDocument ()
//
// Description:
//	Constructor
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKDocument::CKDocument ()
	{
	// Initialize member variables:
	m_pServerHead = NULL;
	m_cdwServers = 0;

	m_pCurSelServer = NULL;
	m_pCurSelGroup = NULL;

	m_bLocked = false;
	}

// **************************************************************************
// ~CKDocument ()
//
// Description:
//	Destructor
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKDocument::~CKDocument ()
	{
	}

// **************************************************************************
// SetLocked ()
//
// Description:
//	Locks the document object.
//
// Parameters:
//	bool		bSet		Set to "true" to lock, "false" to unlock
//
// Returns:
//  void
// **************************************************************************
void CKDocument::SetLocked (bool bSet)
	{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csDoc);

	// Use a flag to indicate locked state:
	m_bLocked = bSet;
	}

// **************************************************************************
// IsLocked ()
//
// Description:
//	Returns the locked state of document object.
//
// Parameters:
//  none
//
// Returns:
//  bool - true if locked.
// **************************************************************************
bool CKDocument::IsLocked ()
	{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csDoc);

	// Return locked state:
	return (m_bLocked);
	}

// **************************************************************************
// OnNewDocument ()
//
// Description:
//	New document event handler.
//
// Parameters:
//  none
//
// Returns:
//  BOOL - TRUE if success.
// **************************************************************************
BOOL CKDocument::OnNewDocument ()
	{
	// Perform default processing:
	if (!CDocument::OnNewDocument ())
		return (FALSE);

	// SDI documents reuse this document so perform reinitialization:
	SetModified (FALSE);
	return (TRUE);
	}

// **************************************************************************
// OnOpenDocument ()
//
// Description:
//	Open document event handler.
//
// Parameters:
//  none
//
// Returns:
//  BOOL - TRUE if success.
// **************************************************************************
BOOL CKDocument::OnOpenDocument (LPCTSTR lpszPathName) 
	{
	// Perform default processing:
	if (!CDocument::OnOpenDocument (lpszPathName))
		return (FALSE);

	// Must do some additional work if we have a server object:
	if (m_pServerHead)
		{
		// Update status bar text to indicate we are loading project:
		CKStatusBarText cText (IDS_LOADING_PROJECT);

		// Update all views so the user can see progress:
		UpdateAllViews (NULL, HINT_LOAD_PROJECT, m_pServerHead);

		// Build a list of servers to load to pass along to a worker thread 
		// for processing:
		CObArray cServerList;

		// Catch memory exceptions that could get thrown by object array:
		try
			{
			// Allocate memory for array of server objects:
			cServerList.SetSize (m_cdwServers);

			// Create a CKServer pointer and set it to first server in linked list:
			CKServer *pServer = m_pServerHead;

			// Loop over servers in linked list:
			for (DWORD dw = 0; dw < m_cdwServers; dw++)
				{
				// Put pointer to server in object array:
				ASSERT (pServer);
				cServerList [dw] = (CObArray *)pServer;

				// Get next server in linked list:
				pServer = pServer->GetNext ();
				}

			ASSERT (pServer == NULL);	// list and count in sync ?
			}
		
		catch (CMemoryException *e)
			{
			// If memory exception thrown, delet exception object and return FALSE
			// to indicate failure.
			e->Delete ();
			return (FALSE);
			}

		// Fill a structre to pass along to worker thread.  Structure will
		// contain a pointer to out list of servers and task specification
		// (start multiple servers).
		WORKERTHREADARG tArg;
		tArg.eTask = WORKERTHREADARG::START_MULTIPLE_SERVER;
		tArg.pvObjectA = (void *)&cServerList;

		// Run the worker thread to start all server connections:
		RunWorkerThread (&tArg);
		}

	// If we make it here, all went OK, so return TRUE:
	return (TRUE);
	}

// **************************************************************************
// DeleteContents ()
//
// Description:
//	Reset the document object for reuse.  This includes disconnect from all
//	OPC servers and deleting all server objects.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CKDocument::DeleteContents () 
	{
	// 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;
	
	// Update status bar text to indicate that we are unloading project:
	CKStatusBarText cText (IDS_UNLOADING_PROJECT);
	
	// Notify all views that the project is closing so that no request for
	// server/group/item is made (as in OnGetDispInfo) for a deleted object:
	UpdateAllViews (NULL, HINT_CLOSE_PROJECT, NULL);

	// Free all server connections maintained by the document.  Start with
	// head of linked list and work our way to end:
	while (m_pServerHead)
		{
		// Need to make a copy of current head of linked list:
		CKServer *pServer = m_pServerHead;

		// Reset linked list head to next server:
		m_pServerHead = pServer->GetNext ();

		// Delete server (previously the head of linked list):
		RemoveServer (pServer);
		}

	// Check that we deleted all servers in linked list (debug only):
	ASSERT (m_cdwServers == 0);

	// Invalidate currently selected server and group:
	m_pCurSelServer = NULL;
	m_pCurSelGroup = NULL;

	// Default processing:
	CDocument::DeleteContents ();
	}

// **************************************************************************
// SetModified ()
//
// Description:
//	Set the document modified flag.  Update title bar to signal that document
//	has been modified.
//
// Parameters:
//  bool		bModified		Set to "true" if document has been modified.
//
// Returns:
//  void
// **************************************************************************
void CKDocument::SetModified (bool bModified /* = true */)
	{
	// If we are currently unmodified, we may need to add or remove an
	// asterisk from title bar. (The framework automatically clears the 
	// asterisk when saving the document):
	if (!IsModified ())
		{
		// Get document title:
		CString strTitle = GetTitle ();

		// If we are modifying, see if we should add asterisk:
		if (bModified)
			{
			// If we can't find an asterisk in title, we need to add one:
			if (strTitle.Find (_T(" *")) < 0)
				{
				strTitle += " *";
				SetTitle (strTitle);
				}
			}

		// Otherwise, remove asterisk if any:
		else
			{
			// If we can find an asterisk in title, we need to remove it:
			if (strTitle.Find (_T(" *")) >= 0)
				{
				strTitle.TrimRight (_T(" *"));
				SetTitle (strTitle);
				}
			}
		}

	// Set modified flag:
	SetModifiedFlag (bModified);
	}

// **************************************************************************
// OnServerShutdown ()
//
// Description:
//	Server shutdown event handler.
//
// Parameters:
//  CKServer		*pServer		Pointer to server that has given us a
//									shutdown notification.
//
// Returns:
//  void
// **************************************************************************
void CKDocument::OnServerShutdown (CKServer *pServer)
	{
	ASSERT (pServer != NULL);

	// Shutdown the server:
	pServer->Stop ();

	// Refresh our group view so that new active status is shown:
	UpdateAllViews (NULL, HINT_REFRESH_GROUPVIEW, NULL);
	}


////////////////////////////////////////////////////////////////////////////
// CKDocument serialization
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// Serialize ()
//
// Description:
//	Save or load project settings.
//
// Parameters:
//  CArchive		&ar			The archive to save or load project settings.
//
// Returns:
//  void
// **************************************************************************
void CKDocument::Serialize (CArchive &ar)
	{
	// Be prepared to catch exceptions:
	try
		{
		// Save project:
		if (ar.IsStoring ())
			{
			// Save the number of server object first so we will know how
			// many to load later:
			ar << m_cdwServers;

			// Now serialize each server object.  Start with head of linked
			// list and work our way to end:
			CKServer *pServer = m_pServerHead;

			// Keep looping until we hit end of linked list, indicated by 
			// a NULL pointer:
			while (pServer)			
				{
				// Serialize server object:
				pServer->Serialize (ar);

				// Get pointer to next server in linked list:
				pServer = pServer->GetNext ();
				}
			}

		// Else load project:
		else
			{
			// First get the number of servers to load:
			DWORD cdwServers;
			ar >> cdwServers;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -