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

📄 stockquotes_.cpp

📁 一个补票分析程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// StockQuotes_.cpp : Implementation of CStockQuotes
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "stockquotes.h"
#include "StockQuotes_.h"
#include "enumstocks.h"
#include "stockupdatenotify.h"

#pragma warning ( disable : 4018 4239 )

static bool  g_bStopUpdating = false;   // stop updating now.
bool         g_bUpdating = false;       // currently updating data from net?

/////////////////////////////////////////////////////////////////////////////
// CEnumStocksAsString

CEnumStocksAsString::~CEnumStocksAsString()
{
	// delete all the stock symbols.
	//
	for (CStocksAsString::iterator i = m_stocksAsString.begin();
		 i != m_stocksAsString.end(); i++)
	{
		::SysFreeString(*i);
	}
	m_stocksAsString.clear();
}

// Return next N stocks, formated in a string.
//
STDMETHODIMP CEnumStocksAsString::Next(ULONG celt, LPOLESTR* rgelt, ULONG* pceltFetched)
{
	if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
		return E_POINTER;
	if (m_iterCur == m_stocksAsString.end())
		return E_FAIL;
	ULONG nRem = (ULONG)(m_stocksAsString.end() - m_iterCur);
	HRESULT hRes = S_OK;
	if (nRem < celt)
		hRes = S_FALSE;
	ULONG nMin = min(celt, nRem);
	if (pceltFetched != NULL)
		*pceltFetched = nMin;
	while(nMin--)
		CCopy::copy(rgelt++, &(*m_iterCur++));
	return hRes;
}

// Skip the next N stocks.
//
STDMETHODIMP CEnumStocksAsString::Skip(ULONG celt)
{
	if (m_stocksAsString.end() - m_iterCur <  celt)
	{
		m_iterCur = m_stocksAsString.end();
		return S_FALSE;
	}
	m_iterCur += celt;
	return S_FALSE;
}

// Start at the begining.
//
STDMETHODIMP CEnumStocksAsString::Reset(void)
{
	m_iterCur = m_stocksAsString.begin();
	return S_OK;
}

// Make a copy.
//
STDMETHODIMP CEnumStocksAsString::Clone(IEnumString** ppEnum)
{
	typedef CComObject<CEnumStocksAsString> _class;
	HRESULT hRes = E_POINTER;
	if (ppEnum != NULL)
	{
		_class* p = NULL;
		ATLTRY(p = new _class)
		if (p == NULL)
		{
			*ppEnum = NULL;
			hRes = E_OUTOFMEMORY;
		}
		else
		{
			hRes = p->Init(m_stocksAsString.begin(), m_stocksAsString.end(),
						   m_iterCur);
			if (FAILED(hRes))
				delete p;
			else
			{
				hRes = p->_InternalQueryInterface(IID_IEnumString, (void**)ppEnum);
				if (FAILED(hRes))
					delete p;
			}
		}
	}
	return hRes;
}

// Helper to initialize object.  Use given iterators to transform CStock info
// into a string.  The string has the form: <symbol>: <price>(<change>) OR
// <symbol>: <NA> if stock data is not available.
//
void CEnumStocksAsString::Init(CStockList::iterator s, CStockList::iterator e)
{
	for (CStockList::iterator i = s; i != e; i++)
	{
		CStock      stock = *i;
		CString     str;
		str = stock.GetSymbol();
		str += _T(": ");
		str += stock.GetCurrent();
		if (stock.GetCurrent() != _T("<NA>"))
		{
			str += _T("(");
			str += stock.GetChange() + _T(")");
		}

		m_stocksAsString.push_back(str.AllocSysString());
	}
	m_iterCur = m_stocksAsString.begin();
}

// Initialize from a CStockAsString object - similar to a copy contructor.
//
HRESULT CEnumStocksAsString::Init(CStocksAsString::iterator s,
								  CStocksAsString::iterator e,
								  CStocksAsString::iterator cur)
{
	for (; s != e; s++)
		m_stocksAsString.push_back(::SysAllocString(*s));
	m_iterCur = m_stocksAsString.begin() + (cur - s);
	return S_OK;
}



/////////////////////////////////////////////////////////////////////////////
// CStockQuotes

// If the notify thread is going post message to it and return immediately .
// Otherwise update now, in which case the function will not return until
// the download is complete.
//
STDMETHODIMP CStockQuotes::Update()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	if (m_pStockUpdateNotify)
	{
		m_pStockUpdateNotify->PostThreadMessage(WM_STOCK_UPDATE_NOTIFY_NOW, 0, 0);
		return S_OK;
	}
	else
		return DoUpdate();
}

// Add a stock.  If the stock symbol is already added then do nothing.
//
STDMETHODIMP CStockQuotes::Add(BSTR bstrSymbol)
{
	Lock();

	CStock  s(bstrSymbol);
	if (std::find(m_stockList.begin(), m_stockList.end(), s) ==
		m_stockList.end())
		m_stockList.push_back(s);
	Unlock();
	return S_OK;
}

// Remove a stock.
//
STDMETHODIMP CStockQuotes::Remove(BSTR bstrSymbol)
{
	Lock();
	CStockListIter i = std::find(m_stockList.begin(),
								 m_stockList.end(), CStock(CString(bstrSymbol)));
	if (i != m_stockList.end())
		m_stockList.erase(i);
	Unlock();
	return S_OK;
}

// Return an IEnumString object which contains the formated stock information.
//
STDMETHODIMP CStockQuotes::EnumAsString(IEnumString** ppEnum)
{
	if (ppEnum == NULL)
		return E_POINTER;
	*ppEnum = NULL;
	CComObject<CEnumStocksAsString>* pEnum = NULL;
	ATLTRY(pEnum = new CComObject<CEnumStocksAsString>);
	if (pEnum == NULL)
		return E_OUTOFMEMORY;
	Lock();
	pEnum->Init(m_stockList.begin(), m_stockList.end());
	Unlock();
	HRESULT hRes = pEnum->QueryInterface(IID_IEnumString, (void**)ppEnum);
	if (FAILED(hRes))
		delete pEnum;
	return hRes;
}

// Return an IEnumStocks object which contains the raw stock data.
//
STDMETHODIMP CStockQuotes::EnumStocks(IEnumStocks** ppEnum)
{
	if (ppEnum == NULL)
		return E_POINTER;
	*ppEnum = NULL;
	CComObject<CEnumStocks>* pEnum = NULL;
	ATLTRY(pEnum = new CComObject<CEnumStocks>);
	if (pEnum == NULL)
		return E_OUTOFMEMORY;
	Lock();
	pEnum->Init(m_stockList.begin(), m_stockList.end());
	Unlock();
	HRESULT hRes = pEnum->QueryInterface(IID_IEnumStocks, (void**)ppEnum);
	if (FAILED(hRes))
		delete pEnum;
	return hRes;
}

// Return number of stocks being tracked.
//
STDMETHODIMP CStockQuotes::StockCount(int* cnt)
{
	*cnt = (int)m_stockList.size();
	return S_OK;
}

//
// Save stock symbols to given stream.
//
STDMETHODIMP CStockQuotes::Save(IStream* pIStream)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	Lock();
	COleStreamFile  file(pIStream);
	int size = (int)m_stockList.size();  // number of stock symbols to save.
	file.Write(&size, sizeof(size));
	for (CStockListIter i = m_stockList.begin(); i != m_stockList.end(); i++)
		SaveString(file, (*i).GetSymbol());

	// save URLs
	//
	CStockQuoteSource*  p = m_sqsList.GetMSInvestor();
	CString             strEmpty(_T(""));
	if (p)
		SaveString(file, p->GetURL());
	else
		SaveString(file, strEmpty);
	p = m_sqsList.GetStockSourceISAPIDll();
	if (p)
		SaveString(file, p->GetURL());
	else
		SaveString(file, strEmpty);

	file.Detach();      // don't want to close the stream.
	Unlock();
	return S_OK;
}

// Load stock symbols from given stream.
//
STDMETHODIMP CStockQuotes::Load(IStream* pIStream)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	Lock();
	COleStreamFile  file(pIStream);

	m_stockList.clear();            // remove all stocks.
	int             size = 0;
	CString         strTmp;
	file.Read(&size, sizeof(size)); // number of stock symbols to read.
	for (int i = 0; i < size; i++)
	{
		LoadString(file, strTmp);
		m_stockList.push_back(CStock(strTmp));      // add to list.
	}

	// load URLs.
	//
	CStockQuoteSource*  p;
	LoadString(file, strTmp);
	if (strTmp.GetLength())
	{
		p = m_sqsList.GetMSInvestor();
		if (p)
			p->SetURL(strTmp);
	}
	LoadString(file, strTmp);
	if (strTmp.GetLength())
	{
		p = m_sqsList.GetStockSourceISAPIDll();
		if (p)
			p->SetURL(strTmp);
	}

	file.Detach();      // don't want to close stream.
	Unlock();
	return S_OK;
}

// Create worker thread that will setup a timer and call back into us
// every "nUpdateInterval" minutes.  If the tread is already runniing just
// adjust the update interval.
//
STDMETHODIMP CStockQuotes::StartUpdating(int nUpdateInterval)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	if (!m_pStockUpdateNotify)
	{
		m_pStockUpdateNotify =
			(CStockUpdateNotify*)AfxBeginThread(RUNTIME_CLASS(CStockUpdateNotify));
		m_pStockUpdateNotify->Init(this);
	}
	if (m_pStockUpdateNotify)
		m_pStockUpdateNotify->SetNotifyInterval(nUpdateInterval);
	return S_OK;
}

// If we are updating (accessing the net) close the connection.  Terminate
// notification thread.
//
STDMETHODIMP CStockQuotes::StopUpdating()
{
	ShutdownUpdating();
	return S_OK;
}

// Set flag indicating that notifications should not occur.
//
STDMETHODIMP CStockQuotes::PauseUpdating()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	if (m_pStockUpdateNotify)
		m_pStockUpdateNotify->SuspendNotifications();
	return S_OK;
}

// Get and Set MS Investor and stock source ISAPI dll URLs.
//
STDMETHODIMP CStockQuotes::SetMSInvestorURL(BSTR newVal)
{
	CStockQuoteSource* pSQS = m_sqsList.GetMSInvestor();
	if (pSQS)
		pSQS->SetURL(newVal);

	return S_OK;
}

STDMETHODIMP CStockQuotes::GetMSInvestorURL(BSTR * pVal)
{
	USES_CONVERSION_EX;

	BSTR strTmp;
	if ((strTmp=T2BSTR_EX(_T("")))==NULL)
		return E_OUTOFMEMORY;
	CComBSTR bstr(strTmp);
	CStockQuoteSource* pSQS = m_sqsList.GetMSInvestor();
	if (pSQS)
	{
		if ((strTmp=T2BSTR_EX((LPCTSTR)pSQS->GetURL()))==NULL)
			return E_OUTOFMEMORY;
		bstr = strTmp;
	}
	*pVal = bstr.Detach();

	return S_OK;
}

STDMETHODIMP CStockQuotes::SetStockSourceISAPIDllURL(BSTR newVal)
{
	CStockQuoteSource* pSQS = m_sqsList.GetStockSourceISAPIDll();
	if (pSQS)
		pSQS->SetURL(newVal);

	return S_OK;
}

STDMETHODIMP CStockQuotes::GetStockSourceISAPIDllURL(BSTR * pVal)
{
	USES_CONVERSION_EX;

	BSTR strTmp;
	if ((strTmp=T2BSTR_EX(_T("")))==NULL)
		return E_OUTOFMEMORY;
	CComBSTR bstr(strTmp);
	CStockQuoteSource* pSQS = m_sqsList.GetStockSourceISAPIDll();
	if (pSQS)
	{
		if ((strTmp=T2BSTR_EX((LPCTSTR)pSQS->GetURL()))==NULL)
			return E_OUTOFMEMORY;
		bstr = strTmp;
	}
	*pVal = bstr.Detach();

	return S_OK;
}

// Close any pending updates and terminate thread.
//
void CStockQuotes::FinalRelease()
{
	ShutdownUpdating();
}

HRESULT CStockQuotes::FinalConstruct()
{
	return S_OK;
}

// Connect to net and download data for all stocks.  Close session (connection)
// at end of download.
//
HRESULT CStockQuotes::DoUpdate()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
	if (g_bUpdating)
		return S_OK;

	Lock();
	g_bUpdating = true;
	DWORD dwAccessType;
	dwAccessType = PRE_CONFIG_INTERNET_ACCESS;

	try
	{
		m_pINetSession = new CInternetSession(_T("Stock Quotes"));

		for (CStockListIter i = m_stockList.begin();
			 !g_bStopUpdating && i != m_stockList.end(); i++)
		{
			bool    bFoundInfo = false;
			for (CSQSList::iterator j = m_sqsList.begin();
				 !g_bStopUpdating && j != m_sqsList.end(); j++)
			{
				if ((*j)->Update(*m_pINetSession, *i))
				{
					bFoundInfo = true;
					break;
				}
			}
			if (!bFoundInfo)   // no stock info, set indicator string.
				i->SetCurrent(_T("<NA>"));
		}
		Fire_InfoUpdate();
	}
	catch(CInternetException* e)
	{
		// if closed prematurely then ok, otherwise let user know.
		//
		if (e->m_dwError != ERROR_INVALID_HANDLE)
		{
			TCHAR   buf[1025];
			e->GetErrorMessage(buf, 1024);
			::MessageBox(0, buf, _T("Stock Quotes Component Error"),

⌨️ 快捷键说明

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