gusucode.com > VC_C++源码,界面编程,网页爬虫源码程序 > VC_C++源码,界面编程,网页爬虫源码程序/code/webpageloader_SourceCode/SessionView.cpp
// ItemView.cpp : implementation of the CSessionView class // #include "stdafx.h" #include "WebPageLoader.h" #include <atlbase.h> #include "Doc.h" #include "MainFrm.h" #include "SessionView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define TIMER_ID 55 static LPCTSTR szSection = _T("Settings"); LPCTSTR GetSizeNumber(long n) { static TCHAR szResult[64] = { 0 }; USES_CONVERSION; WCHAR szwTemp[64]; LONGLONG longlong = (DWORD) n; ::StrFormatByteSizeW(longlong, szwTemp, 63); _tcscpy(szResult, W2CT(szwTemp)); return szResult; } LPCTSTR GetFormattedNumber(long n) // Returns a string formatted using locale rules (thousand separators etc). // Returns a STATIC string buffer. { static TCHAR szResult[64] = { 0 }; // Get the decimal character(s) static TCHAR szDecimal[8] = { 0 }; if( szDecimal[0] == _T('\0') ) { int size = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, NULL, 0); if( size==0 ) return NULL; HLOCAL hlocal = ::LocalAlloc(LPTR, size); LPTSTR lpBuf = (LPTSTR)::LocalLock(hlocal); ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, lpBuf, size); _tcscpy( szDecimal, lpBuf ); ::LocalUnlock(hlocal); ::LocalFree(hlocal); } TCHAR szStr[64] = { 0 }; wsprintf(szStr, _T("%d"), n); ::GetNumberFormat(LOCALE_USER_DEFAULT, 0, szStr, NULL, szResult, 63); // HACK: Remove possible decimals LPTSTR p = _tcsstr( szResult, szDecimal ); if( p!=NULL ) { while( _tcsstr( p+1, szDecimal )!=NULL ) p = _tcsstr( p+1, szDecimal ); if( p!=NULL ) *p = _T('\0'); } return szResult; }; ///////////////////////////////////////////////////////////////////////////// // CSessionView IMPLEMENT_DYNCREATE(CSessionView, CListView) BEGIN_MESSAGE_MAP(CSessionView, CListView) //{{AFX_MSG_MAP(CSessionView) ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged) ON_COMMAND(ID_EDIT_REFRESH, OnEditRefresh) ON_COMMAND(ID_EDIT_DELETE, OnDelete) ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE, OnUpdateDelete) ON_WM_DESTROY() ON_WM_TIMER() ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk) ON_WM_CONTEXTMENU() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSessionView construction/destruction CSessionView::CSessionView() { } CSessionView::~CSessionView() { } BOOL CSessionView::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= LVS_NOSORTHEADER; return CListView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CSessionView drawing void CSessionView::OnTimer(UINT nIDEvent) { if( nIDEvent == TIMER_ID ) RefreshItems(FALSE); CListView::OnTimer(nIDEvent); } void CSessionView::OnDraw(CDC* pDC) { } void CSessionView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& ctlList = GetListCtrl(); // Create the image list for the tree control m_ImageList.Create(IDR_IMAGES, 16, 1, RGB(0,0,255)); ctlList.SetImageList(&m_ImageList, LVSIL_SMALL); // Set style and add columns ctlList.ModifyStyle(LVS_TYPEMASK, LVS_REPORT|LVS_SINGLESEL|LVS_SHOWSELALWAYS); CString s; s.LoadString(IDS_COL_ITEM); ctlList.InsertColumn(0, s, LVCFMT_LEFT); s.LoadString(IDS_COL_FILES); ctlList.InsertColumn(1, s, LVCFMT_CENTER); s.LoadString(IDS_COL_DOWNLOADED); ctlList.InsertColumn(2, s, LVCFMT_CENTER); // Set reasonable widths for our columns int w1, w2, w3; s = ::AfxGetApp()->GetProfileString(szSection, _T("Columns"), _T("300,100,100")); ::sscanf( s, _T("%d,%d,%d"), &w1, &w2, &w3 ); ctlList.SetColumnWidth(0, w1); ctlList.SetColumnWidth(1, w2); ctlList.SetColumnWidth(2, w3); } void CSessionView::OnDestroy() { CString s; CListCtrl& ctlList = GetListCtrl(); s.Format(_T("%d,%d,%d"), ctlList.GetColumnWidth(0), ctlList.GetColumnWidth(1), ctlList.GetColumnWidth(2) ); ::AfxGetApp()->WriteProfileString(szSection, _T("Columns"), s); CListView::OnDestroy(); } ///////////////////////////////////////////////////////////////////////////// // CSessionView diagnostics #ifdef _DEBUG void CSessionView::AssertValid() const { CListView::AssertValid(); } void CSessionView::Dump(CDumpContext& dc) const { CListView::Dump(dc); } CDoc* CSessionView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDoc))); return (CDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CSessionView helpers int CSessionView::StateToImage(CSession *pSession) { ASSERT_VALID(pSession); switch( pSession->m_State ) { case STATE_UNSCHEDULED: return 0; case STATE_QUEUED: return 1; case STATE_CONNECTING: return 2; case STATE_RUNNING: return 3; case STATE_SLEEPING: return 5; case STATE_DONE:; case STATE_STOPPED: // Download complete image: // * Show GREEN image if all files were reported OK // * Show YELLOW image if all files were not downloaded (warnings, skipped files) // * Show RED image if any errors have been reported if( pSession->m_Info.m_nFilesDownloaded==pSession->m_Files.GetCount() ) return 4; if( pSession->m_Info.m_nFilesFailed>0 ) return 16; return 15; default: return 0; }; }; ///////////////////////////////////////////////////////////////////////////// // Implementation int CSessionView::GetSelectedItem() { CListCtrl& ctlList = GetListCtrl(); return ctlList.GetNextItem(-1, LVIS_SELECTED); }; LONG CSessionView::GetSelectedSessionID() { int idx = GetSelectedItem(); if( idx<0 ) return -1; CListCtrl& ctlList = GetListCtrl(); return ctlList.GetItemData(idx); }; void CSessionView::CreateItems() { CListCtrl& ctlList = GetListCtrl(); ctlList.DeleteAllItems(); RefreshItems(TRUE); }; void CSessionView::RefreshItems(BOOL bAll/*=FALSE*/) { CDoc *pDoc = GetDocument(); if( pDoc==NULL ) return; ASSERT_KINDOF(CDoc,pDoc); CSingleLock lock( pDoc->m_ThreadManager, TRUE ); CListCtrl& ctlList = GetListCtrl(); // Update all existing items if nessecary int max = ctlList.GetItemCount(); for( int i=0; i<max; i++ ) { LVITEM itm = { 0 }; itm.iItem = i; itm.mask = LVIF_PARAM; BOOL bFound = ctlList.GetItem(&itm); if( !bFound ) continue; CSession *pSession = pDoc->m_ThreadManager.FindSession(itm.lParam); if( pSession==NULL ) { // Session is no longer to be found in lists... must // have been deleted... ctlList.DeleteItem(itm.iItem); // Force glorious loop to repeat since deleting // usually screws things up in control indexes. i=0; continue; }; ASSERT_VALID(pSession); // Ok, we may wish to update the item! // We only select the stuff that really needs updating // since this is called for all items. { CSingleLock lock( *pSession, TRUE ); UpdateListItem(ctlList, pSession, i, bAll); pSession->m_OldState = pSession->m_State; } }; // Find and add any new items CSessionList List; pDoc->m_ThreadManager.GetSessions(List); POSITION pos = List.GetHeadPosition(); while( pos != NULL ) { CSession *pSession = List.GetNext(pos); ASSERT_VALID(pSession); LVFINDINFO find = { 0 }; find.flags = LVFI_PARAM; find.lParam = pSession->m_iUniqueID; int idx = ctlList.FindItem(&find); if( idx >= 0 ) continue; // Ok, found a new one. Insert it... { CSingleLock lock( *pSession, TRUE ); LV_ITEM itm = { 0 }; itm.iItem = 0; itm.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT; itm.pszText = (LPTSTR)(LPCTSTR)pSession->m_sURL; itm.cchTextMax = pSession->m_sURL.GetLength(); itm.iImage = 0; itm.lParam = pSession->m_iUniqueID; int newidx = ctlList.InsertItem(&itm); UpdateListItem(ctlList,pSession,newidx,TRUE); // ctlList.SetItemState(newidx, LVIS_SELECTED, LVIS_SELECTED); }; }; CMainFrame *frm = ((CMainFrame *)::AfxGetMainWnd()); ASSERT_KINDOF(CMainFrame,frm); if( frm==NULL ) return; // Update statusbar (download statistics) CString files = GetFormattedNumber(pDoc->m_Preferences.m_nFilesDownloaded); CString bytes = GetSizeNumber(pDoc->m_Preferences.m_lBytesDownloaded); CString s; s.Format(IDS_STATUSTEXT, (LPCTSTR)files, (LPCTSTR)bytes); frm->m_wndStatusBar.SetPaneText(2,s,TRUE); // Refresh view periodically if( IsWindowVisible() ) SetTimer(TIMER_ID, 2000, NULL); else KillTimer(TIMER_ID); }; void CSessionView::UpdateListItem(CListCtrl &ctlList, CSession *pSession, int idx, BOOL bForce) // NOT LOCKING { LV_ITEM itm = { 0 }; itm.iItem = idx; itm.mask = 0; int iImage; if( (iImage = StateToImage(pSession)) != itm.iImage ) { itm.mask |= LVIF_IMAGE; itm.iImage = iImage; }; if( itm.mask!=0 ) ctlList.SetItem(&itm); if( bForce || (pSession->m_State == STATE_RUNNING) || (pSession->m_OldState != pSession->m_State) ) { // CString s; s.Format(_T("%d / %d"), pSession->m_Info.m_nFilesDownloaded + pSession->m_Info.m_nFilesSkipped + pSession->m_Info.m_nFilesFailed, pSession->m_Files.GetCount()); ctlList.SetItemText(idx, 1, (LPCTSTR)s); s = GetFormattedNumber(pSession->m_Info.m_lBytesDownloaded); ctlList.SetItemText(idx, 2, (LPCTSTR)s); }; }; ///////////////////////////////////////////////////////////////////////////// // CSessionView message handlers void CSessionView::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; CDoc *pDoc = GetDocument(); ASSERT_KINDOF(CDoc,pDoc); if( pDoc==NULL ) return; CMainFrame *frm = ((CMainFrame *)::AfxGetMainWnd()); ASSERT_KINDOF(CMainFrame,frm); CSession *pSession = pDoc->GetSelectedSession(); if( pSession==NULL ) { frm->OnCreateNodes(0,0); frm->m_wndStatusBar.SetPaneText( 0, _T(""), TRUE ); return; } CSingleLock lock( *pSession, TRUE ); frm->OnCreateNodes(0,0); frm->m_wndStatusBar.SetPaneText( 0, pSession->m_Settings.m_sDownloadPath, TRUE ); *pResult = 0; } void CSessionView::OnEditRefresh() { CreateItems(); } void CSessionView::OnDelete() { CDoc *pDoc = GetDocument(); ASSERT_KINDOF(CDoc,pDoc); if( pDoc==NULL ) return; CSession *pSession = pDoc->GetSelectedSession(); ASSERT_VALID(pSession); if( pSession==NULL ) return; CSingleLock lock( *pSession, TRUE ); pSession->m_bKillRequest = true; ::AfxGetMainWnd()->PostMessage(WM_SCHEDULE); } void CSessionView::OnUpdateDelete(CCmdUI* pCmdUI) { CListCtrl& ctlList = GetListCtrl(); pCmdUI->Enable( ctlList.GetSelectedCount()>0); } void CSessionView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) { CDoc *pDoc = GetDocument(); ASSERT_KINDOF(CDoc,pDoc); pDoc->OnEditProperties(); *pResult = 0; } void CSessionView::OnContextMenu(CWnd* pWnd, CPoint point) { if( GetSelectedItem()<0 ) return; CMainFrame *frm = (CMainFrame *)::AfxGetMainWnd(); ASSERT_VALID(frm); if( frm==NULL ) return; CMenu *menu = frm->GetMenu(); if( menu==NULL ) return; CMenu *editmenu = menu->GetSubMenu(1); if( editmenu==NULL ) return; editmenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, frm, NULL); }