#pragma once
|
/*
|
* ÈÕÖ¾¼Ç¼ʵÏÖÍ·Îļþ
|
* Version: 1.03
|
* Date 2015-07-02
|
* Description:
|
* 2015-07-02 ÐÞ¸ÄÁËÓë¼Ç¼´°¿ÚµÄ°ó¶¨·½Ê½
|
* Ôö¼ÓÁ˶¨Ê±Ë¢ÐµĹ¦ÄÜ
|
* 2015-07-03 Ôö¼ÓÁËdettachwnd
|
* ½«»¥³âÁ¿¸ÄΪÁÙ½çÇø
|
* 2015-08-31 ¶¨Ê±Ë¢ÐÂÉý¼¶¸üÐÂ;
|
*/
|
#include <afxmt.h>
|
#define MAXLOGFILE 10
|
class Logger
|
{
|
public:
|
BOOL bShowThreadId;
|
BOOL bShowLineCount; //ÏÔʾÐкÅ
|
BOOL bShowChannel; //ÏÔʾͨµÀ
|
BOOL bShowDate; //ÏÔʾÈÕÆÚ
|
BOOL bShowTime; //ÏÔʾʱ¼ä
|
BOOL bOneFilePerHour; //°´Ð¡Ê±·ÖÀà
|
BOOL bAutoAppendRN; //×Ô¶¯ÔÚÿÐкó¼ÓÈë»Ø³µ»»ÐÐ
|
BOOL bPauseUpdate; //ÔÝÍ£¸üÐÂ
|
BOOL bNoScroll; //ÔÝÍ£¹ö¶¯
|
|
CEdit m_LogWnd;
|
CEdit * m_pLogWnd;
|
|
CRichEditCtrl m_RichLogWnd;
|
CRichEditCtrl *m_pRichLogWnd;
|
|
int IsLogWndAttached;
|
int AttachedType; //·½Ê½£¬0£¬ËÉ£»1£¬½ô
|
|
CString LogPath;
|
CString LogFilePrefix;
|
|
int UsedChannelCount;
|
CString ChannelPrefix[MAXLOGFILE];
|
|
double MyStartTime;
|
|
int bShowLog[MAXLOGFILE];
|
int bSaveLog[MAXLOGFILE];
|
int LineCount[MAXLOGFILE]; //µ±Ç°ÐкÅ
|
int LogTextLength[MAXLOGFILE];
|
|
int bLogChanged[MAXLOGFILE];
|
CString strChangedLog[MAXLOGFILE];
|
CString strDisplayedLog[MAXLOGFILE];
|
|
CFile CLogFiles[MAXLOGFILE]; //·ÖÏîÈÕÖ¾Îļþ
|
int LogFilesOpened[MAXLOGFILE]; //·ÖÏîÈÕÖ¾ÎļþÊÇ·ñÒѾ´ò¿ª
|
|
CCriticalSection myCriticalSection2;
|
public:
|
static int RelPathToAbsPath(CString BasePath1,CString RelPath2, CString &AbsPath) //Ïà¶Ô·¾¶×ª»»Îª¾ø¶Ô·¾¶
|
{
|
AbsPath=BasePath1+_T("\\")+RelPath2;
|
AbsPath.Replace(_T("/"),_T("\\"));
|
return true;
|
}
|
static int IsAbspath(CString & sPath)
|
{
|
if (sPath.Find(_T(":")) == 1) { return 1;}
|
if (sPath.Find(_T("\\")) == 0){ return 2;}
|
if (sPath.Find(_T("/")) == 0) { return 4;}
|
return false;
|
}
|
int GetDateStr(CString & DateStr)
|
{
|
CTime time1=CTime::GetTickCount();
|
DateStr.Format(_T("%04d-%02d-%02d"),time1.GetYear(),time1.GetMonth(),time1.GetDay());
|
return 0;
|
}
|
int GetTimeStr(CString & TimeStr)
|
{
|
SYSTEMTIME st;
|
GetLocalTime(&st);
|
TimeStr.Format(_T("%2d:%02d:%02d.%03d"), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
return 0;
|
}
|
Logger()
|
{
|
bShowThreadId=0;
|
bShowLineCount=0;
|
bShowChannel = 0;
|
bShowDate = 0;
|
bShowTime=1;
|
bAutoAppendRN=TRUE;
|
bPauseUpdate=FALSE;
|
bNoScroll=FALSE;
|
bOneFilePerHour=0;
|
|
LogPath=_T(".\\Log");
|
LogFilePrefix=_T("DefaultLog");
|
IsLogWndAttached=0;
|
m_pLogWnd=NULL;
|
m_pRichLogWnd=NULL;
|
|
MyStartTime=GetTickTime();
|
|
UsedChannelCount = 1;
|
for (int i=0;i<MAXLOGFILE;i++)
|
{
|
LogFilesOpened[i]=0;
|
LineCount[i]=0;
|
LogTextLength[i]=0;
|
strChangedLog[i].Empty();
|
bLogChanged[i]=0;
|
bShowLog[i]=0;
|
bSaveLog[i]=0;
|
}
|
}
|
|
~Logger()
|
{
|
Dettach();
|
|
for (int i=0;i<MAXLOGFILE;i++)
|
{
|
if (LogFilesOpened[i])
|
{
|
LogToFile(_T("\r\n-< %s >------- <LogFileClosed> ===== \r\n"),i);
|
CLogFiles[i].Close();
|
}
|
}
|
}
|
|
public:
|
int SetLogPathName(CString Path,CString FileName)
|
{
|
LogPath=Path;
|
LogFilePrefix=FileName;
|
|
for (int i=0;i<MAXLOGFILE;i++)
|
{
|
LogFilesOpened[i]=0;
|
LineCount[i]=0;
|
LogTextLength[i]=0;
|
strChangedLog[i].Empty();
|
bLogChanged[i]=0;
|
}
|
|
CString DataStr;
|
GetDateStr(DataStr);
|
CString LogFilePathReal=LogPath+_T("/")+DataStr;
|
|
CString sAbsPath;
|
if (IsAbspath(LogFilePathReal))
|
{
|
sAbsPath=LogFilePathReal;
|
sAbsPath.Replace(_T("/"),_T("\\"));
|
}else
|
{
|
CString sCurPath;
|
int len=GetCurrentDirectory(MAX_PATH,sCurPath.GetBuffer(MAX_PATH));
|
sCurPath.ReleaseBuffer(len);
|
RelPathToAbsPath(sCurPath,LogFilePathReal,sAbsPath);
|
}
|
int j=SHCreateDirectoryEx(NULL,sAbsPath,NULL);
|
return j;
|
}
|
int AttachWnd(HWND hWnd)
|
{
|
CString s1;
|
if (!IsWindow(hWnd))
|
{
|
return false;
|
}
|
if (IsLogWndAttached)
|
{
|
Dettach();
|
}
|
GetClassName(hWnd,s1.GetBuffer(256),256);
|
s1.ReleaseBuffer();
|
CWnd * pCWnd=CWnd::FromHandlePermanent(hWnd);
|
if (s1.Find(_T("Edit"))==0)
|
{
|
if (pCWnd!=NULL)
|
{
|
m_pLogWnd=(CEdit *)pCWnd;
|
AttachedType=0;
|
}
|
else
|
{
|
ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
|
|
if (hWnd == NULL)
|
return FALSE;
|
|
m_LogWnd.Attach(hWnd);
|
m_pLogWnd=&m_LogWnd;
|
AttachedType=1;
|
}
|
m_pLogWnd->ModifyStyle(ES_AUTOHSCROLL|WS_HSCROLL, ES_MULTILINE | ES_AUTOVSCROLL |WS_VSCROLL| ES_SELECTIONBAR | ES_WANTRETURN);
|
m_pLogWnd->Invalidate();
|
m_pLogWnd->SetLimitText(10485760);
|
IsLogWndAttached=1;
|
}else if (s1.Find(_T("RichEdit"))==0)
|
{
|
if (pCWnd!=NULL)
|
{
|
m_pRichLogWnd=(CRichEditCtrl *)pCWnd;
|
AttachedType=0;
|
}
|
else
|
{
|
ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
|
|
if (hWnd == NULL)
|
return FALSE;
|
|
m_RichLogWnd.Attach(hWnd);
|
m_pRichLogWnd=&m_RichLogWnd;
|
AttachedType=1;
|
}
|
m_pRichLogWnd->ModifyStyle(NULL,ES_MULTILINE|ES_AUTOVSCROLL|ES_SELECTIONBAR|ES_WANTRETURN);
|
m_pRichLogWnd->Invalidate();
|
IsLogWndAttached=2;
|
}
|
return true;
|
}
|
|
int Dettach()
|
{
|
if (IsLogWndAttached==1)
|
{
|
IsLogWndAttached=0;
|
if (AttachedType==1)
|
{
|
m_LogWnd.Detach();
|
}
|
m_pLogWnd=NULL;
|
}else if (IsLogWndAttached==2)
|
{
|
IsLogWndAttached=0;
|
if (AttachedType==1)
|
{
|
m_RichLogWnd.Detach();
|
}
|
m_pRichLogWnd=NULL;
|
}
|
return true;
|
}
|
double GetTickTime(double StartTime=0)
|
{
|
LARGE_INTEGER t1,f1;
|
::QueryPerformanceCounter(&t1);
|
::QueryPerformanceFrequency(&f1);
|
return (double)t1.QuadPart/f1.QuadPart-StartTime;
|
}
|
void LogTxt(CString s,int channel=0)
|
{
|
if (channel<0||channel>=MAXLOGFILE)
|
{
|
return;
|
}
|
|
if (bAutoAppendRN)
|
{
|
if (s.Right(2)!=_T("\r\n"))
|
{
|
s.Append(_T("\r\n"));
|
}
|
}
|
CString DateStr, TimeStr;
|
|
if (bShowDate || bShowTime)
|
{
|
GetDateStr(DateStr);
|
GetTimeStr(TimeStr);
|
CString DateTimeStr;
|
if (bShowDate && bShowTime)
|
{
|
DateTimeStr = _T("[") + DateStr + _T(" ") + TimeStr +_T("] ");
|
}else if (bShowTime)
|
{
|
DateTimeStr = _T("[") + TimeStr + _T("] ");
|
}
|
s = DateTimeStr + s ;
|
}
|
|
if (bShowLog[channel])
|
{
|
CString s2;
|
|
myCriticalSection2.Lock(INFINITE);
|
|
LineCount[channel]++;
|
int ThreadId=GetCurrentThreadId();
|
if (bShowThreadId &&bShowChannel)
|
{
|
s2.Format(_T("[%d %4d]"),ThreadId,channel);
|
}else if (bShowChannel)
|
{
|
s2.Format(_T("[%d]"),channel);
|
}else{
|
s2.Empty();
|
}
|
if (bShowLineCount)
|
{
|
s2.AppendFormat(_T("[%d]"),LineCount[channel]);
|
}
|
s2+=s;
|
|
LogTextLength[channel]+=s2.GetLength();
|
|
if (bLogChanged[channel]==1)
|
{
|
strChangedLog[channel]+=s2;
|
}
|
else
|
{
|
strChangedLog[channel]=s2;
|
}
|
|
if (strChangedLog[channel].GetLength()>3000000)
|
{
|
strChangedLog[channel]=strChangedLog[channel].Mid(1000000);
|
LogTextLength[channel]-=1000000;
|
}
|
|
bLogChanged[channel]=1;
|
}
|
if (bSaveLog[channel])
|
{
|
LogToFile(s,channel);
|
}
|
|
myCriticalSection2.Unlock();
|
}
|
int LogToFile(CString msg,int channel=0)
|
{
|
CString s1;
|
CStringA sa1;
|
CStringA DateStrA,TimeStrA,DateTimeStrA;
|
CStringA msgA;
|
CString DateStrT;
|
CString logfilename;
|
int j;
|
#ifdef UNICODE
|
int l;
|
l=msg.GetLength();
|
j=WideCharToMultiByte(CP_ACP,0,msg,l,msgA.GetBuffer(l*2),l*2,NULL,NULL);
|
msgA.ReleaseBuffer(j);
|
#else
|
msgA=msg;
|
#endif
|
try
|
{
|
CTime time1=CTime::GetTickCount();
|
CString timesecstr;
|
timesecstr.Format(_T("%d"),time1);
|
DateStrA.Format("%04d-%02d-%02d",time1.GetYear(),time1.GetMonth(),time1.GetDay());
|
DateStrT.Format(_T("%04d-%02d-%02d"),time1.GetYear(),time1.GetMonth(),time1.GetDay());
|
TimeStrA.Format("%02d:%02d:%02d",time1.GetHour(),time1.GetMinute(),time1.GetSecond());
|
DateTimeStrA=DateStrA+_T(" ")+TimeStrA;
|
CString LogDirPath,LogFilePath;
|
LogDirPath=LogPath+_T("\\")+DateStrT;
|
if (bOneFilePerHour)
|
{
|
if (channel==0&&UsedChannelCount==1)
|
{
|
logfilename.Format(_T("%slog_%s_%02d.log"),LogFilePrefix,DateStrT,time1.GetHour());
|
LogFilePath=LogDirPath+_T("\\")+logfilename;
|
}else
|
{
|
logfilename.Format(_T("%slog[%d]_%s_%s_%02d.log"),LogFilePrefix,channel,ChannelPrefix[channel],DateStrT,time1.GetHour());
|
LogFilePath=LogDirPath+_T("\\")+logfilename;
|
}
|
}else
|
{
|
if (channel==0&&UsedChannelCount==1)
|
{
|
logfilename.Format(_T("%slog_%s.log"),LogFilePrefix,DateStrT);
|
LogFilePath=LogDirPath+_T("\\")+logfilename;
|
}else
|
{
|
logfilename.Format(_T("%slog[%d]_%s_%s.log"),LogFilePrefix,channel,ChannelPrefix[channel],DateStrT);
|
LogFilePath=LogDirPath+_T("\\")+logfilename;
|
}
|
}
|
|
if (channel>=0&&channel<MAXLOGFILE)
|
{
|
if (LogFilesOpened[channel])
|
{
|
CString oldfilename=CLogFiles[channel].GetFileName();
|
if (oldfilename!=logfilename)
|
{
|
sa1.Format("\r\n-< %s >------- <LogFileClosed> ===== \r\n",DateTimeStrA);
|
CLogFiles[channel].Write(sa1.GetString(),sa1.GetLength());
|
CLogFiles[channel].Close();
|
LogFilesOpened[channel]=0;
|
}
|
}
|
if (!LogFilesOpened[channel])
|
{
|
CString sAbsPath;
|
if (IsAbspath(LogDirPath))
|
{
|
sAbsPath=LogDirPath;
|
sAbsPath.Replace(_T("/"),_T("\\"));
|
}else
|
{
|
CString sCurPath;
|
int len=GetCurrentDirectory(MAX_PATH,sCurPath.GetBuffer(MAX_PATH));
|
sCurPath.ReleaseBuffer(len);
|
RelPathToAbsPath(sCurPath,LogDirPath,sAbsPath);
|
}
|
SHCreateDirectoryEx(NULL,sAbsPath,NULL);
|
|
CFileException e;
|
if (CLogFiles[channel].Open(LogFilePath,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyWrite,&e))
|
{
|
CLogFiles[channel].SeekToEnd();
|
sa1.Format("\r\n-< %s >------- <LogFileOpened : %d > ===== \r\n",DateTimeStrA,channel);
|
CLogFiles[channel].Write(sa1.GetString(),sa1.GetLength());
|
LogFilesOpened[channel]=1;
|
}
|
else
|
{
|
LogFilesOpened[channel]=0;
|
s1.Format(_T("ÈÕÖ¾Îļþ %s ²Ù×÷ʧ°Ü"),LogFilePath);
|
strChangedLog[channel]+=s1+_T("\r\n");
|
return false;
|
}
|
}
|
if (LogFilesOpened[channel])
|
{
|
if (bShowTime)
|
{
|
sa1.Format("%s : %s",DateTimeStrA,msgA);
|
}
|
else
|
{
|
sa1=msgA;
|
}
|
CLogFiles[channel].Write(sa1,sa1.GetLength());
|
return true;
|
}
|
}
|
|
return false;
|
}
|
catch (CMemoryException* e)
|
{
|
CString s1;
|
CString stre1;
|
e->GetErrorMessage(stre1.GetBuffer(2048),2048);
|
stre1.ReleaseBuffer();
|
s1.Format(_T("·¢Éú´íÎó %s"),stre1);
|
strChangedLog[channel]+=s1+_T("\r\n");
|
AfxMessageBox(s1);
|
return false;
|
}
|
catch (CFileException* e)
|
{
|
CString s1;
|
CString stre1;
|
e->GetErrorMessage(stre1.GetBuffer(2048),2048);
|
stre1.ReleaseBuffer();
|
s1.Format(_T("·¢Éú´íÎó %s"),stre1);
|
strChangedLog[channel]+=s1+_T("\r\n");
|
AfxMessageBox(s1);
|
return false;
|
}
|
catch (CException* e)
|
{
|
CString s1;
|
CString stre1;
|
e->GetErrorMessage(stre1.GetBuffer(2048),2048);
|
stre1.ReleaseBuffer();
|
s1.Format(_T("·¢Éú´íÎó %s"),stre1);
|
strChangedLog[channel]+=s1+_T("\r\n");
|
AfxMessageBox(s1);
|
return false;
|
}
|
return false;
|
}
|
int UpdateLogDisplay(int channel=0)
|
{
|
int i,j,k;
|
if (channel<0 || channel >= MAXLOGFILE)
|
{
|
return 0;
|
}
|
if (bPauseUpdate)
|
{
|
return 0;
|
}
|
if (bLogChanged[channel]==0)
|
{
|
return 0;
|
}
|
if (!myCriticalSection2.Lock(INFINITE))
|
{
|
return -1;
|
}
|
if (IsLogWndAttached==1 && m_pLogWnd && IsWindow(m_pLogWnd->m_hWnd))
|
{
|
if (LogTextLength[channel]>2000000)
|
{
|
int len = min(strDisplayedLog[channel].GetLength(),1000000);
|
|
strDisplayedLog[channel]=strDisplayedLog[channel].Mid(len);
|
|
m_pLogWnd->SetSel(0,len);
|
m_pLogWnd->Clear();
|
LogTextLength[channel]-=len;
|
}
|
|
int line1,line2;
|
line1=m_pLogWnd->GetFirstVisibleLine();
|
i=m_pLogWnd->GetLineCount();
|
|
j=m_pLogWnd->LineIndex(i-1);
|
m_pLogWnd->SetSel(j,j,true);
|
|
k=m_pLogWnd->LineIndex(-1)+m_pLogWnd->LineLength(-1);
|
m_pLogWnd->SetSel(k,k,true);
|
|
m_pLogWnd->ReplaceSel(strChangedLog[channel]);
|
line2=m_pLogWnd->GetFirstVisibleLine();
|
|
strDisplayedLog[channel]+=strChangedLog[channel];
|
if (bNoScroll)
|
{
|
m_pLogWnd->LineScroll(line1-line2);
|
}
|
m_pLogWnd->UpdateWindow();
|
}else if (IsLogWndAttached==2 && m_pRichLogWnd && IsWindow(m_pRichLogWnd->m_hWnd))
|
{
|
if (LogTextLength[channel]>2000000)
|
{
|
int len = min(strDisplayedLog[channel].GetLength(),1000000);
|
|
strDisplayedLog[channel]=strDisplayedLog[channel].Mid(len);
|
|
m_pRichLogWnd->SetSel(0,len);
|
m_pRichLogWnd->Clear();
|
LogTextLength[channel]-=len;
|
}
|
|
int line1,line2;
|
line1=m_pRichLogWnd->GetFirstVisibleLine();
|
i=m_pRichLogWnd->GetLineCount();
|
|
j=m_pRichLogWnd->LineIndex(i-1);
|
m_pRichLogWnd->SetSel(j,j);
|
|
// k=m_pRichLogWnd->LineIndex(-1)+m_pLogWnd->LineLength(-1);
|
// m_pRichLogWnd->SetSel(k,k);
|
|
m_pRichLogWnd->ReplaceSel(strChangedLog[channel]);
|
line2=m_pRichLogWnd->GetFirstVisibleLine();
|
|
strDisplayedLog[channel]+=strChangedLog[channel];
|
if (bNoScroll)
|
{
|
m_pRichLogWnd->LineScroll(line1-line2);
|
}
|
// m_pRichLogWnd->PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
|
m_pRichLogWnd->SendMessage(WM_VSCROLL, SB_BOTTOM, 0);
|
m_pRichLogWnd->UpdateWindow();
|
}
|
|
strChangedLog[channel].Empty();
|
bLogChanged[channel]=0;
|
|
myCriticalSection2.Unlock();
|
return 0;
|
}
|
};
|