自己实现一个DebugView
#include "stdafx.h"
#include "SimpleDbgView.h"
#include "SimpleDbgViewDlg.h"
#include <new>
#include "FilterDlg.h"
#include "ScreenCapture.h"
#include "ClipBoardHelp.h"
#include "aboutdlg.h"
using namespace std;
#define WM_USER_ADDLOG (WM_USER+0x1002)
CSimpleDbgViewDlg::CSimpleDbgViewDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSimpleDbgViewDlg::IDD, pParent)
, m_strPID(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
m_pList = NULL;
m_bAutoScroll = 0;
m_bExclude = 0;
m_dwPID = 0xFFFFFFFF;
}
void CSimpleDbgViewDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_strPID);
}
BEGIN_MESSAGE_MAP(CSimpleDbgViewDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_DESTROY()
ON_MESSAGE(WM_USER_ADDLOG, OnAddMsg)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_BUTTON1, &CSimpleDbgViewDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CSimpleDbgViewDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON3, &CSimpleDbgViewDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CSimpleDbgViewDlg::OnBnClickedButton4)
ON_COMMAND(ID_FILE_SAVELOG, &CSimpleDbgViewDlg::OnFileSavelog)
ON_COMMAND(ID_FILE_EXIT, &CSimpleDbgViewDlg::OnFileExit)
ON_COMMAND(ID_FILE_SAVEAS, &CSimpleDbgViewDlg::OnFileSaveas)
ON_COMMAND(ID_HELP_ABOUT, &CSimpleDbgViewDlg::OnHelpAbout)
ON_COMMAND(ID_FILTER_EDITFILTERS, &CSimpleDbgViewDlg::OnFilterEditfilters)
ON_EN_CHANGE(IDC_EDIT1, &CSimpleDbgViewDlg::OnEnChangeEdit1)
ON_BN_CLICKED(IDC_BUTTON5, &CSimpleDbgViewDlg::OnBnClickedButton5)
ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, &CSimpleDbgViewDlg::OnLvnKeydownList1)
END_MESSAGE_MAP()
LRESULT CSimpleDbgViewDlg::OnAddMsg(WPARAM wp, LPARAM lp)
{
CString* str = (CString*)wp;
if(str)
{
if(m_pList)
{
WCHAR szTime[100];
swprintf(szTime, L"%u", GetTickCount());
int rc = m_pList->GetItemCount();
m_pList->InsertItem(rc , szTime);
m_pList->SetItemText(rc , 1, (*str));
if(rc == 0)
{
RECT rcC;
::GetClientRect(m_hWnd, &rcC);
int cx = rcC.right - rcC.left;
int cy = rcC.bottom - rcC.top;
OnSize(0, cx, cy);
}
if(m_bAutoScroll)
{
m_pList->EnsureVisible(rc, FALSE); //设置滚动条到最下面
//nColumn为当前记录条数
}
}
delete str;
}
return 0;
}
BOOL CSimpleDbgViewDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if(pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
//
m_custom_list.SubclassDlgItem(IDC_LIST1, this);
m_pList = &m_custom_list;
InitList();
StartDbgThread();
SetWindowPos(0, 0, 0, _S(800), _S(600), SWP_NOZORDER | SWP_NOMOVE);
return TRUE;
}
void CSimpleDbgViewDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
if(nID == SC_CLOSE)
{
EndDialog((IDOK));
return;
}
CDialog::OnSysCommand(nID, lParam);
}
}
void CSimpleDbgViewDlg::OnPaint()
{
if(IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CSimpleDbgViewDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CSimpleDbgViewDlg::OnDestroy()
{
m_custom_list.UnsubclassWindow();
CDialog::OnDestroy();
}
void CSimpleDbgViewDlg::OnSize(UINT nType, int cx, int cy)
{
if(m_pList)
{
m_pList->SetWindowPos(0, 0, _S(20), cx , cy - _S(20), SWP_NOZORDER);
}
}
void CSimpleDbgViewDlg::InitList()
{
if(m_pList)
{
m_pList->SetExtendedStyle(m_pList->GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_SINGLEROW);
m_pList->InsertColumn(0, L"Tick Time", LVCFMT_LEFT, 100);
m_pList->InsertColumn(1, L"Dbg Print", LVCFMT_LEFT, 1800);
m_pList->DeleteAllItems();
}
}
/***************************************************************************************
*
* 关于DebugLog如何抓取的代码
*
**************************************************************************************/
#define MAX_DEBUG_BUF_LEN (4096)
#pragma pack(push)
#pragma pack(1)
typedef struct __DEBUGBUFFER
{
DWORD dwPID;
char szString[MAX_DEBUG_BUF_LEN - sizeof(DWORD)];
} DEBUGBUFFER, *PDEBUGBUFFER;
#pragma pack(pop)
DWORD WINAPI __get_log_thread(LPVOID lpp)
{
CSimpleDbgViewDlg* pDlg = (CSimpleDbgViewDlg*)lpp;
if(!pDlg)
return -1;
HANDLE hReadyEvent = NULL;
DWORD dwResult = ERROR_INVALID_HANDLE;
HANDLE hMapping = NULL;
HANDLE hAckEvent = NULL;
PDEBUGBUFFER pdbBuffer = NULL;
do
{
hAckEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_BUFFER_READY"));// 打开事件句柄
if(!hAckEvent)
break;
hReadyEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_DATA_READY"));
if(!hReadyEvent)
break;
// 创建文件映射
hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_DEBUG_BUF_LEN, TEXT("DBWIN_BUFFER"));
if(!hMapping)
break;
// 映射调试缓冲区
pdbBuffer = (PDEBUGBUFFER) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if(pdbBuffer == NULL)
break;
for(dwResult = ERROR_SIGNAL_PENDING; (dwResult == ERROR_SIGNAL_PENDING);)
{
SetEvent(hAckEvent);//发给调用OutputDebugString的程序,告诉他,缓冲区已经就绪
// 等待缓冲区数据
if(WaitForSingleObject(hReadyEvent, INFINITE) == WAIT_OBJECT_0)
{
// 如果是继续等待,否则表示主线程发出了停止信号,退出当前线程
if(dwResult == ERROR_SIGNAL_PENDING)
{
// 添加新项
pDlg->AddLogItem(pdbBuffer->dwPID, pdbBuffer->szString);
}
}
else
{
// 等待失败
dwResult = WAIT_ABANDONED;
}
}
}
while(0);
// 释放
if(pdbBuffer)
UnmapViewOfFile(pdbBuffer);
if(hMapping)
CloseHandle(hMapping);
if(hReadyEvent)
CloseHandle(hReadyEvent);
if(hAckEvent)
CloseHandle(hAckEvent);
return dwResult;
}
void CSimpleDbgViewDlg::StartDbgThread()
{
HANDLE hThread =::CreateThread(0, 0, __get_log_thread, this, 0, 0);
}
void CSimpleDbgViewDlg::AddLogItem(DWORD dwPID, char* szString)
{
if(szString)
{
if(m_dwPID != 0xFFFFFFFF && dwPID != m_dwPID)
{
return;
}
if(Filter_Pass(szString))
{
return;
}
CString* strDbgAdd = new(nothrow)CString;
if(strDbgAdd)
{
strDbgAdd->Format(L"[%u] %s", dwPID, CStringW(szString));
this->PostMessage(WM_USER_ADDLOG, (WPARAM)strDbgAdd);
}
}
}
void CSimpleDbgViewDlg::OnBnClickedButton1()
{
// TODO: Save
SaveLog();
}
void CSimpleDbgViewDlg::OnBnClickedButton2()
{
// TODO: Clear
if(m_pList)
{
m_pList->DeleteAllItems();
}
}
void CSimpleDbgViewDlg::OnBnClickedButton3()
{
// TODO: AutoScroll
m_bAutoScroll = TRUE;
}
void CSimpleDbgViewDlg::OnBnClickedButton4()
{
// TODO: NotAutoScroll
m_bAutoScroll = FALSE;
}
void CSimpleDbgViewDlg::OnFileSavelog()
{
// TODO:
SaveLog();
}
void CSimpleDbgViewDlg::SaveLog()
{
if(m_strLogFileName.GetLength())
{
_SaveLog(m_strLogFileName);
}
else
{
m_strLogFileName = SelectFile();
_SaveLog(m_strLogFileName);
}
}
void CSimpleDbgViewDlg::OnFileExit()
{
EndDialog(IDOK);
}
void CSimpleDbgViewDlg::OnFileSaveas()
{
m_strLogFileName = L"";
SaveLog();
}
void CSimpleDbgViewDlg::_SaveLog(CString strLogFileName)
{
if(strLogFileName.GetLength())
{
if(m_pList)
{
FILE* fp = _wfopen(strLogFileName, L"wb+");
if(fp)
{
SetWindowText(strLogFileName);
int rc = m_pList->GetItemCount();
for(int i = 0; i < rc; i++)
{
CString strItem1 = m_pList->GetItemText(i, 0);
CString strItem2 = m_pList->GetItemText(i, 1);
CStringA strS;
strS.Format("[%s] %s\r\n", CStringA(strItem1), CStringA(strItem2));
fwrite((LPCSTR)strS, 1, strS.GetLength(), fp);
}
fclose(fp);
}
}
}
}
CString CSimpleDbgViewDlg::SelectFile()
{
CString strRet;
CFileDialog fd(0, L".log", m_strLogFileName.GetLength() ? m_strLogFileName : L"SimpleDbgView.log");
if(fd.DoModal() == IDOK)
{
strRet = fd.GetPathName();
}
return strRet;
}
void CSimpleDbgViewDlg::OnHelpAbout()
{
// TODO: 在此添加命令处理程序代码
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
void CSimpleDbgViewDlg::OnFilterEditfilters()
{
// TODO: 在此添加命令处理程序代码
FilterDlg dlg;
dlg.DoModal();
LoadCfg();
}
const char * __cdecl strstr_i(const char * str1, const char * str2)
{
const char *cp = (char *) str1;
const char *s1, *s2;
if(!*str2)
return((char *)str1);
while(*cp)
{
s1 = cp;
s2 = (char *) str2;
while(*s1 && *s2 && !(toupper(*s1) - toupper(*s2)))
s1++, s2++;
if(!*s2)
return(cp);
cp++;
}
return(NULL);
}
CMyCriticalSection lock_filter;
bool CSimpleDbgViewDlg::Filter_Pass(char* szString)
{
bool bRet = true;
if(szString)
{
CAutoCriticalSection lock(lock_filter.GetSection());
if(//命中过滤条件
m_strKeyW1.GetLength() && strstr_i(szString, m_strKeyW1) ||
m_strKeyW2.GetLength() && strstr_i(szString, m_strKeyW2) ||
m_strKeyW3.GetLength() && strstr_i(szString, m_strKeyW3) ||
m_strKeyW4.GetLength() && strstr_i(szString, m_strKeyW4)
)
{
if(m_bExclude)//排除的
bRet = true;//不要
else//包含的
bRet = false;//要
}
else//未命中条件
{
if(
m_strKeyW1.GetLength() ||
m_strKeyW2.GetLength() ||
m_strKeyW3.GetLength() ||
m_strKeyW4.GetLength()
)
{
if(m_bExclude)
bRet = false;
else
bRet = true;
}
else//没有设置过滤的
{
bRet = false; //要
}
}
}
return bRet;
}
void CSimpleDbgViewDlg::LoadCfg()
{
CAutoCriticalSection lock(lock_filter.GetSection());
WCHAR szDll[MAX_PATH] = {};
::GetModuleFileName(NULL, szDll, MAX_PATH);
CString strCfg = CString(szDll) + L".ini";
WCHAR szTxt[1000] = {};
GetPrivateProfileStringW(L"Cfg", L"K1", L"", szTxt, _countof(szTxt), strCfg);
m_strKeyW1 = CStringA(szTxt);
GetPrivateProfileStringW(L"Cfg", L"K2", L"", szTxt, _countof(szTxt), strCfg);
m_strKeyW2 = CStringA(szTxt);
GetPrivateProfileStringW(L"Cfg", L"K3", L"", szTxt, _countof(szTxt), strCfg);
m_strKeyW3 = CStringA(szTxt);
GetPrivateProfileStringW(L"Cfg", L"K4", L"", szTxt, _countof(szTxt), strCfg);
m_strKeyW4 = CStringA(szTxt);
GetPrivateProfileStringW(L"Cfg", L"bex", L"", szTxt, _countof(szTxt), strCfg);
m_bExclude = _wtoi(szTxt);
}
void CSimpleDbgViewDlg::OnEnChangeEdit1()
{
UpdateData(TRUE);
if(m_strPID.GetLength())
{
m_dwPID = _wtoi(m_strPID);
}
else
{
m_dwPID = 0xFFFFFFFF;
}
}
void CSimpleDbgViewDlg::OnBnClickedButton5()
{
AfxGetScreenCaptureWin().CaptureScreen(0);
AfxGetScreenCaptureWin().SetMyDlg(this);
AfxGetScreenCaptureWin().ShowSnapWindow();
}
void CSimpleDbgViewDlg::setPIDByHwnd(HWND m_hCurrentHWND)
{
DWORD dwPid = 0;
GetWindowThreadProcessId(m_hCurrentHWND, &dwPid);
m_strPID.Format(L"%u", dwPid);
UpdateData(0);
OnEnChangeEdit1();
}
void CSimpleDbgViewDlg::OnLvnGetdispinfoList1(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
*pResult = 0;
}
void CSimpleDbgViewDlg::OnLvnKeydownList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVKEYDOWN pLVKeyDow = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
if(m_pList && GetKeyState('C') & 0x8000 &&
GetKeyState(VK_CONTROL) & 0x8000)
{
int sl = m_pList->GetSelectionMark();
int rc = m_pList->GetItemCount();
if(sl >= 0 && sl < rc)
{
CString str1 = m_pList->GetItemText(sl, 0);
CString str2 = m_pList->GetItemText(sl, 1);
CString strClipboard;
strClipboard.Format(L"%s %s", str1, str2);
GetClipBoard().SetClipBoard_SimpleText(strClipboard);
}
}
*pResult = 0;
}