⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 logger.cpp

📁 这是本人在工作中积累的VC++类库
💻 CPP
字号:
/************************************************************************
模快名:		moxu 公共类库
功能:		日志打印
完成日期:	2007-10-20
作者:		许 培 Xu Pei(Email/MSN: peimoxu@163.com)

本代码可以自由使用,但因使用本代码造成的后果,本人不承担任何责任
************************************************************************/

#include "StdAfx.h"
#include "Logger.h"
#include <time.h>
#include "Config.h"
#include "ScopeGuard.h"
#include "PathFile.h"

#define WM_PRINT_MSG	WM_USER+1
#define WM_CLOSE_LOG	WM_USER+2
#define WM_SET_CAPTION	WM_USER+3
namespace moxu
{

namespace detail
{
	//////////////////////////////////////////////////////////////////////////
	//FileLog
	bool FileLog::Create()
	{
		time_t	t = time(0);
		tm* pTm = localtime(&t);
		m_fileName = TString(_T("c:\\")) + m_caption +
			moxu::Str::Format(_T("%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d"),
			pTm->tm_year+1900, pTm->tm_mon+1, pTm->tm_mday, 
			pTm->tm_hour, pTm->tm_min, pTm->tm_sec)
			+ _T(".log");

		m_file.imbue(std::locale("chs"));
		m_file.open(moxu::Str::TtoA(m_fileName.c_str()).c_str(), 
			std::ios_base::out | std::ios_base::app);
		m_bCreated = true;
		return true; 
	}

	void FileLog::Close()
	{
		if(m_bCreated)
		{
			m_file.close();
			m_bCreated = false;
		}
	}

	void FileLog::Print(const TString& msg)
	{
		if(m_bCreated)
			m_file<<msg<<std::endl;
	}

	void FileLog::SetCaption(const TString& str)
	{ 
		m_caption = str;
		if(m_bCreated)
		{
			Close();
			Create();
		}
	}

	//////////////////////////////////////////////////////////////////////////
	//WndLog
	bool WndLog::Create()
	{
		WNDCLASSEX winclass = {0}; 
		winclass.cbSize = sizeof(WNDCLASSEX);
		winclass.style = CS_NOCLOSE | CS_HREDRAW | CS_VREDRAW;
		winclass.lpfnWndProc = WindowProc;
		winclass.hInstance = 0;
		winclass.hbrBackground = (HBRUSH)(COLOR_WINDOW);
		winclass.lpszClassName = _T("MYLOGGERWND");
		winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
		RegisterClassEx(&winclass);

		m_hWnd = CreateWindowEx(
			WS_EX_TOPMOST /*| WS_EX_TOOLWINDOW*/,
			_T("MYLOGGERWND"), 
			m_caption.c_str(),  
			WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
			CW_USEDEFAULT, CW_USEDEFAULT, 600, 300, 
			NULL, 
			NULL, 
			NULL, 
			NULL);

		SetWindowLong(m_hWnd, GWL_USERDATA, (long)this);

		RECT rct;
		GetClientRect(m_hWnd, &rct);

		m_hList = CreateWindowEx(
			WS_EX_CLIENTEDGE, 
			_T("ListBox"), 
			_T("MyListBox"),  
			WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | LBS_NOINTEGRALHEIGHT, 
			rct.left, rct.top, rct.right, rct.bottom,
			m_hWnd, 
			NULL, 
			(HINSTANCE)GetWindowLong(m_hWnd, GWL_HINSTANCE), 
			NULL);

		HFONT font = CreateFont(
			16, 0, 0, 10,   
			0, false, false, false,   
			ANSI_CHARSET,OUT_CHARACTER_PRECIS,   
			CLIP_CHARACTER_PRECIS,ANTIALIASED_QUALITY,   
			FF_DECORATIVE,   
			_T("Courier New"));  

		SendMessage(m_hList, WM_SETFONT,(WPARAM)font,(LPARAM)1);
		m_bCreated = true;
		return true;
	}

	void WndLog::Close()
	{
		if(m_bCreated)
		{
			SendMessage(m_hWnd, WM_CLOSE, 0, 0);
			m_bCreated = false;
		}
	}

	void WndLog::Print(const TString& msg)
	{
		if(m_bCreated)
		{
			SendMessage(m_hList, LB_INSERTSTRING, 0, (LPARAM)msg.c_str());

			//Max size is 200, delete old item
			SendMessage(m_hList, LB_DELETESTRING, 200, 0);	
			/*//显示水平滚动条
			HDC   hdc=::GetDC(m_hList);   
			SIZE   size;   
			GetTextExtentPoint32(hdc, _T(""), lstrlen(_T("")),&size);     
			ReleaseDC(m_hList,hdc);
			SendMessage(m_hList,LB_SETHORIZONTALEXTENT,(WPARAM)size.cx,0);
			*/
		}
	}

	void WndLog::SetCaption(const TString& str)
	{ 
		m_caption = str;
		if(m_bCreated)
			SetWindowText(m_hWnd, m_caption.c_str());
	}

	LRESULT CALLBACK WndLog::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		WndLog* pThis = (WndLog*)GetWindowLong(hWnd, GWL_USERDATA);

		switch(uMsg)
		{
		case WM_SIZE : 
			if(SIZE_RESTORED == wParam || SIZE_MAXIMIZED == wParam)
			{		
				if(pThis != NULL)
					MoveWindow(pThis->m_hList, 0, 0, LOWORD(lParam), HIWORD(lParam), false);
			}
			break;
		case WM_SETFOCUS: 
			if( pThis != NULL ) 
				SetFocus((HWND)pThis->m_hList); 
			break;
		/*case WM_CLOSE:
			if(MessageBox(hWnd, _T("您确实要关闭日志窗口吗?"), _T("日志窗口"), 
				MB_ICONINFORMATION | MB_YESNO) != IDYES)
				return 1;
			break;*/
		default:
			break;
		}
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}

}//namespace detail


//////////////////////////////////////////////////////////////////////////
//Logger
Logger::Logger(void) :
m_bInfo(false), 
m_bDebug(false), 
m_bError(false),
m_bFileLog(false), 
m_bWndLog(false),
m_pFileLog(NULL), 
m_pWndLog(NULL)
{
}

Logger::~Logger(void)
{
	if(m_bFileLog || m_bWndLog)
		Close();
}

bool Logger::Create()
{
	m_semaphore.Create(0, 1);
	m_thread.Start(moxu::Bind(this, Logger::RunThread));
	m_semaphore.Wait();	//wait first CheckConfig() in RunThread()
	m_semaphore.Close();
	return true;
}

void Logger::SetCaption(const TString& str)
{ 
	moxu::ScopedLock locker(m_cs2);
	m_caption = str;
	if(m_bFileLog || m_bWndLog)
		PostThreadMessage(m_thread.GetId(), WM_SET_CAPTION, 0, 0);
}

void Logger::Close()
{
	PostThreadMessage(m_thread.GetId(), WM_CLOSE_LOG, 0, 0);
	m_thread.Join();
}

void Logger::RunThread()
{
	MSG msg;
	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);

	CheckConfig();
	m_semaphore.Release(1);

	UINT timerId = SetTimer(NULL, 0, 30*1000, NULL);
	int nTimeCounter = 0; 

	BOOL ret;
	while((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
	{
		//if(ret == -1){ error }
		if(msg.message == WM_TIMER && msg.wParam == timerId)
		{
			CheckConfig();
			if(m_bFileLog)
			{
				nTimeCounter++;
				if(nTimeCounter == 10)
				{
					UINT64 size = moxu::PathFile::GetFileSize(
						((detail::FileLog*)m_pFileLog)->GetFileName().c_str());

					if(size > 1024*1024*5) //当文件过大时更换文件名
					{
						m_pFileLog->Close();
						m_pFileLog->Create();
					}
					nTimeCounter = 0;
				}
			}
		}
		else if(msg.message == WM_PRINT_MSG)
		{
			Print();
		}
		else if(msg.message == WM_SET_CAPTION)
		{
			moxu::ScopedLock locker(m_cs2);
			if(m_bWndLog)
				m_pWndLog->SetCaption(m_caption);
			if(m_bFileLog)
				m_pFileLog->SetCaption(m_caption);
		}
		else if(msg.message == WM_CLOSE_LOG)
		{
			if(m_bWndLog)
			{
				m_pWndLog->Close();
				delete m_pWndLog;
				m_pWndLog = NULL;
				m_bWndLog = false;
			}
			if(m_bFileLog)
			{
				m_pFileLog->Close();
				delete m_pFileLog;
				m_pFileLog = NULL;
				m_bFileLog = false;
			}
			m_bInfo = false;
			m_bDebug = false;
			m_bError = false;
			moxu::ScopedLock locker(m_cs);
			m_strList.clear();
			break;
		}
		else
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	KillTimer(NULL, timerId);
}

void Logger::Info(LPCTSTR str, ...)
{
	if(m_bInfo)
	{
		va_list args;
		va_start(args, str);
		AddLog(str, args);
		va_end(args);
	}
}

void Logger::Debug(LPCTSTR str, ...)
{
	if(m_bDebug)
	{
		va_list args;
		va_start(args, str);
		AddLog(str, args);
		va_end(args);
	}
}

void Logger::Error(LPCTSTR str, ...)
{
	if(m_bError)
	{
		va_list args;
		va_start(args, str);
		AddLog(str, args);
		va_end(args);
	}
}

void Logger::AddLog(LPCTSTR str, va_list args)
{
	int len = 9 + (_vsctprintf(str, args) + 1);	//message format: "hh:mm:ss message"
	LPTSTR pStr = new TCHAR[len];

	if(pStr == NULL)
		throw _T("Alloc memory error");
	moxu::ScopeGuard sg = moxu::MakeArrayGuard(pStr);

	_tstrtime(pStr);
	pStr[8] = ' ';
	_vstprintf(pStr+9, str, args);

	moxu::ScopedLock locker(m_cs);
	m_strList.push_back(pStr);
	PostThreadMessage(m_thread.GetId(), WM_PRINT_MSG, 0, 0);
}

void Logger::Print()
{
	moxu::ScopedLock locker(m_cs);
	for(int i=0; i<m_strList.size(); i++)
	{
		if(m_bWndLog)
			m_pWndLog->Print(m_strList[i]);
		if(m_bFileLog)
			m_pFileLog->Print(m_strList[i]);
	}
	m_strList.clear();
}

void Logger::CheckConfig()
{
	bool bWndLog, bFileLog;

	bWndLog = moxu::Config::GetIniInt(_T("..\\Logger.ini"), _T("Test"), _T("WndLog"), 0);
	if(m_bWndLog != bWndLog)
	{
		m_bWndLog = bWndLog;
		if(m_bWndLog)
		{
			m_pWndLog = new detail::WndLog;
			m_pWndLog->SetCaption(m_caption);
			if(!m_pWndLog->Create())
			{
				m_bWndLog = false;
			}
		}
		else
		{
			m_pWndLog->Close();
			delete m_pWndLog;
			m_pWndLog = NULL;
		}
	}

	bFileLog = moxu::Config::GetIniInt(_T("..\\Logger.ini"), _T("Test"), _T("FileLog"), 0);
	if(m_bFileLog != bFileLog)
	{
		m_bFileLog = bFileLog;
		if(m_bFileLog)
		{
			m_pFileLog = new detail::FileLog;
			m_pFileLog->SetCaption(m_caption);
			if(!m_pFileLog->Create())
			{
				m_bFileLog = false;
			}
		}
		else
		{
			m_pFileLog->Close();
			delete m_pFileLog;
			m_pFileLog = NULL;
		}
	}

	if(m_bWndLog || m_bFileLog)
	{
		m_bInfo = moxu::Config::GetIniInt(_T("..\\Logger.ini"), _T("Test"), _T("Info"), 0);
		m_bDebug = moxu::Config::GetIniInt(_T("..\\Logger.ini"), _T("Test"), _T("Debug"), 0);
		m_bError = moxu::Config::GetIniInt(_T("..\\Logger.ini"), _T("Test"), _T("Error"), 0);
	}
	else
	{
		m_bInfo = false;
		m_bDebug = false;
		m_bError = false;
		moxu::ScopedLock locker(m_cs);
		m_strList.clear();
	}
}

}//namespace moxu



/*
软件运行时,可修改配置文件,
#include "stdafx.h"
#include <Logger.h>
#include <conio.h>

using namespace moxu;

int main()
{
Logger logger;
logger.Create();
logger.SetCaption(_T("Test Log"));

int c = 1000;
while(c--)
{
logger.Error(_T("log %d"), c+1);
Sleep(500);
}

getch();
return 0;
}


*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -