📄 logview.cpp
字号:
// Written by JHCC, 1997
// LogView.cpp : implementation file
//
#include "stdafx.h"
#include "JHHB.h"
#include "JHHBDoc.h"
#include "RowView.h"
#include "LogView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CLogView
IMPLEMENT_DYNCREATE(CLogView, CRowView)
CLogView::CLogView()
{
m_header.nLogCount = 0;
m_header.nLogLength = sizeof(m_record);
m_header.nExtraHeaderLength = sizeof(m_extraHeader);
m_extraHeader.nFirstLogNo = 0;
m_extraHeader.dwFileSignature = JHHB_LOG_SIGNATURE;
m_nActiveLog = 0;
}
CLogView::~CLogView()
{
}
CJHHBDoc* CLogView::GetDocument(void)
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CJHHBDoc)));
return (CJHHBDoc*)m_pDocument;
}
BOOL CLogView::Open(LPCTSTR lpszPathName)
{
CString strLogPathName;
if (lpszPathName == NULL || ::lstrlen(lpszPathName) == 0)
{
// Show an open file dialog to get the name
CFileDialog dlg(TRUE, // open
NULL, // no default extension
NULL, // no initial file name
OFN_HIDEREADONLY,
"Log files (*.Log)|*.LOG|All files (*.*)|*.*||");
if (dlg.DoModal() == IDOK)
{
strLogPathName = dlg.GetPathName();
}
else
{
return FALSE;
}
CString strCtrlSection;
strCtrlSection.LoadString(IDS_CTRLSECTION);
CString strLogFilePathItem;
strLogFilePathItem.LoadString(IDS_LOGFILEPATHITEM);
::AfxGetApp()->WriteProfileString(strCtrlSection, strLogFilePathItem, strLogPathName);
}
else
strLogPathName = lpszPathName;
ASSERT(m_file.m_hFile == CFile::hFileNull);
CFileException e;
if (!m_file.Open(strLogPathName,
CFile::modeReadWrite | CFile::shareExclusive, &e))
{
if (e.m_cause == CFileException::fileNotFound)
{
if (!m_file.Open(strLogPathName,
CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &e))
return FALSE;
}
}
// If the file is too long,we need remove and re_create it
//so that we can look it easy add at 07/24/1997
if (m_file.GetLength() >= 50*1024L)//2001年6月1日改,原50处为1024
{
m_file.Close();
CFile::Remove( strLogPathName );
if (!m_file.Open(strLogPathName,
CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &e))
return FALSE;
}
// If the file is empty, that is so because the application has
// just created a new file.
// It this case, we need to create a header for the new file.
// We pass bNewHeader=TRUE to WriteHeader so that the CLogView
// takes the opportunity to write the first record in its override
// of OnWriteHeader.
if (m_file.GetLength() == 0L)
{
WriteHeader(&m_file, TRUE);
}
else
{
return (ReadHeader(&m_file));
}
return TRUE;
}
void CLogView::WriteHeader(CFile* pFile, BOOL bNewHeader)
{
pFile->Seek(0L, CFile::begin);
pFile->Write(&m_header, sizeof(m_header));
if (m_header.nExtraHeaderLength > 0)
{
// OnWriteExtraHeader must be implemented by the derived class
OnWriteExtraHeader(pFile, bNewHeader);
}
}
BOOL CLogView::OnReadExtraHeader(CFile* pFile)
{
// and verify the file signature to make sure we're not
// reading a non-Log file.
if (pFile->Read(&m_extraHeader, sizeof(m_extraHeader)) < sizeof(m_extraHeader))
return FALSE;
return (m_extraHeader.dwFileSignature == JHHB_LOG_SIGNATURE);
}
void CLogView::OnWriteExtraHeader(CFile* pFile, BOOL bNewHeader)
{
pFile->Write(&m_extraHeader, sizeof(m_extraHeader));
// If this is a new header (that is, if the first is first being
// created), then create the first record.
if (bNewHeader)
{
ASSERT(pFile == &m_file);
CString strLogBegin;
strLogBegin.LoadString(IDS_LOGBEGIN);
AddNewLog(strLogBegin);
// CreateNewRecord();
}
}
BOOL CLogView::ReadHeader(CFile* pFile)
{
pFile->Seek(0L, CFile::begin);
if (pFile->Read(&m_header, sizeof(m_header)) < sizeof(m_header))
return FALSE;
if (m_header.nExtraHeaderLength < 1)
return TRUE;
// OnReadExtraHeader is implemented by the derived class.
return OnReadExtraHeader(pFile);
}
//UINT CLogView::CreateNewRecord(void)
UINT CLogView::AddNewLog(CString strMemo)
{
// CreateNewRecord is called by the view to create a new fixed
// length record. Increment the record count and update the
// the header to reflect the addition of a new record in the file.
// Notify all views about the new record.
UINT nNewRecordIndex = m_header.nLogCount ++;
WriteHeader(&m_file, FALSE);
FileSeekRecord(nNewRecordIndex);
void* pNewRecord = OnCreateNewRecord(nNewRecordIndex, strMemo);
m_file.Write(pNewRecord, m_header.nLogLength);
#ifdef _DEBUG
// Read back the record just written to see if were written correctly.
void* pCompareRec = malloc(m_header.nLogLength);
FileSeekRecord(nNewRecordIndex);
if (m_file.Read(pCompareRec, m_header.nLogLength) < m_header.nLogLength)
ASSERT(FALSE);
ASSERT(memcmp(pCompareRec, pNewRecord, m_header.nLogLength) == 0);
free(pCompareRec);
#endif
UpdateRow(nNewRecordIndex);
return nNewRecordIndex;
}
void* CLogView::OnCreateNewRecord(int nNewLogIndex, CString strMemo)
{
// format a new log record (in memory).
CTime time = CTime::GetCurrentTime();
CString strDate = time.Format(_T("%Y/%m/%d"));
CString strTimeFmt = _T("%02i:%02i:%02i");
CString strTime;
strTime.Format(strTimeFmt, time.GetHour(), time.GetMinute(), time.GetSecond());
PackRecord(strDate, strTime, strMemo);
m_nActiveLog = nNewLogIndex;
return &m_record;
}
void CLogView::PackRecord(LPCTSTR lpszDate, LPCTSTR lpszTime, LPCTSTR lpszMemo)
{
lstrcpyn(m_record.szDate, lpszDate, sizeof(m_record.szDate) / sizeof(TCHAR));
m_record.szDate[sizeof(m_record.szDate) / sizeof(TCHAR) - 1] = 0;
lstrcpyn(m_record.szTime, lpszTime, sizeof(m_record.szTime) / sizeof(TCHAR));
m_record.szTime[sizeof(m_record.szTime) / sizeof(TCHAR) - 1] = 0;
lstrcpyn(m_record.szMemo, lpszMemo, sizeof(m_record.szMemo) / sizeof(TCHAR));
m_record.szMemo[sizeof(m_record.szMemo) / sizeof(TCHAR) - 1] = 0;
}
void CLogView::ParseRecord(CString& strDate, CString& strTime, CString& strMemo)
{
strDate = m_record.szDate;
strTime = m_record.szTime;
strMemo = m_record.szMemo;
}
UINT CLogView::GetRecordCount(void)
{
return m_header.nLogCount;
}
UINT CLogView::GetActiveLogNo(void)
{
return m_nActiveLog + m_extraHeader.nFirstLogNo;
}
UINT CLogView::GetFirstLogNo(void)
{
return m_extraHeader.nFirstLogNo;
}
UINT CLogView::GetLastLogNo(void)
{
return m_extraHeader.nFirstLogNo + GetRecordCount() - 1;
}
void CLogView::GetLog(UINT nLogNo, CString& strDate,
CString& strTime, CString& strMemo)
{
//nCheckNo - m_extraHeader.nFirstCheckNo
GetRecord(nLogNo, &m_record);
ParseRecord(strDate, strTime, strMemo);
}
///////////////////////////////////////////////////////////////////////
// Implementation
void CLogView::FileSeekRecord(UINT nRecord)
{
m_file.Seek(sizeof(m_header) + m_header.nExtraHeaderLength
+ nRecord * m_header.nLogLength,
CFile::begin);
}
void CLogView::GetRecord(UINT nRecordIndex, void* pRecord)
{
FileSeekRecord(nRecordIndex);
if (m_file.Read(pRecord, m_header.nLogLength) <
m_header.nLogLength)
ASSERT(FALSE);
}
void CLogView::UpdateRecord(CView* pSourceView, UINT nRecordIndex,
void* pRecord) // called by view
{
FileSeekRecord(nRecordIndex);
m_file.Write(pRecord, m_header.nLogLength);
}
void CLogView::GetRowWidthHeight(CDC* pDC, int& nRowWidth, int& nRowHeight)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
nRowWidth = tm.tmAveCharWidth * ROW_WIDTH;
nRowHeight = tm.tmHeight; // 1 lines of text
}
int CLogView::GetActiveRow()
{
return GetActiveLogNo() - GetFirstLogNo();
}
int CLogView::GetRowCount()
{
return GetLastLogNo() - GetFirstLogNo() + 1;
}
void CLogView::ChangeSelectionNextRow(BOOL bNext)
{
if (bNext)
{
if (m_nActiveLog < (GetRecordCount() - 1))
{
++ m_nActiveLog;
// InvalidateRect(NULL, FALSE);
UpdateRow(m_nActiveLog);
}
}
else
{
if (m_nActiveLog > 0)
{
-- m_nActiveLog;
// InvalidateRect(NULL, FALSE);
UpdateRow(m_nActiveLog);
}
}
}
void CLogView::ChangeSelectionToRow(int nRow)
{
m_nActiveLog = nRow + GetFirstLogNo();
// InvalidateRect(NULL, FALSE);
UpdateRow(m_nActiveLog);
}
void CLogView::OnDrawRow(CDC* pDC, int nRow, int y, BOOL bSelected)
{
// Prepare for highlighting or un-highlighting the check, depending
// on whether it is the currently selected check or not. And
// paint the background (behind the text) accordingly.
CBrush brushBackground;
// save colors for drawing selected item on the screen
COLORREF crOldText = 0;
COLORREF crOldBackground = 0;
if (!pDC->IsPrinting())
{
if (bSelected)
{
brushBackground.CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
crOldBackground = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
crOldText = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
brushBackground.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
}
CRect rectSelection;
pDC->GetClipBox(&rectSelection);
rectSelection.top = y;
rectSelection.bottom = y + m_nRowHeight;
pDC->FillRect(&rectSelection, &brushBackground);
}
// Get the data for the specific check.
int nLogNo = nRow + GetFirstLogNo();
CString strDate;
CString strTime;
CString strMemo;
GetLog(nLogNo, strDate, strTime, strMemo);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
// Display the log in one lines of text.
// line 1
pDC->TextOut(DATE_COL * tm.tmAveCharWidth, y, strDate);
pDC->TextOut(TIME_COL * tm.tmAveCharWidth, y, strTime);
pDC->TextOut(MEMO_COL * tm.tmAveCharWidth, y, strMemo);
// Restore the DC.
if (!pDC->IsPrinting() && bSelected)
{
pDC->SetBkColor(crOldBackground);
pDC->SetTextColor(crOldText);
}
}
BEGIN_MESSAGE_MAP(CLogView, CRowView)
//{{AFX_MSG_MAP(CLogView)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLogView drawing
void CLogView::OnInitialUpdate()
{
CRowView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
CString strCtrlSection;
strCtrlSection.LoadString(IDS_CTRLSECTION);
CString strLogFilePathItem;
strLogFilePathItem.LoadString(IDS_LOGFILEPATHITEM);
CString strLogFilePath;
strLogFilePath = ::AfxGetApp()->GetProfileString(strCtrlSection, strLogFilePathItem);
Open(strLogFilePath);
}
/////////////////////////////////////////////////////////////////////////////
// CLogView diagnostics
#ifdef _DEBUG
void CLogView::AssertValid() const
{
CRowView::AssertValid();
}
void CLogView::Dump(CDumpContext& dc) const
{
CRowView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CLogView message handlers
/*
int CLogView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
// side-step CRowView's implementation since we don't want to activate
// this view
return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -