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

📄 timestmp.cpp

📁 PC客户和opc通信的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// **************************************************************************
// timestmp.cpp
//
// Description:
//	Implements a class to contain time stamp data.
//
// 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 "timestmp.h"

// Define number of day in each month:
static unsigned short anDaysPerMonth [] =
	{
	31,	// January
	28,	// February (except leap year)
	31,	// March
	30,	// April
	31,	// May
	30,	// June
	31,	// July
	31,	// August
	30,	// September
	31,	// October
	30,	// November
	31	// December
	};

// Private static member initialization:
INTLDATEFORMAT CTimeStamp::stDateFmt;
INTLTIMEFORMAT CTimeStamp::stTimeFmt;
HWND CTimeStamp::sm_hwndNotify = NULL;
CCriticalSection CTimeStamp::sm_cs;


// **************************************************************************
// NotifyWndProc ()
//
// Description:
//	Hidden window proc for window created in GlobalInit ().  Used to to keep
//	us infored of date and time format changes.
//
// Parameters:
//  HWND		hWnd		Handle to the window procedure that received the 
//							  message. 
//	UINT		msg			Specifies the message. 
//	WPARAM		wParam		Specifies additional message information. The 
//							  content of this parameter depends on the value
//							  of the Msg parameter. 
//	LPARAM		lParam		Specifies additional message information. The 
//							  content of this parameter depends on the value
//							  of the Msg parameter. 
//
// Returns:
//  long - The return value is the result of the message processing and 
//  depends on the message. 
// **************************************************************************
long WINAPI CTimeStamp::NotifyWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
	// Processes WM_WININICHANGE (application ini file change) and WM_SETTINGCHANGE
	// (system setting change) messages:
	if (msg == WM_WININICHANGE || msg == WM_SETTINGCHANGE)
		{
		// Reset the date time format:
		SetDateTimeFormat ();

		// Force a repaint:
		AfxGetMainWnd ()->Invalidate ();
		}

	// Perform default processing and return result:
	return (DefWindowProc (hWnd, msg, wParam, lParam));
	}

// **************************************************************************
// GlobalInit ()
//
// Description:
//	This function must be called once by the application using this class
//	so that a hidden window may be be created to recieve system change
//	notifications.  These notifications will trigger an update of the
//	internal settings used when formatting dates and times.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CTimeStamp::GlobalInit ()
	{
	// Create our settings change notification window if it hasn't already
	// been created (indicated by NULL handle):
	if (!sm_hwndNotify)
		{
		WNDCLASS wc;
		
		// Get handle to current application instance (needed to define
		// hidden window):
		HINSTANCE hInst = AfxGetInstanceHandle ();
		ASSERT (hInst);

		// Define hidden window class:
		wc.style         = 0;		// style
		wc.lpfnWndProc   = CTimeStamp::NotifyWndProc;	// pointer to window procedure
		wc.cbClsExtra    = 0;		// number of extra bytes to allocate following the window-class structure
		wc.cbWndExtra    = 0;		// number of extra bytes to allocate following the window instance
		wc.hIcon         = NULL;	// handle to the class icon
		wc.hCursor       = NULL;	// handle to the class cursor
		wc.hInstance     = hInst;	// handle to the instance that contains the window procedure for the class
		wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);	// handle to the class background brush
		wc.lpszMenuName  = 0;					// resource name of menu resource
		wc.lpszClassName = _T("__TCN_CLASS__"); // window class name

		// Register our hidden window class:
		RegisterClass (&wc);

		// Create a hidden window:
		sm_hwndNotify = ::CreateWindow (
			wc.lpszClassName,	// registered class name
			_T(""),				// window name
			0,					// window style
			0, 0,				// horizontal, vertical position of window
			0, 0,				// window width, height
			NULL,				// handle to parent or owner window
			NULL,				// menu handle or child identifier
			hInst,				// handle to application instance
			NULL);				// window-creation data

		ASSERT (sm_hwndNotify);
		TRACE (_T("Time change notification window created (HWND == %08X)\n"), sm_hwndNotify);

		// Initialize the statics:
		SetDateTimeFormat ();
		}
	}

// **************************************************************************
// CTimeStamp ()
//
// Description:
//	Constructor.
//
// Parameters:
//  SYSTEMTIME	&st		Structure containing the initial time and date.	
//
// Returns:
//  none
// **************************************************************************
CTimeStamp::CTimeStamp (SYSTEMTIME &st)
	{
	// Test input data (for debugging only):
	ASSERT (st.wMonth >= 1 && st.wMonth <= 12);
	ASSERT (st.wHour >= 0 && st.wHour <= 23);
	ASSERT (st.wMinute >= 0 && st.wMinute <= 59);
	ASSERT (st.wSecond >= 0 && st.wSecond <= 59);
	ASSERT (st.wMilliseconds >= 0 && st.wMilliseconds <= 999);

	// Save input data:
	m_st = st;

	// Convert date to day of year:
	ConvertDateToDays ();

	// Convert time to milliseconds since midnight:
	ConvertTimeToMS ();
	}

// **************************************************************************
// Assign ()
//
// Description:
//	Assigns time and date specified in st, and performs date and time 
//	conversion if specified by bInitialize.
//
// Parameters:
//	SYSTEMTIME	&st			Structure containing the time and data.
//	bool		bInitialize	Set to true to initialize member variables.
//
// Returns:
//  void
// **************************************************************************
void CTimeStamp::Assign (SYSTEMTIME &st, bool bInitialize)
	{
	// Test input data (for debugging only):
	ASSERT (st.wMonth >= 1 && st.wMonth <= 12);
	ASSERT (st.wHour >= 0 && st.wHour <= 23);
	ASSERT (st.wMinute >= 0 && st.wMinute <= 59);
	ASSERT (st.wSecond >= 0 && st.wSecond <= 59);
	ASSERT (st.wMilliseconds >= 0 && st.wMilliseconds <= 999);

	// Save input data:
	m_st = st;

	// Initialize (convert date and time) if requested:
	if (bInitialize)
		{
		ConvertDateToDays ();
		ConvertTimeToMS ();
		}
	}

// **************************************************************************
// Assign ()
//
// Description:
//	Assigns current local time and date, and performs date and time 
//	conversion.
//
// Parameters:
//  none
//
// Returns:
//  void
// **************************************************************************
void CTimeStamp::Assign ()
	{
	// Set member variables for local time:
	GetLocalTime (&m_st);

	// Convert date to day of year:
	ConvertDateToDays ();

	// Convert time to milliseconds since midnight:
	ConvertTimeToMS ();
	}

// **************************************************************************
// SetTime ()
//
// Description:
//	Set the time.
//
// Parameters:
//	LPCTSTR		lpTime		Pointer to string representation of time.  Time
//							  must be in hh:mm:ss AM/PM format.  Delimiter
//							  could be that specified in system time format
//							  instead of ":".
//	bool		bInitialize	Set to true to initialize member variables.
//
// Returns:
//  bool - true if success
// **************************************************************************
bool CTimeStamp::SetTime (LPCTSTR lpTime, bool bInitialize)
	{
	SYSTEMTIME tm;
	int nState = 1;
	TCHAR ch;
	TCHAR chSep;
	BOOL bPM = FALSE;

	// 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 (&sm_cs);

	// Formatting info must be initialized:
	if (!stTimeFmt.nFmtLen)
		SetDateTimeFormat ();

	// Determine the selected delimiter:
	chSep = *stTimeFmt.szSeparator;

	// Initialize seconds in case they are not specified:
	tm.wSecond = 0;

	// Parse lpTime string using state machine approach.  (What we see
	// now determines the state.  The state determines what we expect
	// to see next).  Initial state set to 1.
	// (Loop until we get NULL terminator or nState set to -1 which
	// flags an invalid time string.)
	while (*lpTime && nState != -1)
		{
		// Save off current character, then increment pointer so we get next
		// character in string next time around loop:
		ch = *lpTime++;

		// Skip all whitespace:
		if (_istspace (ch))
			continue;

		// Process character according to state:
		switch (nState)
			{
			// Looking for white space or first hour digit:
			case 1:
				// If character is a digit, we will assume it is the first
				// digit of the hour.  Save as hour and set state to 2:
				if (_istdigit (ch))
					{
					tm.wHour = ch - _T('0'); // Convert from ASCII
					++nState;
					}

				// Else character is invalid.  Set state to -1 to break out
				// of loop:
				else
					nState = -1;

				break;

			// Looking for second hour digit or separator:
			case 2:
				// If characer is a digit, we will assume it is the second
				// digit of the hour.  Update hour and set state to 3:
				if (_istdigit (ch))
					{
					tm.wHour *= 10; // First digit parsed becomes second digit
					tm.wHour += (ch - _T('0')); // Convert from ASCII
					++nState;
					}

				// If character is a separator, set state to 4:
				else if (ch == chSep || ch == _T(':'))
					nState = 4;

				// Else character is invalid.  Set state to -1 to break out
				// of loop:
				else
					nState = -1;

				break;

			// Looking for a separator:
			case 3:
				// If character is a separator, set state to 4:
				if (ch == chSep || ch == _T(':'))
					nState = 4;

				// Else character is invalid.  Set state to -1 to break out
				// of loop:
				else
					nState = -1;

				break;

			// Looking for first minute digit:
			case 4:
				// If character is a digit, we will assume it is the first
				// digit of minute.  Save as minute and set state to 5:
				if (_istdigit (ch))
					{
					tm.wMinute = ch - _T('0'); // Convert from ASCII
					++nState;
					}

				// Else character is invalid.  Set state to -1 to break out
				// of loop:
				else
					nState = -1;

				break;

			// Looking for second minute digit, separator or first character
			// of "AM" or "PM":
			case 5:
				// If characer is a digit, we will assume it is the second
				// digit of the minute.  Update minute and set state to 6:
				if (_istdigit (ch))
					{
					tm.wMinute *= 10; // First digit parsed becomes second digit
					tm.wMinute += (ch - _T('0')); // Convert from ASCII
					++nState;
					}

				// Else if character is a separator, set state to 7:
				else if (ch == chSep || ch == _T(':'))
					nState = 7;

				// Else if character is an "a" or "A", set state to 11:
				else if (ch == _T('a') || ch == _T('A'))
					nState = 11;

				// Else if character is a "p" or "P", set state to 11:
				else if (ch == _T('p') || ch == _T('P'))
					{
					nState = 11;
					bPM = TRUE;
					}

				// Else character is invalid.  Set state to -1 to break out
				// of loop:
				else
					nState = -1;

				break;

			// Looking for a separator or first character of "AM" or PM":
			case 6:
				// If character is a separator, set state to 7:
				if (ch == chSep || ch == _T(':'))
					nState = 7;

				// Else if character is an "a" or "A", set state to 11:
				else if (ch == _T('a') || ch == _T('A'))
					nState = 11;

				// Else if character is a "p" or "P", set state to 11:

⌨️ 快捷键说明

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