Click here to Skip to main content
15,895,740 members
Articles / Desktop Programming / MFC

Introduces RSS Reader by AgileInfoSoftware

Rate me:
Please Sign up or sign in to vote.
4.38/5 (15 votes)
2 Dec 20032 min read 155.2K   1.1K   31  
This article introduces an application to consume RSS Feed from Internet.
// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "AgileReader.h"

#include "MainFrm.h"
#include "TreeViewEx.h"
#include "AgileReaderView.h"
#include "FeedDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_COMMAND(ID_FILE_SUBSCRIBERFEED, OnFileSubscriberfeed)
	ON_COMMAND(ID_EDIT_DELETE, OnEditDelete)
	ON_WM_CLOSE()
	ON_COMMAND(ID_TOOLS_REFRESHNOW, OnToolsRefreshnow)
	ON_UPDATE_COMMAND_UI(ID_TOOLS_REFRESHNOW, OnUpdateToolsRefreshnow)
	ON_WM_TIMER()
	ON_COMMAND(ID_TOOLS_REFRESHRATE_5MINUTES, OnToolsRefreshrate5minutes)
	ON_COMMAND(ID_TOOLS_REFRESHRATE_15MINUTES, OnToolsRefreshrate15minutes)
	ON_COMMAND(ID_TOOLS_REFRESHRATE_1HOUR, OnToolsRefreshrate1hour)
	ON_COMMAND(ID_TOOLS_REFRESHRATE_8HOUR, OnToolsRefreshrate8hour)
	ON_UPDATE_COMMAND_UI(ID_TOOLS_REFRESHRATE_15MINUTES, OnUpdateToolsRefreshrate15minutes)
	ON_UPDATE_COMMAND_UI(ID_TOOLS_REFRESHRATE_8HOUR, OnUpdateToolsRefreshrate8hour)
	ON_UPDATE_COMMAND_UI(ID_TOOLS_REFRESHRATE_5MINUTES, OnUpdateToolsRefreshrate5minutes)
	ON_UPDATE_COMMAND_UI(ID_TOOLS_REFRESHRATE_1HOUR, OnUpdateToolsRefreshrate1hour)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_TREEDCLICK, OnTreeDblClick)
	ON_MESSAGE(WM_LISTDCLICK, OnListDblClick)
	ON_MESSAGE(WM_TREEITEMCHANGE, OnTreeItemChange)
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
	// TODO: add member initialization code here
	m_bCreate = FALSE;
	m_image.Create( IDB_IMAGE, 16, 0, RGB(255, 255, 255) );
	m_pThread = NULL;
	m_bRunning = FALSE;
	m_nTimer = 0;
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}

	// TODO: Delete these three lines if you don't want the toolbar to
	//  be dockable
	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);

	// By default we refresh every 5 minutes
	OnToolsRefreshrate5minutes();
	m_nTimer = SetTimer(1, m_nRate, 0);

	return 0;
}

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
	CCreateContext* pContext)
{
	CRect			rect;
	GetClientRect( &rect );
	int				nWidth1 = (int)0.25 * rect.Width();
	int				nWidth2 = (int)0.75 * rect.Width();
	int				nHeight1 = (int)0.25 * rect.Height();
	int				nHeight2 = (int)0.75 * rect.Height();

	if ( !m_wndSplitter.CreateStatic(this, 1, 2) ) 
	{
		return false;
	}

	if(!m_wndSplitter.CreateView(0, 0,
								RUNTIME_CLASS(CTreeViewEx), 
								CSize(nWidth1, rect.Height() ), 
								pContext))
	{
		TRACE(_T("Failed to create top view\n"));
		return FALSE;
	}

	if (!m_wndSplitterRight.CreateStatic(
		&m_wndSplitter,     // our parent window is the first splitter
		2, 1,               // the new splitter is 2 rows, 1 column
		WS_CHILD | WS_VISIBLE | WS_BORDER,  // style, WS_BORDER is needed
		m_wndSplitter.IdFromRowCol(0, 1)
			// new splitter is in the first row, 2nd column of first splitter
	   ))
	{
		TRACE0("Failed to create nested splitter\n");
		return FALSE;
	}


	// create top view
	if(!m_wndSplitterRight.CreateView(0, 0,
								RUNTIME_CLASS(CAgileReaderView), 
								CSize(nWidth2, nHeight1), 
								pContext))
	{
		TRACE(_T("Failed to create top view\n"));
		return FALSE;
	}

	// create bottom view
	if(!m_wndSplitterRight.CreateView(1, 0,
		RUNTIME_CLASS(CHtmlView), 
		CSize(nWidth2, nHeight2), pContext))
	{
		TRACE(_T("Failed to create bottom view\n"));
		return FALSE;
	}
	
	m_wndSplitterRight.RecalcLayout();
	m_bCreate = TRUE;

	InitTree();
	InitList();

	return TRUE;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
		| WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE;

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers


void CMainFrame::OnSize(UINT nType, int cx, int cy) 
{
	CFrameWnd::OnSize(nType, cx, cy);
	
	if ( m_bCreate )
	{
		CRect r;
		GetClientRect(&r);

		int w1 = (int)(r.Width()*0.25);
		int w2 = (int)(r.Width()*0.75);

		m_wndSplitter.SetColumnInfo( 0, w1, 0 );
		m_wndSplitter.SetColumnInfo( 1, w2, 0 );
		m_wndSplitter.RecalcLayout();		

		w1 = (int)(r.Height()*0.25);
		w2 = (int)(r.Height()*0.75);
		m_wndSplitterRight.SetRowInfo( 0, w1, 0 );
		m_wndSplitterRight.SetRowInfo( 1, w2, 0 );
		m_wndSplitterRight.RecalcLayout();		
	}	
}

/////////////////////////////////////////////////////////////////////////////
// Get Left TreeCtrl
//
CTreeCtrl* CMainFrame::GetTreeCtrl()
{
	CTreeViewEx* pTree = (CTreeViewEx*)m_wndSplitter.GetPane(0,0);	
	return &(pTree->GetTreeCtrl());
}

/////////////////////////////////////////////////////////////////////////////
// Get Right Top ListCtrl
//
CListCtrl* CMainFrame::GetListCtrl()
{
	CListView* pView = (CListView*)m_wndSplitterRight.GetPane(0,0);
	return &(pView->GetListCtrl());
}

/////////////////////////////////////////////////////////////////////////////
// Get Right Bottom HtmlView
//
CHtmlView* CMainFrame::GetHtmlView()
{
	CHtmlView* pView = (CHtmlView*)m_wndSplitterRight.GetPane(1,0);
	return pView;
}

/////////////////////////////////////////////////////////////////////////////
// Initialize Tree Ctrl
//
void CMainFrame::InitTree()
{
	SetWindowLong( GetTreeCtrl()->m_hWnd, GWL_STYLE, GetWindowLong( GetTreeCtrl()->m_hWnd, GWL_STYLE ) | TVS_HASLINES | TVS_HASBUTTONS | TVS_SHOWSELALWAYS );
	GetTreeCtrl()->SetImageList( &m_image, TVSIL_NORMAL );

	// Need to create Image List and attach image list to tree
	AddTreeNode( _T("My Feed"), _T("") );

	// Need to read congfig file to get a list of subscribered RSS Feeds and populated to the tree structure
	CStringArray		strTitleArray;
	CStringArray		strLinkArray;
	CFeed::GetFeedSourceList( strTitleArray, strLinkArray );
	for( int nIndex = 0; nIndex < strTitleArray.GetSize(); nIndex++ )
	{
		AddTreeNode( strTitleArray[nIndex], strLinkArray[nIndex] );
	}

	// Need to determine which one was the last visited and then load that entry into right side
}

/////////////////////////////////////////////////////////////////////////////
// Initialize List
//
void CMainFrame::InitList()
{
	// Step 1. Set the list style
	SetWindowLong( GetListCtrl()->m_hWnd, GWL_STYLE, WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_SHOWSELALWAYS | LVS_REPORT );
	GetListCtrl()->SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT  );
	GetListCtrl()->SetImageList( &m_image, LVSIL_SMALL );

	// Step 2. Set the column header
	GetListCtrl()->InsertColumn( 0, _T("Title"), LVCFMT_LEFT, 400 );
	GetListCtrl()->InsertColumn( 1, _T("Description"), LVCFMT_LEFT, 300 );
	GetListCtrl()->InsertColumn( 2, _T("Link"), LVCFMT_LEFT, 200 );
	GetListCtrl()->InsertColumn( 3, _T("Author"), LVCFMT_LEFT, 200 );
	GetListCtrl()->InsertColumn( 4, _T("Category"), LVCFMT_LEFT, 200 );
	GetListCtrl()->InsertColumn( 5, _T("Publish Date"), LVCFMT_LEFT, 200 );
	GetListCtrl()->InsertColumn( 6, _T("Subject"), LVCFMT_LEFT, 200 );
}

/////////////////////////////////////////////////////////////////////////////
// Subscribe a feed
//
void CMainFrame::OnFileSubscriberfeed() 
{
	CString			strRSSFile;

	// Step 1. Popup a dialog to ask user to specify RSS Feeds URL
	CFeedDlg	dlg;
	if ( dlg.DoModal() == IDOK )
	{
		strRSSFile = dlg.m_strUrl;
	}
	else
	{
		return;
	}
	
	// Step 2. If this feed already exists, then switch to that one
	// then return.

	// Step 4. Open XML Document and Parse it there
	CFeed		feed( strRSSFile );
	feed.m_source.m_strLink = dlg.m_strUrl;
	feed.Save();

	// Step 5. Add this entry into tree structure
	// Need to check whether it already exists in the tree structure
	if ( feed.m_bAdded && feed.m_item.GetSize() > 0 )
	{
		AddTreeNode( feed.m_source.m_strTitle, feed.m_source.m_strLink );

		// Step 6. Load all the items into list view
		DisplayFeed( feed );
	}
}

/////////////////////////////////////////////////////////////////////////////
// Get current user selection, then load feed into list
//
LONG CMainFrame::OnTreeDblClick(UINT wParam, LONG lParam)
{
	CWaitCursor		wait;
	HTREEITEM	hItem = GetTreeCtrl()->GetSelectedItem();
	CNode*		pNode = NULL;
	if ( hItem )
	{
		pNode = (CNode*)GetTreeCtrl()->GetItemData( hItem );
		if ( !pNode->m_strLink.IsEmpty() )
		{
			// Step 4. Open XML Document and Parse it there
			CFeed		feed( pNode->m_strLink );
			feed.m_source.m_strLink = pNode->m_strLink;
			feed.Save(FALSE);

			// Step 5. Load all the items into list view
			CFeed		feed1;
			feed1.LoadLocal(pNode->m_strLink);

			// Step 5. Load all the items into list view
			DisplayFeed( feed1 );
		}
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// When Tree Item Change
//
LONG CMainFrame::OnTreeItemChange(UINT wParam, LONG lParam)
{
	HTREEITEM	hItem = GetTreeCtrl()->GetSelectedItem();
	CNode*		pNode = NULL;
	if ( hItem )
	{
		pNode = (CNode*)GetTreeCtrl()->GetItemData( hItem );
		if ( !pNode->m_strLink.IsEmpty() )
		{
			// Step 4. Open XML Document and Parse it there
			CFeed		feed;
			feed.LoadLocal(pNode->m_strLink);

			// Step 5. Load all the items into list view
			DisplayFeed( feed );
		}
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// Get Current Selection and start this page
//
LONG CMainFrame::OnListDblClick(UINT wParam, LONG lParam)
{
	POSITION	pos = GetListCtrl()->GetFirstSelectedItemPosition();
	CFeedItem	item;

	int			nIndex;
	if ( pos != NULL )
	{
		nIndex = GetListCtrl()->GetNextSelectedItem(pos);
		GetHtmlView()->Navigate( GetListCtrl()->GetItemText(nIndex,2) );

		// Get item data
		item.m_strTitle = GetListCtrl()->GetItemText( nIndex, 0 );
		item.m_strDescription = GetListCtrl()->GetItemText( nIndex, 1 );
		item.m_strLink = GetListCtrl()->GetItemText( nIndex, 2 );
		item.m_strAuthor = GetListCtrl()->GetItemText( nIndex, 3 );
		item.m_strCategory = GetListCtrl()->GetItemText( nIndex, 4 );
		item.m_strPubDate = GetListCtrl()->GetItemText( nIndex, 5 );
		item.m_strSubject = GetListCtrl()->GetItemText( nIndex, 6 );
		CFeed::MarkItemRead( item.m_strLink );

		GetListCtrl()->LockWindowUpdate();
		GetListCtrl()->InsertItem( nIndex+1, item.m_strTitle, 2 );
		GetListCtrl()->SetItemText( nIndex+1, 1, item.m_strDescription );
		GetListCtrl()->SetItemText( nIndex+1, 2, item.m_strLink );
		GetListCtrl()->SetItemText( nIndex+1, 3, item.m_strAuthor );
		GetListCtrl()->SetItemText( nIndex+1, 4, item.m_strCategory );
		GetListCtrl()->SetItemText( nIndex+1, 5, item.m_strPubDate );
		GetListCtrl()->SetItemText( nIndex+1, 6, item.m_strSubject );	
		GetListCtrl()->DeleteItem( nIndex );

		GetListCtrl()->SetItemState( nIndex, LVIS_SELECTED, LVIS_SELECTED );
		GetListCtrl()->UnlockWindowUpdate();
		GetListCtrl()->UpdateWindow();
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// Add Tree Node
//
void CMainFrame::AddTreeNode(CString strTitle, CString strLink)
{
	CNode*		pNode = NULL;
	HTREEITEM	hItem;
	if ( strLink.IsEmpty() )
	{
		hItem = GetTreeCtrl()->InsertItem( strTitle, 0, 0 );
	}
	else
	{
		hItem = GetTreeCtrl()->InsertItem( strTitle, 3, 3, GetTreeCtrl()->GetRootItem() );
	}
	pNode = new CNode( strLink );
	GetTreeCtrl()->SetItemData( hItem, (DWORD)pNode );

	GetTreeCtrl()->Expand( GetTreeCtrl()->GetRootItem(), TVE_EXPAND );
}

/////////////////////////////////////////////////////////////////////////////
// Release Data Attached to each node
//
void CMainFrame::Release( HTREEITEM hParent )
{
	CNode*		pNode = NULL;
	HTREEITEM	hItem = NULL;

	// Step 1. Release current node
	if ( hParent != NULL )
	{
		pNode = (CNode*)GetTreeCtrl()->GetItemData( hParent );
		if ( pNode )
		{
			delete pNode;
			pNode = NULL;
		}
	}

	// Step 2. Release child node
	hItem = GetTreeCtrl()->GetChildItem( hParent );
	while( hItem )
	{
		Release( hItem );
		hItem = GetTreeCtrl()->GetNextSiblingItem( hItem );
	}
}

/////////////////////////////////////////////////////////////////////////////
// Display Feed Information into List
void CMainFrame::DisplayFeed(CFeed& feed)
{
	int			nIndex;

	GetListCtrl()->DeleteAllItems();
	for( nIndex = 0; nIndex < feed.m_item.GetSize(); nIndex++ )
	{
		if ( feed.m_item[nIndex].m_strReadStatus == _T("1") )
		{
			GetListCtrl()->InsertItem( nIndex, feed.m_item[nIndex].m_strTitle, 2 );
		}
		else
		{
			GetListCtrl()->InsertItem( nIndex, feed.m_item[nIndex].m_strTitle, 1 );
		}
		GetListCtrl()->SetItemText( nIndex, 1, feed.m_item[nIndex].m_strDescription );
		GetListCtrl()->SetItemText( nIndex, 2, feed.m_item[nIndex].m_strLink );
		GetListCtrl()->SetItemText( nIndex, 3, feed.m_item[nIndex].m_strAuthor );
		GetListCtrl()->SetItemText( nIndex, 4, feed.m_item[nIndex].m_strCategory );
		GetListCtrl()->SetItemText( nIndex, 5, NormalizeDate( feed.m_item[nIndex].m_strPubDate ) );
		GetListCtrl()->SetItemText( nIndex, 6, feed.m_item[nIndex].m_strSubject );
	}
}

/////////////////////////////////////////////////////////////////////////////
// Delete Item from Database
//
void CMainFrame::OnEditDelete() 
{
	int					nIndex;
	CArray<int,int>		nIndexArray;
	CStringArray		strLinkArray;
	CString				strMsg;

	CView* pView = GetActiveView();
	if ( pView->IsKindOf(RUNTIME_CLASS(CTreeViewEx) ) )
	{
		// Delete from Tree
		HTREEITEM	hItem = GetTreeCtrl()->GetSelectedItem();
		if ( hItem == NULL )
		{
			return;
		}
		CNode* pNode = (CNode*)GetTreeCtrl()->GetItemData( hItem );
		if ( pNode->m_strLink.IsEmpty() )
		{
			return;
		}
		
		strMsg.Format( _T("Are you sure you want to unsubscribe '%s'?"), GetTreeCtrl()->GetItemText( hItem ) );
		if( AfxMessageBox( strMsg, MB_ICONQUESTION | MB_YESNO ) == IDYES )
		{
			CFeed::DeleteFeedSource( pNode->m_strLink );
			Release( hItem );
			GetTreeCtrl()->DeleteItem( hItem );
		}
	}
	else if ( pView->IsKindOf(RUNTIME_CLASS(CAgileReaderView) ) )
	{
		POSITION		pos = GetListCtrl()->GetFirstSelectedItemPosition();
		while( pos )
		{
			nIndex = GetListCtrl()->GetNextSelectedItem( pos );
			nIndexArray.Add( nIndex );
			strLinkArray.Add( GetListCtrl()->GetItemText(nIndex,2) );
		}

		// Delete it from Database
		CFeed::DeleteListArray( strLinkArray );

		// Delete it from ListView
		for( nIndex = nIndexArray.GetSize()-1; nIndex>= 0; nIndex-- )
		{
			GetListCtrl()->DeleteItem( nIndexArray[nIndex] );
		}
	}
}

void CMainFrame::OnClose() 
{
	Release( GetTreeCtrl()->GetRootItem() );	
	KillTimer(m_nTimer);
	CFrameWnd::OnClose();
}

/////////////////////////////////////////////////////////////////////////////
// Normalize a GMT Date Time to Date
//
CString CMainFrame::NormalizeDate(CString strValue)
{
	int		nPos;
	strValue.MakeUpper();
	strValue.Replace( _T("GMT"),  _T("") );
	strValue.Replace( _T("PST"),  _T("") );
	strValue.Replace( _T("EST"),  _T("") );
	strValue.Replace( _T("MON,"), _T("") );
	strValue.Replace( _T("TUE,"), _T("") );
	strValue.Replace( _T("WED,"), _T("") );
	strValue.Replace( _T("THU,"), _T("") );
	strValue.Replace( _T("FRI,"), _T("") );
	strValue.Replace( _T("SAT,"), _T("") );
	strValue.Replace( _T("SUN,"), _T("") );
	strValue.TrimLeft();
	strValue.TrimRight();
	nPos = strValue.ReverseFind( '-' );
	if ( strValue.GetLength() - nPos == 5 )
	{
		strValue = strValue.Left( nPos-1 );
		strValue.TrimRight();
	}
	return strValue;
}

/////////////////////////////////////////////////////////////////////////////
// Start a thread to refresh all subscriptions now
//
void CMainFrame::OnToolsRefreshnow() 
{
	// Step 1. Check whether there is any refreshing thread running
	if ( m_bRunning )
	{
		// There is a thread running, skip this
		return;
	}

	// Step 2. If there is no thread running, then start a thread to refresh it
	m_bRunning = TRUE;
	m_pThread = AfxBeginThread( CMainFrame::ProcRefreshAll, this );
}

/////////////////////////////////////////////////////////////////////////////
// Refresh Subscription Thread Function
//
UINT CMainFrame::ProcRefreshAll( void* pParam )
{
	CMainFrame*	pMain = (CMainFrame*)pParam;

	CoInitialize( NULL );

	// Real Refresh function is a static function
	CFeed::RefreshAll();

	CoUninitialize();

	// Set status back to ready
	pMain->m_bRunning = FALSE;

	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// Enable or disable refresh depending on status
//
void CMainFrame::OnUpdateToolsRefreshnow(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( !m_bRunning	);
}

/////////////////////////////////////////////////////////////////////////////
// When it is timer, then start the thread to refresh
//
void CMainFrame::OnTimer(UINT nIDEvent) 
{
	// Refresh it now
	OnToolsRefreshnow();
	
	CFrameWnd::OnTimer(nIDEvent);
}

void CMainFrame::OnToolsRefreshrate5minutes() 
{
	m_nRate = 5*60*1000;	
}

void CMainFrame::OnToolsRefreshrate15minutes() 
{
	m_nRate = 15*60*1000;	
}

void CMainFrame::OnToolsRefreshrate1hour() 
{
	m_nRate = 60*60*1000;	
}

void CMainFrame::OnToolsRefreshrate8hour() 
{
	m_nRate = 8*60*60*1000;	
}

void CMainFrame::OnUpdateToolsRefreshrate15minutes(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck( m_nRate == 15*60*1000 );	
}

void CMainFrame::OnUpdateToolsRefreshrate8hour(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck( m_nRate == 8*60*60*1000 );	
}

void CMainFrame::OnUpdateToolsRefreshrate5minutes(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck( m_nRate == 5*60*1000 );	
}

void CMainFrame::OnUpdateToolsRefreshrate1hour(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck( m_nRate == 60*60*1000 );	
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
LI is a architect of several database-centric tools and technologies. He has been programming since 1995. He is a Microsoft Certified Solution Developer (MCSD), MCSD.NET, SCJP, SCJD and OCDBA.

His programming experience includes C/C++, C#, MFC, ASP, VB and Perl. He has worked on Solaris, AIX, HPUX and various Windows, and found Windows is the easiest one to work with.

He has over 8 years of database experiences in Oracle, SQL Server, DB2 and other DBMS.

LI co-founded AgileInfoSoftware LLC (http://www.agileinfollc.com) in 2003. He is responsible for the overall vision and development strategy of the company.

Comments and Discussions