356 lines
No EOL
8.4 KiB
C++
356 lines
No EOL
8.4 KiB
C++
#include "stdafx.h"
|
|
#include "LogWnd.h"
|
|
#include <time.h>
|
|
|
|
#pragma warning(disable:4311)
|
|
#pragma warning(disable:4312)
|
|
|
|
namespace LogWnd {
|
|
|
|
|
|
PCMD_PROC g_pCallBack = NULL;
|
|
#define CMD_EDIT 100
|
|
|
|
class __LogWnd
|
|
{
|
|
public:
|
|
__LogWnd( bool bAttachDate = false, DWORD nTarget = LOG_TARGET_WINDOW, const TCHAR* szFilename = NULL, const TCHAR* szPath = NULL );
|
|
virtual ~__LogWnd();
|
|
|
|
int Log( int nLogLevel, const TCHAR* szLog );
|
|
|
|
private:
|
|
void CreateLogWindow();
|
|
|
|
bool m_bAttachDate;
|
|
unsigned int m_nTarget;
|
|
TCHAR m_szFilename[8192];
|
|
HWND m_hwnd;
|
|
HWND m_hwndList;
|
|
static HWND m_hwndEdit;
|
|
static WNDPROC m_OldEditProc;
|
|
|
|
private:
|
|
static LRESULT CALLBACK __LogWnd::WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
|
static LRESULT CALLBACK __LogWnd::EditSubWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
|
};
|
|
|
|
HWND __LogWnd::m_hwndEdit= NULL;
|
|
WNDPROC __LogWnd::m_OldEditProc= NULL;
|
|
|
|
__LogWnd* g_pLog = NULL;
|
|
|
|
//-------------------------------------------------------------------------------------------------------------
|
|
__LogWnd::__LogWnd( bool bAttachDate, DWORD nTarget, const TCHAR* szFilename, const TCHAR* szPath )
|
|
{
|
|
m_bAttachDate = bAttachDate;
|
|
m_nTarget = nTarget;
|
|
ZeroMemory( m_szFilename, sizeof(TCHAR) * 1024 );
|
|
|
|
if( nTarget & LOG_TARGET_FILE )
|
|
{
|
|
if( szFilename == NULL )
|
|
{
|
|
struct tm now;
|
|
time_t systemTime;
|
|
|
|
time(&systemTime); // 현재 시각을 초 단위로 얻기
|
|
localtime_s(&now, &systemTime); // 초 단위의 시간을 분리하여 구조체에 넣기
|
|
|
|
// 현재 실행 모듈을 알아낸다.
|
|
TCHAR szCurFileName[MAX_PATH] = {0,};
|
|
::GetModuleFileName (NULL, szCurFileName, MAX_PATH );
|
|
TCHAR __szDrive[MAX_PATH] = { 0, };
|
|
TCHAR __szDir[MAX_PATH] = { 0, };
|
|
TCHAR __szFileName[MAX_PATH] = { 0, };
|
|
TCHAR __szExt[MAX_PATH] = { 0, };
|
|
|
|
_splitpath_s( szCurFileName, __szDrive, __szDir, __szFileName, __szExt );
|
|
|
|
_sntprintf_s( m_szFilename, 4000, _T("%s%s\\Log\\%s_%04d%02d%02d_%02d%02d%02d_Log.txt"), __szDrive, __szDir, __szFileName,
|
|
1900+now.tm_year, now.tm_mon+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec );
|
|
}
|
|
else
|
|
_tcscpy_s( m_szFilename, szFilename );
|
|
}
|
|
else
|
|
m_szFilename[0] = NULL;
|
|
|
|
if( nTarget & LOG_TARGET_WINDOW )
|
|
CreateLogWindow();
|
|
else
|
|
m_hwnd = NULL;
|
|
|
|
Log( LogLevel::Info, _T("Logging Start..") );
|
|
}
|
|
|
|
__LogWnd::~__LogWnd()
|
|
{
|
|
DestroyWindow( m_hwnd );
|
|
}
|
|
|
|
void __LogWnd::CreateLogWindow()
|
|
{
|
|
int x, y, cx, cy;
|
|
WNDCLASS wc;
|
|
RECT rc;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
wc.lpfnWndProc = (WNDPROC)__LogWnd::WndProc;
|
|
wc.cbClsExtra = 0; // No Extra Window Data
|
|
wc.cbWndExtra = 0; // No Extra Window Data
|
|
wc.hInstance = GetModuleHandle( NULL );
|
|
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
|
|
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH) ;
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = _T("LogWindow");
|
|
|
|
RegisterClass( &wc );
|
|
|
|
cx = LOG_WINDOW_CX;
|
|
cy = LOG_WINDOW_CY;
|
|
x = GetSystemMetrics( SM_CXSCREEN ) - cx;
|
|
y = 0;
|
|
|
|
// 현재 실행 모듈을 알아낸다.
|
|
TCHAR szCurFileName[MAX_PATH];
|
|
::GetModuleFileName( NULL, szCurFileName, MAX_PATH );
|
|
|
|
TCHAR drive[_MAX_DRIVE];
|
|
TCHAR dir[_MAX_DIR];
|
|
TCHAR fname[_MAX_FNAME];
|
|
TCHAR ext[_MAX_EXT];
|
|
|
|
_splitpath_s( szCurFileName, drive, dir, fname, ext );
|
|
|
|
m_hwnd = CreateWindow( _T("LogWindow"), fname, WS_OVERLAPPED | WS_CAPTION, x, y, cx, cy, NULL, NULL, GetModuleHandle( NULL ), NULL );
|
|
DWORD nError = GetLastError();
|
|
GetClientRect( m_hwnd, &rc );
|
|
|
|
m_hwndList = CreateWindow( _T("LISTBOX"), _T(""), WS_CHILD | WS_VSCROLL | WS_HSCROLL, 0, 0, rc.right, rc.bottom-30, m_hwnd, NULL, GetModuleHandle( NULL ), NULL );
|
|
m_hwndEdit = CreateWindow( _T("edit"), _T(""), WS_CHILD|WS_BORDER|ES_NOHIDESEL , 0, rc.bottom-30, rc.right, 30, m_hwnd, (HMENU)CMD_EDIT, GetModuleHandle( NULL ), NULL );
|
|
|
|
ShowWindow( m_hwnd, SW_SHOW );
|
|
ShowWindow( m_hwndList, SW_SHOW );
|
|
ShowWindow( m_hwndEdit, SW_SHOW );
|
|
|
|
m_OldEditProc = (WNDPROC)SetWindowLong( m_hwndEdit, GWL_WNDPROC, LONG((WNDPROC)__LogWnd::EditSubWndProc) );
|
|
}
|
|
|
|
int __LogWnd::Log( int nLogLevel, const TCHAR* szLog )
|
|
{
|
|
struct tm now;
|
|
time_t systemTime;
|
|
|
|
time( &systemTime ); // 현재 시각을 초 단위로 얻기
|
|
localtime_s( &now, &systemTime ); // 초 단위의 시간을 분리하여 구조체에 넣기
|
|
|
|
TCHAR szTotal[2048] = _T("");
|
|
ZeroMemory(szTotal, sizeof(TCHAR) * 2048);
|
|
|
|
TCHAR szErrorLevel[128] = {0,};
|
|
switch( nLogLevel )
|
|
{
|
|
case LogLevel::Error:
|
|
_tcscpy_s( szErrorLevel, _T("error") );
|
|
break;
|
|
case LogLevel::Warning:
|
|
_tcscpy_s( szErrorLevel, _T("warning") );
|
|
break;
|
|
case LogLevel::Info:
|
|
_tcscpy_s( szErrorLevel, _T("info") );
|
|
break;
|
|
case LogLevel::Debug:
|
|
_tcscpy_s( szErrorLevel, _T("debug") );
|
|
break;
|
|
}
|
|
|
|
if( m_bAttachDate )
|
|
{
|
|
if( m_nTarget & LOG_TARGET_WINDOW )
|
|
{
|
|
_sntprintf_s(szTotal, 2048, _T("%04d%02d%02d%02d%02d%02d [%s] %s"),
|
|
1900+now.tm_year, now.tm_mon+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, szErrorLevel, szLog );
|
|
}
|
|
else
|
|
{
|
|
_sntprintf_s(szTotal, 2048, _T("%04d%02d%02d%02d%02d%02d [%s]\t%s"),
|
|
1900+now.tm_year, now.tm_mon+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, szErrorLevel, szLog );
|
|
}
|
|
}
|
|
else
|
|
_sntprintf_s(szTotal, 2048, _T("[Lv:%d]=>%s"), nLogLevel, szLog );
|
|
|
|
// Log File에 출력할 경우
|
|
if( m_nTarget & LOG_TARGET_FILE )
|
|
{
|
|
FILE* fp = NULL;
|
|
errno_t error = _tfopen_s( &fp, m_szFilename, _T("a+") );
|
|
if( fp )
|
|
{
|
|
#ifdef _UNICODE
|
|
char szTemp[2048] = { 0, };
|
|
WideCharToMultiByte( CP_ACP, 0, szTotal, -1, szTemp , 2048, NULL, NULL );
|
|
fprintf_s( fp, "%s\n", szTemp);
|
|
#else
|
|
fprintf_s( fp, "%s\n", szTotal);
|
|
fclose( fp );
|
|
#endif
|
|
fclose( fp );
|
|
}
|
|
}
|
|
|
|
static const int nEnterLineLen = 65;
|
|
// Log Window에 출력할 경우
|
|
if( m_nTarget & LOG_TARGET_WINDOW )
|
|
{
|
|
#ifdef _UNICODE
|
|
std::wstring szLogMsg;
|
|
#else
|
|
std::string szLogMsg;
|
|
#endif
|
|
szLogMsg = szTotal;
|
|
|
|
while( szLogMsg.size() > 0 )
|
|
{
|
|
#ifdef _UNICODE
|
|
std::wstring szTemp;
|
|
#else
|
|
std::string szTemp;
|
|
#endif
|
|
szTemp = szLogMsg.substr( 0, min(nEnterLineLen, szLogMsg.size()) );
|
|
szLogMsg.erase( 0, min(nEnterLineLen, szLogMsg.size()) );
|
|
SendMessage( m_hwndList, LB_ADDSTRING, 0, (LPARAM) szTemp.c_str() );
|
|
LRESULT n = SendMessage( m_hwndList, LB_GETCOUNT, 0, 0L ) - 1;
|
|
SendMessage( m_hwndList, LB_SETCURSEL, (WPARAM)n, 0L );
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
LRESULT CALLBACK __LogWnd::EditSubWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
case WM_CHAR:
|
|
{
|
|
if( wParam == VK_RETURN )
|
|
return 1;
|
|
}
|
|
break;
|
|
case WM_KEYDOWN:
|
|
{
|
|
if( wParam == VK_RETURN )
|
|
{
|
|
static TCHAR s_CmdBuff[2048] = _T("");
|
|
GetWindowText( m_hwndEdit, s_CmdBuff, 2048-1 );
|
|
|
|
if( g_pCallBack )
|
|
g_pCallBack(s_CmdBuff);
|
|
|
|
SetWindowText( m_hwndEdit, _T("") );
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc( m_OldEditProc,hwnd,uMsg,wParam,lParam );
|
|
}
|
|
|
|
LRESULT CALLBACK __LogWnd::WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
case WM_ACTIVATE:
|
|
{
|
|
SetFocus( m_hwndEdit );
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
{
|
|
if( wParam == VK_RETURN )
|
|
return 0;
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
SetWindowLong( m_hwndEdit, GWL_WNDPROC, (LONG)m_OldEditProc );
|
|
}
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc( hwnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------
|
|
bool CreateLog( bool bAttachDate, DWORD nLogTarget, const TCHAR* szFileName )
|
|
{
|
|
if( g_pLog )
|
|
return false;
|
|
|
|
g_pLog = new __LogWnd( bAttachDate, nLogTarget, szFileName );
|
|
|
|
return true;
|
|
}
|
|
|
|
void SetCommandCallBack( PCMD_PROC pCallBack )
|
|
{
|
|
g_pCallBack = pCallBack;
|
|
}
|
|
|
|
void Log( int nLogLevel, const TCHAR* fmt, ... )
|
|
{
|
|
if( nLogLevel < 0 || g_pLog == NULL )
|
|
return;
|
|
|
|
static TCHAR gs_Buffer[2048] = { _T('0'), };
|
|
|
|
ZeroMemory( gs_Buffer, sizeof(TCHAR) * 2048 );
|
|
va_list args;
|
|
va_start( args, fmt );
|
|
_vsntprintf_s( gs_Buffer, 2048-1, fmt, args );
|
|
va_end( args );
|
|
gs_Buffer[2048-1] = 0;
|
|
|
|
g_pLog->Log( nLogLevel, gs_Buffer );
|
|
}
|
|
|
|
void TraceLog( const TCHAR* fmt, ... )
|
|
{
|
|
if( g_pLog == NULL )
|
|
return;
|
|
|
|
static TCHAR gs_Buffer[2048] = { _T('0'), };
|
|
|
|
ZeroMemory( gs_Buffer, sizeof(TCHAR) * 2048 );
|
|
va_list args;
|
|
va_start( args, fmt );
|
|
_vsntprintf_s( gs_Buffer, 2048-1, fmt, args );
|
|
va_end( args );
|
|
gs_Buffer[2048-1] = 0;
|
|
|
|
CString str;
|
|
str = gs_Buffer;
|
|
str += _T('\n');
|
|
|
|
TRACE( str.GetBuffer() );
|
|
g_pLog->Log( LogLevel::Debug, gs_Buffer );
|
|
}
|
|
|
|
bool DestroyLog()
|
|
{
|
|
if( g_pLog )
|
|
{
|
|
SAFE_DELETE( g_pLog );
|
|
g_pLog = NULL;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
}; // namespace LogWnd;
|