QuakeGod
2022-07-22 dd67df95a7303aee3bed65ffa935465f20ee8b32
提交 | 用户 | age
4b03ae 1 #pragma once
Q 2 /*
3 * 日志记录实现头文件
4 * Version: 1.03
5 * Date 2015-07-02
6 * Description: 
7 * 2015-07-02 修改了与记录窗口的绑定方式
8 *             增加了定时刷新的功能
9 * 2015-07-03 增加了dettachwnd
10 * 将互斥量改为临界区
11 * 2015-08-31 定时刷新升级更新;
12 */
13 #include <afxmt.h>
14 #define MAXLOGFILE 10
15 class Logger
16 {
17 public:
18     BOOL bShowThreadId;
19     BOOL bShowLineCount;    //显示行号
20     BOOL bShowChannel;        //显示通道
21     BOOL bShowDate;            //显示日期
22     BOOL bShowTime;            //显示时间
23     BOOL bOneFilePerHour;    //按小时分类
24     BOOL bAutoAppendRN;        //自动在每行后加入回车换行
25     BOOL bPauseUpdate;        //暂停更新
26     BOOL bNoScroll;            //暂停滚动
27
28     CEdit m_LogWnd;
29     CEdit * m_pLogWnd;
30
31     CRichEditCtrl m_RichLogWnd;
32     CRichEditCtrl *m_pRichLogWnd;
33
34     int IsLogWndAttached;
35     int AttachedType;        //方式,0,松;1,紧
36
37     CString LogPath;
38     CString LogFilePrefix;
39
40     int UsedChannelCount;
41     CString ChannelPrefix[MAXLOGFILE];
42
43     double MyStartTime;
44
45     int bShowLog[MAXLOGFILE];
46     int bSaveLog[MAXLOGFILE];
47     int LineCount[MAXLOGFILE];        //当前行号
48     int LogTextLength[MAXLOGFILE];
49
50     int bLogChanged[MAXLOGFILE];
51     CString strChangedLog[MAXLOGFILE];
52     CString strDisplayedLog[MAXLOGFILE];
53
54     CFile CLogFiles[MAXLOGFILE]; //分项日志文件
55     int LogFilesOpened[MAXLOGFILE]; //分项日志文件是否已经打开
56
57     CCriticalSection myCriticalSection2;
58 public:    
59     static int RelPathToAbsPath(CString BasePath1,CString RelPath2, CString &AbsPath) //相对路径转换为绝对路径
60     {
61         AbsPath=BasePath1+_T("\\")+RelPath2;
62         AbsPath.Replace(_T("/"),_T("\\"));
63         return true;
64     }
65     static int IsAbspath(CString & sPath)
66     {
67         if (sPath.Find(_T(":")) == 1) {    return 1;}
68         if (sPath.Find(_T("\\")) == 0){ return 2;}
69         if (sPath.Find(_T("/")) == 0) { return 4;}
70         return false;
71     }
72     int GetDateStr(CString & DateStr)
73     {
74         CTime time1=CTime::GetTickCount();
75         DateStr.Format(_T("%04d-%02d-%02d"),time1.GetYear(),time1.GetMonth(),time1.GetDay());
76         return 0;
77     }
78     int GetTimeStr(CString & TimeStr)
79     {
80         SYSTEMTIME st;
81         GetLocalTime(&st);
82         TimeStr.Format(_T("%2d:%02d:%02d.%03d"), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
83         return 0;
84     }
85     Logger()
86     {
87         bShowThreadId=0;
88         bShowLineCount=0;
89         bShowChannel = 0;
90         bShowDate = 0;
91         bShowTime=1;
92         bAutoAppendRN=TRUE;
93         bPauseUpdate=FALSE;
94         bNoScroll=FALSE;
95         bOneFilePerHour=0;
96
97         LogPath=_T(".\\Log");
98         LogFilePrefix=_T("DefaultLog");
99         IsLogWndAttached=0;
100         m_pLogWnd=NULL;
101         m_pRichLogWnd=NULL;
102
103         MyStartTime=GetTickTime();
104
105         UsedChannelCount = 1;
106         for (int i=0;i<MAXLOGFILE;i++)
107         {
108             LogFilesOpened[i]=0;
109             LineCount[i]=0;
110             LogTextLength[i]=0;
111             strChangedLog[i].Empty();
112             bLogChanged[i]=0;
113             bShowLog[i]=0;
114             bSaveLog[i]=0;
115         }
116     }
117
118     ~Logger()
119     {
120         Dettach();
121
122         for (int i=0;i<MAXLOGFILE;i++)
123         {
124             if (LogFilesOpened[i])
125             {
126                 LogToFile(_T("\r\n-< %s >------- <LogFileClosed> ===== \r\n"),i);
127                 CLogFiles[i].Close();
128             }
129         }
130     }
131
132 public:
133     int SetLogPathName(CString Path,CString FileName)
134     {
135         LogPath=Path;
136         LogFilePrefix=FileName;
137
138         for (int i=0;i<MAXLOGFILE;i++)
139         {
140             LogFilesOpened[i]=0;
141             LineCount[i]=0;
142             LogTextLength[i]=0;
143             strChangedLog[i].Empty();
144             bLogChanged[i]=0;
145         }
146
147         CString DataStr;
148         GetDateStr(DataStr);
149         CString LogFilePathReal=LogPath+_T("/")+DataStr;
150         
151         CString sAbsPath;
152         if (IsAbspath(LogFilePathReal))
153         {
154             sAbsPath=LogFilePathReal;
155             sAbsPath.Replace(_T("/"),_T("\\"));
156         }else
157         {
158             CString sCurPath;
159             int len=GetCurrentDirectory(MAX_PATH,sCurPath.GetBuffer(MAX_PATH));
160             sCurPath.ReleaseBuffer(len);
161             RelPathToAbsPath(sCurPath,LogFilePathReal,sAbsPath);
162         }
163         int j=SHCreateDirectoryEx(NULL,sAbsPath,NULL);
164         return j;
165     }
166     int AttachWnd(HWND  hWnd)
167     {
168         CString s1;
169         if (!IsWindow(hWnd))
170         {
171             return false;
172         }
173         if (IsLogWndAttached) 
174         {
175             Dettach();
176         }
177         GetClassName(hWnd,s1.GetBuffer(256),256);
178         s1.ReleaseBuffer();
179         CWnd * pCWnd=CWnd::FromHandlePermanent(hWnd);
180         if (s1.Find(_T("Edit"))==0)
181         {
182             if (pCWnd!=NULL)
183             {
184                 m_pLogWnd=(CEdit *)pCWnd;
185                 AttachedType=0;
186             }
187             else
188             {
189                 ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
190
191                 if (hWnd == NULL)
192                     return FALSE;
193
194                 m_LogWnd.Attach(hWnd);
195                 m_pLogWnd=&m_LogWnd;
196                 AttachedType=1;
197             }
198             m_pLogWnd->ModifyStyle(ES_AUTOHSCROLL|WS_HSCROLL, ES_MULTILINE | ES_AUTOVSCROLL |WS_VSCROLL| ES_SELECTIONBAR | ES_WANTRETURN);
199             m_pLogWnd->Invalidate();
200             m_pLogWnd->SetLimitText(10485760);
201             IsLogWndAttached=1;
202         }else if (s1.Find(_T("RichEdit"))==0)
203         {
204             if (pCWnd!=NULL)
205             {
206                 m_pRichLogWnd=(CRichEditCtrl *)pCWnd;
207                 AttachedType=0;
208             }
209             else
210             {
211                 ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
212
213                 if (hWnd == NULL)
214                     return FALSE;
215
216                 m_RichLogWnd.Attach(hWnd);
217                 m_pRichLogWnd=&m_RichLogWnd;
218                 AttachedType=1;
219             }
220             m_pRichLogWnd->ModifyStyle(NULL,ES_MULTILINE|ES_AUTOVSCROLL|ES_SELECTIONBAR|ES_WANTRETURN);
221             m_pRichLogWnd->Invalidate();
222             IsLogWndAttached=2;
223         }
224         return true;
225     }
226
227     int Dettach()
228     {
229         if (IsLogWndAttached==1)
230         {
231             IsLogWndAttached=0;    
232             if (AttachedType==1)
233             {
234                 m_LogWnd.Detach();
235             }
236             m_pLogWnd=NULL;
237         }else if (IsLogWndAttached==2)
238         {
239             IsLogWndAttached=0;    
240             if (AttachedType==1)
241             {
242                 m_RichLogWnd.Detach();
243             }
244             m_pRichLogWnd=NULL;
245         }
246         return true;
247     }
248     double GetTickTime(double StartTime=0)
249     {
250         LARGE_INTEGER t1,f1;
251         ::QueryPerformanceCounter(&t1);
252         ::QueryPerformanceFrequency(&f1);
253         return (double)t1.QuadPart/f1.QuadPart-StartTime;
254     }
255     void LogTxt(CString s,int channel=0)
256     {
257         if (channel<0||channel>=MAXLOGFILE)
258         {
259             return;
260         }
261
262         if (bAutoAppendRN)
263         {
264             if (s.Right(2)!=_T("\r\n"))
265             {
266                 s.Append(_T("\r\n"));
267             }
268         }
269         CString DateStr, TimeStr;
270
271         if (bShowDate || bShowTime)
272         {
273             GetDateStr(DateStr);
274             GetTimeStr(TimeStr);
275             CString DateTimeStr;
276             if (bShowDate && bShowTime)
277             {
278                 DateTimeStr = _T("[") + DateStr + _T(" ") + TimeStr +_T("] ");
279             }else if (bShowTime)
280             {
281                 DateTimeStr = _T("[") + TimeStr + _T("] ");
282             }
283             s = DateTimeStr + s ;
284         }
285
286         if (bShowLog[channel])
287         {
288             CString s2;
289
290             myCriticalSection2.Lock(INFINITE);
291
292             LineCount[channel]++;
293             int ThreadId=GetCurrentThreadId();
294             if (bShowThreadId &&bShowChannel)
295             {
296                 s2.Format(_T("[%d %4d]"),ThreadId,channel);
297             }else if (bShowChannel)
298             {
299                 s2.Format(_T("[%d]"),channel);
300             }else{
301                 s2.Empty();
302             }
303             if (bShowLineCount)
304             {
305                 s2.AppendFormat(_T("[%d]"),LineCount[channel]);
306             }
307             s2+=s;
308
309             LogTextLength[channel]+=s2.GetLength();
310
311             if (bLogChanged[channel]==1)
312             {
313                 strChangedLog[channel]+=s2;
314             }
315             else
316             {
317                 strChangedLog[channel]=s2;
318             }
319
320             if (strChangedLog[channel].GetLength()>3000000)
321             {
322                 strChangedLog[channel]=strChangedLog[channel].Mid(1000000);
323                 LogTextLength[channel]-=1000000;
324             }
325
326             bLogChanged[channel]=1;
327         }
328         if (bSaveLog[channel])
329         {
330             LogToFile(s,channel);
331         }
332
333         myCriticalSection2.Unlock();
334     }
335     int LogToFile(CString msg,int channel=0)
336     {
337         CString s1;
338         CStringA sa1;
339         CStringA DateStrA,TimeStrA,DateTimeStrA;
340         CStringA msgA;
341         CString DateStrT;
342         CString logfilename;
343         int j;
344 #ifdef UNICODE
345         int l;
346         l=msg.GetLength();
347         j=WideCharToMultiByte(CP_ACP,0,msg,l,msgA.GetBuffer(l*2),l*2,NULL,NULL);
348         msgA.ReleaseBuffer(j);
349 #else
350         msgA=msg;
351 #endif
352         try
353         {
354             CTime time1=CTime::GetTickCount();
355             CString timesecstr;
356             timesecstr.Format(_T("%d"),time1);
357             DateStrA.Format("%04d-%02d-%02d",time1.GetYear(),time1.GetMonth(),time1.GetDay());
358             DateStrT.Format(_T("%04d-%02d-%02d"),time1.GetYear(),time1.GetMonth(),time1.GetDay());
359             TimeStrA.Format("%02d:%02d:%02d",time1.GetHour(),time1.GetMinute(),time1.GetSecond());
360             DateTimeStrA=DateStrA+_T(" ")+TimeStrA;
361             CString LogDirPath,LogFilePath;
362             LogDirPath=LogPath+_T("\\")+DateStrT;
363             if (bOneFilePerHour)
364             {
365                 if (channel==0&&UsedChannelCount==1)
366                 {
367                     logfilename.Format(_T("%slog_%s_%02d.log"),LogFilePrefix,DateStrT,time1.GetHour());
368                     LogFilePath=LogDirPath+_T("\\")+logfilename;
369                 }else
370                 {
371                     logfilename.Format(_T("%slog[%d]_%s_%s_%02d.log"),LogFilePrefix,channel,ChannelPrefix[channel],DateStrT,time1.GetHour());
372                     LogFilePath=LogDirPath+_T("\\")+logfilename;
373                 }
374             }else
375             {
376                 if (channel==0&&UsedChannelCount==1)
377                 {
378                     logfilename.Format(_T("%slog_%s.log"),LogFilePrefix,DateStrT);
379                     LogFilePath=LogDirPath+_T("\\")+logfilename;
380                 }else
381                 {
382                     logfilename.Format(_T("%slog[%d]_%s_%s.log"),LogFilePrefix,channel,ChannelPrefix[channel],DateStrT);
383                     LogFilePath=LogDirPath+_T("\\")+logfilename;
384                 }
385             }
386
387             if (channel>=0&&channel<MAXLOGFILE)
388             {
389                 if (LogFilesOpened[channel])
390                 {
391                     CString oldfilename=CLogFiles[channel].GetFileName();
392                     if (oldfilename!=logfilename)
393                     {
394                         sa1.Format("\r\n-< %s >------- <LogFileClosed> ===== \r\n",DateTimeStrA);
395                         CLogFiles[channel].Write(sa1.GetString(),sa1.GetLength());
396                         CLogFiles[channel].Close();
397                         LogFilesOpened[channel]=0;
398                     }
399                 }
400                 if (!LogFilesOpened[channel]) 
401                 {
402                     CString sAbsPath;
403                     if (IsAbspath(LogDirPath))
404                     {
405                         sAbsPath=LogDirPath;
406                         sAbsPath.Replace(_T("/"),_T("\\"));
407                     }else
408                     {
409                         CString sCurPath;
410                         int len=GetCurrentDirectory(MAX_PATH,sCurPath.GetBuffer(MAX_PATH));
411                         sCurPath.ReleaseBuffer(len);
412                         RelPathToAbsPath(sCurPath,LogDirPath,sAbsPath);
413                     }
414                     SHCreateDirectoryEx(NULL,sAbsPath,NULL);
415
416                     CFileException e;
417                     if (CLogFiles[channel].Open(LogFilePath,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyWrite,&e))
418                     {
419                         CLogFiles[channel].SeekToEnd();
0ed438 420                         sa1.Format("\r\n-< %s >------- <LogFileOpened : %d > ===== \r\n",DateTimeStrA,channel);
4b03ae 421                         CLogFiles[channel].Write(sa1.GetString(),sa1.GetLength());
Q 422                         LogFilesOpened[channel]=1;
423                     }
424                     else
425                     {
426                         LogFilesOpened[channel]=0;
427                         s1.Format(_T("日志文件 %s 操作失败"),LogFilePath);
428                         strChangedLog[channel]+=s1+_T("\r\n");
429                         return false;
430                     }
431                 }
432                 if (LogFilesOpened[channel])
433                 {
434                     if (bShowTime)
435                     {
436                         sa1.Format("%s : %s",DateTimeStrA,msgA);
437                     }
438                     else
439                     {
440                         sa1=msgA;
441                     }
442                     CLogFiles[channel].Write(sa1,sa1.GetLength());
443                     return true;
444                 }
445             }
446
447             return false;
448         }
449         catch (CMemoryException* e)
450         {
451             CString s1;
452             CString stre1;
453             e->GetErrorMessage(stre1.GetBuffer(2048),2048);
454             stre1.ReleaseBuffer();
455             s1.Format(_T("发生错误 %s"),stre1);
456             strChangedLog[channel]+=s1+_T("\r\n");
457             AfxMessageBox(s1);
458             return false;
459         }
460         catch (CFileException* e)
461         {
462             CString s1;
463             CString stre1;
464             e->GetErrorMessage(stre1.GetBuffer(2048),2048);
465             stre1.ReleaseBuffer();
466             s1.Format(_T("发生错误 %s"),stre1);
467             strChangedLog[channel]+=s1+_T("\r\n");
468             AfxMessageBox(s1);
469             return false;
470         }
471         catch (CException* e)
472         {
473             CString s1;
474             CString stre1;
475             e->GetErrorMessage(stre1.GetBuffer(2048),2048);
476             stre1.ReleaseBuffer();
477             s1.Format(_T("发生错误 %s"),stre1);
478             strChangedLog[channel]+=s1+_T("\r\n");
479             AfxMessageBox(s1);
480             return false;
481         }
482         return false;
483     }
0ed438 484     int UpdateLogDisplay(int channel=0)
4b03ae 485     {
Q 486         int i,j,k;
487         if (channel<0 || channel >= MAXLOGFILE)
488         {
489             return 0;
490         }
491         if (bPauseUpdate)
492         {
493             return 0;
494         }
495         if (bLogChanged[channel]==0)
496         {
497             return 0;
498         }
499         if (!myCriticalSection2.Lock(INFINITE))
500         {
501             return -1;
502         }
503         if (IsLogWndAttached==1 && m_pLogWnd && IsWindow(m_pLogWnd->m_hWnd))
504         {
505             if (LogTextLength[channel]>2000000)
506             {
507                 int len = min(strDisplayedLog[channel].GetLength(),1000000);
508
509                 strDisplayedLog[channel]=strDisplayedLog[channel].Mid(len);
510
511                 m_pLogWnd->SetSel(0,len);
512                 m_pLogWnd->Clear();
513                 LogTextLength[channel]-=len;
514             }
515
516             int line1,line2;
517             line1=m_pLogWnd->GetFirstVisibleLine();
518             i=m_pLogWnd->GetLineCount();
519
520             j=m_pLogWnd->LineIndex(i-1);
521             m_pLogWnd->SetSel(j,j,true);
522
523             k=m_pLogWnd->LineIndex(-1)+m_pLogWnd->LineLength(-1);
524             m_pLogWnd->SetSel(k,k,true);
525
526             m_pLogWnd->ReplaceSel(strChangedLog[channel]);
527             line2=m_pLogWnd->GetFirstVisibleLine();
528
529             strDisplayedLog[channel]+=strChangedLog[channel];
530             if (bNoScroll)
531             {
532                 m_pLogWnd->LineScroll(line1-line2);
533             }
534         }else if (IsLogWndAttached==2 && m_pRichLogWnd && IsWindow(m_pRichLogWnd->m_hWnd))
535         {
536             if (LogTextLength[channel]>2000000)
537             {
538                 int len = min(strDisplayedLog[channel].GetLength(),1000000);
539
540                 strDisplayedLog[channel]=strDisplayedLog[channel].Mid(len);
541
542                 m_pRichLogWnd->SetSel(0,len);
543                 m_pRichLogWnd->Clear();
544                 LogTextLength[channel]-=len;
545             }
546
547             int line1,line2;
548             line1=m_pRichLogWnd->GetFirstVisibleLine();
549             i=m_pRichLogWnd->GetLineCount();
550
551             j=m_pRichLogWnd->LineIndex(i-1);
552             m_pRichLogWnd->SetSel(j,j);
553
554             k=m_pRichLogWnd->LineIndex(-1)+m_pLogWnd->LineLength(-1);
555             m_pRichLogWnd->SetSel(k,k);
556
557             m_pRichLogWnd->ReplaceSel(strChangedLog[channel]);
558             line2=m_pRichLogWnd->GetFirstVisibleLine();
559
560             strDisplayedLog[channel]+=strChangedLog[channel];
561             if (bNoScroll)
562             {
563                 m_pRichLogWnd->LineScroll(line1-line2);
564             }
565         }
566
567         strChangedLog[channel].Empty();
568         bLogChanged[channel]=0;
569
570         myCriticalSection2.Unlock();
571         return 0;
572     }
573 };