www.pudn.com > countingsrc.rar > CountingDlg.cpp
/*************************************************************
* 源码统计器1.0版
* 作者:魏镇江
* Email: xiaogi@sohu.com
* homepage: http://xiaogi.nease.net
* 版权所有(C) 2004.1.
**************************************************************/
// CountingDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Counting.h"
#include "CountingDlg.h"
#include "FolderDialog.h"
#include "HyperLink.h"
#include "PropertyDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "CreditStatic.h"
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
private:
UINT m_nCreditTimer;
UINT m_nIconTimer;
CCreditStatic m_static;
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
CHyperLink m_ctrlMyEmail;
CHyperLink m_ctrlMyHomepage;
CStatic m_ctlCount;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
afx_msg void OnTimer(UINT nIDEvent);
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
m_nIconTimer = NULL;
m_nCreditTimer = NULL;
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
DDX_Control(pDX, IDC_MYEMAIL, m_ctrlMyEmail);
DDX_Control(pDX, IDC_MYHOMEPAGE, m_ctrlMyHomepage);
DDX_Control(pDX, IDC_COUNTICON, m_ctlCount);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
char *pArrCredit = {
"IDB_COUNT^|"
"源码统计器1.1\t|"
"版权所有(c) 2004.1.\r|"
"软件设计者\t|魏镇江\r|"
"E-mail: xiaogi@sohu.com\r||"
"主页: http://xiaogi.nease.net\r||"
"IDB_COUNT^|"
"★ “源码统计器”使用说明 ★\t|"
"最新更新下载:http://xiaogi.nease.net\r||"
"软件说明: \t||"
"在工作中,我们经常碰到客户要求告之所写程\r|"
"序的行数,包括代码行、注释行和空白行等。\r|"
"本软件就是为了这一目的编写的,最先是用于\r|"
"对我自己写的C/C++,VC++程序进行行数统计\r|"
"。它可以准确地计算出源代码中的各种行数。\r|"
"后来经过不断改进,增加了对VB, Java, ASP,\r|"
"JSP和SQL等程序的源代码的统计,使得软件的\r|"
"应用范围更加广泛。网络上也有不少类似统计\r|"
"行数的软件,但到目前为止,我发现我的这个\r|"
"源码统计器统计速度是最快的,而且相比较发\r|"
"现更加准确,考虑到了源码中的许多特殊情况\r|"
"(如引号之间有/*,或/*之后有//,或//之后\r|"
"有/*等)。 \r||"
"使用方法: \t||"
"在“文件名或文件类型”组合框中输入你需要\r|"
"进行统计的文件类型(如:*.cpp;*.c;*.h),\r|"
"扩展名之间用;,:分隔。你也可以直接输入需 \r|"
"要统计的文件名(如:a.cpp;b.c;c.h),同样\r|"
"的,文件名之间也用;,:分隔。点击下拉框可 \r|"
"以选择软件缺省为你提供的几种文件类型,点\r|"
"击右边的按钮可以选择需要进行统计文件(可\r|"
"多选,并且软件自动将选中文件所在目录放入\r|"
"“搜索文件夹”组合框中)。 \r||"
"在“搜索文件夹”组合框中输入你需要进行统\r|"
"计的文件所在的文件夹(如:d:\\study),点\r|"
"击下拉框可以选择近几次选择的文件夹。如果\r|"
"你手动输入的文件夹不在下拉框中,那软件在\r|"
"统计开始后将自动加入。点击右边的按钮可以\r|"
"选择文件夹。 \r||"
"你可以选择统计时是否也需要统计子文件夹中\r|"
"的相关文件。 \r||"
"点击“统计”按钮开始,再次点击该按钮停止\r|"
"统计。 \r||"
"若你需要保存统计结果,请点击“保存”按钮\r|"
"。你可以选择以文本文件或csv文件两种格式 \r|"
"保存。其中csv文件可被几乎所有的统计软件 \r|"
"识别,包括微软Office系列的Excel. \r||"
"软件可稳定地运行于MS Windows系列操作系统\r|"
"上。 \r||"
"作者声明: \t||"
"本软件为自由软件,源代码完全公开。你可以\r|"
"来信索要并不受限制地利用,但务请保留作者\r|"
"的版权信息。若你觉得本软件对你有帮助或你\r|"
"需要将其中部分的代码用到自己的软件中,请\r|"
"给作者来信告知。如果你对本软件有好的建议\r|"
"或bug 发现,也请来信告知。 \r|"
"我的Email:xiaogi@sohu.com \r|"
"个人主页:http://xiaogi.nease.net \r||"
" xiaogi \r|"
" 2002年11月 \r|||"
};
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_ctrlMyEmail.SetURL("mailto:xiaogi@sohu.com");
m_ctrlMyHomepage.SetURL("http://xiaogi.nease.net");
m_static.SubclassDlgItem(IDC_DISPLAY_HELP,this);
m_static.SetCredits(pArrCredit,'|');
m_static.SetColor(BACKGROUND_COLOR, RGB(0,0,255));
m_static.SetTransparent();
m_static.StartScrolling();
m_nCreditTimer = SetTimer(ABOUT_CREDIT_TIMER,5000,NULL);
ASSERT(m_nCreditTimer != 0);
m_nIconTimer = SetTimer(ABOUT_ICON_TIMER, 200, NULL);
ASSERT(m_nIconTimer != 0);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/*****************************************************************
动态显示About对话框中的图标
*****************************************************************/
void CAboutDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(nIDEvent != (UINT)m_nIconTimer)
return;
static int big_icons[] =
{ IDI_BIG_ICON1, IDI_BIG_ICON2, IDI_BIG_ICON3, IDI_BIG_ICON4,
IDI_BIG_ICON5, IDI_BIG_ICON6, IDI_BIG_ICON7};
static long big_index = 0;
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(big_icons[big_index++%7]),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);//SM_CXICON
m_ctlCount.SendMessage(STM_SETICON, (WPARAM)hIcon, 0);
// CDialog::OnTimer(nIDEvent);
}
/////////////////////////////////////////////////////////////////////////////
// CCountingDlg dialog
CCountingDlg::CCountingDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCountingDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCountingDlg)
m_strFiles = _T("");
m_bIncludeSubfolder = TRUE;
m_strComboExt = _T("");
m_strComboFolder = _T("");
m_strSize = _T("");
m_strCommentLines = _T("");
m_strBlankLines = _T("");
m_strCodeLines = _T("");
m_strTotalLines = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_CountingStatus = STOP;
m_nTimer = NULL;
m_nSysTimer = NULL;
m_nStatMethod = 1;
}
CCountingDlg::~CCountingDlg()
{
}
void CCountingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCountingDlg)
// DDX_Control(pDX, IDC_SAVE, m_ctrlSave);
DDX_Control(pDX, IDC_COUNTINGICON, m_ctrlCountingIcon);
DDX_Control(pDX, IDC_SIZES, m_ctrlSize);
DDX_Control(pDX, IDC_RESULT, m_ctlResult);
DDX_Control(pDX, IDC_COMBO_FOLDER, m_ctlFolder);
DDX_Control(pDX, IDC_COMBO_EXTENSION, m_ctlExtension);
DDX_Text(pDX, IDC_FILES, m_strFiles);
DDX_Check(pDX, IDC_INCLUDE_SUBFOLDER, m_bIncludeSubfolder);
DDX_CBString(pDX, IDC_COMBO_EXTENSION, m_strComboExt);
DDX_CBString(pDX, IDC_COMBO_FOLDER, m_strComboFolder);
DDX_Text(pDX, IDC_SIZES, m_strSize);
DDX_Text(pDX, IDC_COMMENT, m_strCommentLines);
DDX_Text(pDX, IDC_BLANK, m_strBlankLines);
DDX_Text(pDX, IDC_CODE, m_strCodeLines);
DDX_Text(pDX, IDC_TOTAL, m_strTotalLines);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_COUNT, m_btnCount);
DDX_Control(pDX, IDC_SAVE, m_btnSave);
DDX_Control(pDX, IDC_PROPERTY, m_btnProperty);
DDX_Control(pDX, IDC_ABOUT, m_btnAbout);
DDX_Control(pDX, IDC_QUIT, m_btnQuit);
}
BEGIN_MESSAGE_MAP(CCountingDlg, CDialog)
//{{AFX_MSG_MAP(CCountingDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SAVE, OnSave)
ON_BN_CLICKED(IDC_COUNT, OnCount)
ON_BN_CLICKED(IDC_BROWSE_FOLDER, OnBrowseFolder)
ON_BN_CLICKED(IDC_BROWSE_EXT, OnBrowseExt)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_QUIT, OnQuit)
ON_BN_CLICKED(IDC_ABOUT, OnAbout)
ON_BN_CLICKED(IDC_PROPERTY, OnProperty)
//}}AFX_MSG_MAP
// ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnNeedText)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCountingDlg message handlers
BOOL CCountingDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
HICON hIcon = AfxGetApp()->LoadIcon(IDI_SMALLICON);
SetIcon(hIcon, FALSE); // Set small icon
m_structExtention.arrayType.Add("cpp"); //0
m_structExtention.arrayType.Add("c"); //1
m_structExtention.arrayType.Add("h"); //2
m_structExtention.arrayType.Add("txt"); //3
m_structExtention.arrayType.Add("wri"); //4
m_structExtention.arrayType.Add("tli"); //5
m_structExtention.arrayType.Add("tlh"); //6
m_structExtention.arrayType.Add("rc"); //7
m_structExtention.arrayType.Add("dsw"); //8
m_structExtention.arrayType.Add("hpj"); //9
m_structExtention.arrayType.Add("htm"); //10
m_structExtention.arrayType.Add("html");//11
m_structExtention.arrayType.Add("cxx"); //12
m_structExtention.arrayType.Add("hpp"); //13
m_structExtention.arrayType.Add("def"); //14
m_structExtention.arrayType.Add("java");//15
m_structExtention.arrayType.Add("frm"); //16
m_structExtention.arrayType.Add("bas"); //17
m_structExtention.arrayType.Add("ctl"); //18
m_structExtention.arrayType.Add("cls"); //19
m_structExtention.arrayType.Add("asp"); //20
m_structExtention.arrayType.Add("jsp"); //21
m_structExtention.arrayType.Add("sql"); //22
m_structExtention.arrayType.Add("pl"); //23
m_structExtention.arrayType.Add("sh"); //24
m_structExtention.arrayType.Add("*"); //25
m_structExtention.nType[0] = TYPE_CPP;
m_structExtention.nType[1] = TYPE_C;
m_structExtention.nType[2] = TYPE_H;
m_structExtention.nType[3] = TYPE_TXT;
m_structExtention.nType[4] = TYPE_WRI;
m_structExtention.nType[5] = TYPE_H;
m_structExtention.nType[6] = TYPE_H;
m_structExtention.nType[7] = TYPE_RC;
m_structExtention.nType[8] = TYPE_DSW;
m_structExtention.nType[9] = TYPE_HPJ;
m_structExtention.nType[10] = TYPE_HTM;
m_structExtention.nType[11] = TYPE_HTM;
m_structExtention.nType[12] = TYPE_CPP;
m_structExtention.nType[13] = TYPE_H;
m_structExtention.nType[14] = TYPE_OTH;
m_structExtention.nType[15] = TYPE_JAVA;
m_structExtention.nType[16] = TYPE_VB;
m_structExtention.nType[17] = TYPE_VB;
m_structExtention.nType[18] = TYPE_VB;
m_structExtention.nType[19] = TYPE_VB;
m_structExtention.nType[20] = TYPE_ASP;
m_structExtention.nType[21] = TYPE_JSP;
m_structExtention.nType[22] = TYPE_SQL;
m_structExtention.nType[23] = TYPE_PERL;
m_structExtention.nType[24] = TYPE_SHELL;
m_structExtention.nType[25] = TYPE_OTH;
//设置按钮图标等
m_btnCount.SetIcon(IDI_COUNT);
m_btnCount.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
m_btnCount.SetRounded(TRUE);
m_btnCount.SetSound(MAKEINTRESOURCE(IDR_WAVEHOVER), ::GetModuleHandle(NULL));
m_btnCount.SetBtnCursor(IDC_HAND);
m_btnSave.SetIcon(IDI_SAVE);
m_btnSave.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
m_btnSave.SetRounded(TRUE);
m_btnSave.SetSound(MAKEINTRESOURCE(IDR_WAVEHOVER), ::GetModuleHandle(NULL));
m_btnSave.SetBtnCursor(IDC_HAND);
m_btnProperty.SetIcon(IDI_PROP);
m_btnProperty.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
m_btnProperty.SetRounded(TRUE);
m_btnProperty.SetSound(MAKEINTRESOURCE(IDR_WAVEHOVER), ::GetModuleHandle(NULL));
m_btnProperty.SetBtnCursor(IDC_HAND);
m_btnAbout.SetIcon(IDI_ABOUT);
m_btnAbout.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
m_btnAbout.SetRounded(TRUE);
m_btnAbout.SetSound(MAKEINTRESOURCE(IDR_WAVEHOVER), ::GetModuleHandle(NULL));
m_btnAbout.SetBtnCursor(IDC_HAND);
m_btnQuit.SetIcon(IDI_QUIT);
m_btnQuit.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);
m_btnQuit.SetRounded(TRUE);
m_btnQuit.SetSound(MAKEINTRESOURCE(IDR_WAVEHOVER), ::GetModuleHandle(NULL));
m_btnQuit.SetBtnCursor(IDC_HAND);
//文件夹选择框设置MRU
m_ctlFolder.SetMRURegKey ( _T("Combobox MRU folder") );
m_ctlFolder.SetMRUValueFormat ( _T("String #%d") );
m_ctlFolder.SetAutoRefreshAfterAdd ( TRUE );
m_ctlFolder.SetAutoSaveAfterAdd ( TRUE );
m_ctlFolder.LoadMRU();
m_ctlFolder.RefreshCtrl();
//设置ListCtrl属性
DWORD oldStyle = m_ctlResult.GetExtendedStyle();
m_ctlResult.SetExtendedStyle(oldStyle |LVS_EX_FULLROWSELECT|LVS_EX_TRACKSELECT|LVS_EX_UNDERLINEHOT|LVS_EX_GRIDLINES);
CString str;
str.LoadString(IDS_FILENAME);
m_ctlResult.InsertColumn(0, str, LVCFMT_LEFT, 120, -1);
str.LoadString(IDS_PATHNAME);
m_ctlResult.InsertColumn(1, str, LVCFMT_LEFT, 120, -1);
str.LoadString(IDS_TOTALLINE);
m_ctlResult.InsertColumn(2, str, LVCFMT_RIGHT, 70, -1);
str.LoadString(IDS_CODELINE);
m_ctlResult.InsertColumn(3, str, LVCFMT_RIGHT, 70, -1);
str.LoadString(IDS_COMMENTLINE);
m_ctlResult.InsertColumn(4, str, LVCFMT_RIGHT, 70, -1);
str.LoadString(IDS_BLANKLINE);
m_ctlResult.InsertColumn(5, str, LVCFMT_RIGHT, 70, -1);
str.LoadString(IDS_FILETYPE);
m_ctlResult.InsertColumn(6, str, LVCFMT_LEFT, 120, -1);
//获取log文件路径
char pathname[_MAX_PATH];
char drive[_MAX_DRIVE]; //由于读取动态鼠标时还要用,所以改成成员变量
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
GetModuleFileName(NULL, pathname, _MAX_PATH);//可执行文件所在目录
_splitpath(pathname, drive, dir, fname, ext);
_makepath(pathname, drive, dir, "log", "txt");
m_strLogFile = pathname;
m_nSysTimer = SetTimer(SYS_TIMER, 200, NULL);//左上角图标动画
return TRUE; // return TRUE unless you set the focus to a control
}
void CCountingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CCountingDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CCountingDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
/***********************************************************
* 当按下ESC键时,确认是否退出
***********************************************************/
void CCountingDlg::OnCancel()
{
// TODO: Add extra cleanup here
CString str1, str2;
str1.LoadString(IDS_TOQUIT);
str2.LoadString(IDS_MESSAGE);
if(MessageBox(str1, str2, MB_YESNO)==IDNO)
{
return ;
}
CDialog::OnCancel();
}
/***********************************************************
* 将统计保存为文本文件和csv文件
***********************************************************/
void CCountingDlg::OnSave()
{
// TODO: Add your control notification handler code here
if(0==m_ctlResult.GetItemCount())
{
CString str1, str2;
str1.LoadString(IDS_UNSTARTED);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
return;
}
if(m_CountingStatus == COUNTING)
{
CString str1, str2;
str1.LoadString(IDS_WAITING);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
return;
}
CFileDialog dlgFile(
FALSE, _T("*.txt"), NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
NULL, this);
dlgFile.m_ofn.lStructSize = sizeof(OPENFILENAME);
dlgFile.m_ofn.lpstrFilter = "文本文件(*.txt)\0*.txt\0Excel 文件(*.xls)\0*.xls\0CSV 文件(*.csv)\0*.csv\0\0";
dlgFile.m_ofn.lpstrTitle = "选择保存统计结果的文件";
if (dlgFile.DoModal() == IDCANCEL)
return ;
CString sPath = dlgFile.GetPathName();
CString sExt = dlgFile.GetFileExt();
sExt.MakeLower();
if(sExt == "txt")
SaveAsTextFile((LPCTSTR)sPath);
else if(sExt == "csv")
SaveAsCSVFile((LPCTSTR)sPath);
else if(sExt == "xls")
SaveAsExcelFile((LPCTSTR)sPath);
else
{
CString str1, str2;
str1.LoadString(IDS_WRONGTYPE);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
}
CString str1, str2;
str1.LoadString(IDS_SAVEOVER);
str2.Format("%s:%s", str1, sPath);
GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str2);
}
/*******************************************************
点击“统计”按钮,开始统计
********************************************************/
void CCountingDlg::OnCount()
{
// TODO: Add your control notification handler code here
if(m_CountingStatus == COUNTING)
{
m_CountingStatus = STOP;
return;
}
UpdateData(TRUE);
if(m_strComboExt.Find(_T("**")) != -1||m_strComboFolder.Find(_T("**")) != -1)
{
CString str1, str2;
str1.LoadString(IDS_INVALIDFILE);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
return;
}
if(m_strComboExt.IsEmpty())
{
CString str1, str2;
str1.LoadString(IDS_INPUT_FILE);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
return;
}
if(m_strComboFolder.IsEmpty())
{
CString str1, str2;
str1.LoadString(IDS_COUNTING_PATH);
str2.LoadString(IDS_MESSAGE);
MessageBox(str1, str2);
return;
}
if(m_ctlFolder.FindStringExact(-1, m_strComboFolder)==CB_ERR)
{
m_ctlFolder.AddToMRU((LPCTSTR)m_strComboFolder);
}
m_btnCount.SetIcon(IDI_COUNTSTOP);
CString str;
str.LoadString(IDS_STOP);
m_btnCount.SetWindowText(str);
m_imageList.DeleteImageList();
m_imageList.Create(16, 16, ILC_MASK|ILC_COLORDDB, 1, 100);
m_ctlResult.SetImageList(&m_imageList, LVSIL_SMALL);
m_ctlResult.DeleteAllItems();
m_nItemCountSet = 1000;
m_ctlResult.SetItemCount(m_nItemCountSet);
char strCurrentDirectory[_MAX_PATH];
GetCurrentDirectory(_MAX_PATH, strCurrentDirectory);
m_strCurrentDir = strCurrentDirectory; //保存当前路径以便线程结束后恢复
SetCurrentDirectory(m_strComboFolder);//set directory to count
m_nTotalLines = 0;//initialize
m_nCodeLines = 0;
m_nCommentLines = 0;
m_nBlankLines = 0;
m_nFiles = 0;
m_nSize = 0;
m_nTimer = SetTimer(COUNTING_TIMER, 200, NULL);
m_CountingStatus = COUNTING;
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BIG_ICON2),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);//SM_CXICON
m_ctrlCountingIcon.SendMessage(STM_SETICON, (WPARAM)hIcon, 0);
char buf[_MAX_PATH];
GetCurrentDirectory(_MAX_PATH, buf);
//开始线程
CWinThread* pThread = AfxBeginThread(CountThread, this);
}
/*******************************************************************
* Extract one extension from strExtension, and assign it to strOneOfExt
* for example: strExtension = "*.cpp;*.c;*.h"
* then, 1st time: strOneOfExt = "*.cpp",
* 2nd time: strOneOfExt = "*.c",
* 3rd time: strOneOfExt = "*.h",
* return: TRUE: extracted successfully
* FALSE: strExtension is empty.
*********************************************************************/
BOOL CCountingDlg::ExtractExtension(CString & strOneOfExt, CString & strExtension)
{
strExtension.TrimLeft();
if(strExtension.IsEmpty())
return FALSE;
int nLength = strExtension.GetLength();
int nFirst = strExtension.FindOneOf(";,:");
if(nFirst == -1) //there may be only one extension in strExtsion
nFirst = nLength;
strOneOfExt = strExtension.Left(nFirst);
if(nFirst == nLength)
strExtension.Empty();
else
strExtension = strExtension.Right(nLength-1-nFirst);//rest
strOneOfExt.TrimLeft();//trim whitespace
strOneOfExt.TrimRight();
return TRUE;
}
/*******************************************************************
* find file type according to its extension
* for example: strExtension = "xiaogi.c"
* return: TYPE_C
*********************************************************************/
int CCountingDlg::FindFileType(CString strFile)
{
int nLast = strFile.ReverseFind('.');
CString extNoDot = strFile.Right(strFile.GetLength()-nLast-1);
for(int i=0; im_strComboFolder[pThis->m_strComboFolder.GetLength()-1]=='\\')
strPath = pThis->m_strComboFolder + "*.*";
else
strPath = pThis->m_strComboFolder + "\\*.*";
do{
bWorking = finder.FindFile(strPath);
while(bWorking && pThis->m_CountingStatus==COUNTING)
{
bWorking = finder.FindNextFile();
CString strFilePath = finder.GetFilePath();
if(finder.IsDots())
continue;
if(finder.IsDirectory())
{
if(pThis->m_bIncludeSubfolder)
listPaths.AddHead(strFilePath);
continue;
}
else
{
if(pThis->IsSearchingFor(strFilePath))
{
CString str1, str2;
str1.LoadString(IDS_COUNTINGFILE);
str2.Format("%s:%s", str1, strFilePath);
pThis->GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str2);
int nType;
nType = pThis->FindFileType(strFilePath);
if(nType == -1)
nType = TYPE_OTH;
int nLines=0;
int nCodeLines=0;
int nCommentLines=0;
int nBlankLines=0;
int nLength=0;
switch(nType)
{
case TYPE_C:
case TYPE_CPP:
case TYPE_H:
case TYPE_JAVA:
nLines = pThis->GetCppFileLines((LPCTSTR)strFilePath, &nLength, &nCodeLines, &nCommentLines, &nBlankLines);
break;
case TYPE_VB:
case TYPE_ASP:
nLines = pThis->GetVBFileLines((LPCTSTR)strFilePath, &nLength, &nCodeLines, &nCommentLines, &nBlankLines);
break;
case TYPE_SQL:
// nLines = pThis->GetSqlFileLines((LPCTSTR)strFilePath, &nLength, &nCodeLines, &nCommentLines, &nBlankLines);
break;
case TYPE_JSP:
//AfxMessageBox("jsp文件目前还不提供统计");
break;
case TYPE_PERL:
case TYPE_SHELL:
nLines = pThis->GetPerlFileLines((LPCTSTR)strFilePath, &nLength, &nCodeLines, &nCommentLines, &nBlankLines);
break;
default:
nLines = pThis->GetTxtFileLines((LPCTSTR)strFilePath, &nLength, &nCodeLines, &nCommentLines, &nBlankLines);
break;
}
//下行在1.0以后的版本中删掉,nCodeLines由函数计算
// nCodeLines = nLines - nCommentLines - nBlankLines;
int pos=strFilePath.ReverseFind('\\');
if(pThis->m_nFiles > pThis->m_nItemCountSet)
pThis->m_nItemCountSet += 1000;
pThis->m_ctlResult.SetItemCount(pThis->m_nItemCountSet);
SHFILEINFO sfi;
if (::SHGetFileInfo (strFilePath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES | SHGFI_DISPLAYNAME | SHGFI_TYPENAME |SHGFI_ICON|SHGFI_SMALLICON ))
{
CString str;
pThis->m_imageList.Add(sfi.hIcon);
pThis->m_ctlResult.InsertItem(pThis->m_nFiles,sfi.szDisplayName,pThis->m_nFiles);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 1, strFilePath.Mid(0,pos));
str.Format("%d", nLines);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 2, str);
str.Format("%d", nCodeLines);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 3, str);
str.Format("%d", nCommentLines);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 4, str);
str.Format("%d", nBlankLines);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 5, str);
pThis->m_ctlResult.SetItemText(pThis->m_nFiles, 6, sfi.szTypeName);
}
pThis->m_ctlResult.Update(pThis->m_nFiles);
pThis->m_nFiles++;
pThis->m_nSize += nLength;
pThis->m_nTotalLines += nLines;
pThis->m_nCodeLines += nCodeLines;
pThis->m_nCommentLines += nCommentLines;
pThis->m_nBlankLines += nBlankLines;
pThis->UpdateResult();
}
}
}
if(listPaths.IsEmpty())
break;
strFolder = listPaths.RemoveHead();
strPath = strFolder + "\\*.*";
finder.Close();
}while(pThis->m_CountingStatus==COUNTING);
if(pThis->m_nTimer!=NULL)
{
pThis->KillTimer(pThis->m_nTimer);
pThis->m_nTimer = NULL;
}
CString str1;
if(pThis->m_CountingStatus==STOP)
str1.LoadString(IDS_ABORT); //用户强行终止
else
str1.LoadString(IDS_COUNTINGSTOP);
pThis->GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str1);
pThis->m_CountingStatus = STOP;
pThis->m_btnCount.SetIcon(IDI_COUNT);
CString str;
str.LoadString(IDS_COUNT);
pThis->m_btnCount.SetWindowText(str);
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BIG_ICON1),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);//SM_CXICON
pThis->m_ctrlCountingIcon.SendMessage(STM_SETICON, (WPARAM)hIcon, 0);
return 0;
}
////////////////////////////////////////////////////////////
//modify a path with file name to without file name
// such as:
// modify: d:\\temp\\countingdlg.cpp
// to: d:\\temp
//
////////////////////////////////////////////////////////////
CString CCountingDlg::GetPurePath(CString strPath)
{
int nLast = strPath.ReverseFind('\\');
return strPath.Left(nLast);
}
/******************************************************************
* 往一字符串strText中追加空格,使其长度达到num
* bAtEnd : TRUE表示在字符串后面追加空格
* FALSE表示在字符串前面追加空格
* 若strText的长度本来就大于num,则将最后三个字符改为...
*******************************************************************/
CString CCountingDlg::TextAppendSpace(CString strText, int num, BOOL bAtEnd)
{
CString str;
if(strText.GetLength()>=num)
{
str = strText.Left(num-3);
str += "...";
}
else
{
str = strText;
for(int i=strText.GetLength(); i=nLength2)
return TRUE;
while(i=nLength1)
return FALSE;
continue;
}
if(inputFile[j]=='?')
{
continue;
}
if(inputFile[j]==strFile[i])
{
continue;
}
else
return FALSE;
}
if(i==nLength1&&j==nLength2)
return TRUE;
else
return FALSE;
}
/*****************************************************************
统计开始后动态显示图标,表示统计进行中
*****************************************************************/
void CCountingDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(nIDEvent == (UINT)m_nSysTimer)
{//左上角动态图标
static int icons[] =
{ IDI_ICON1, IDI_ICON2, IDI_ICON3, IDI_ICON4, IDI_ICON5, IDI_ICON6,
IDI_ICON7, IDI_ICON8, IDI_ICON9, IDI_ICON10, IDI_ICON10};
static long index = 0;
index = ++index%10;
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(icons[index]),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);//SM_CXICON
HICON hPrevIcon = (HICON)AfxGetMainWnd()->SendMessage(WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
return;
}
if(nIDEvent != (UINT)m_nTimer)
return;
static int icons[] =
{ IDI_BIG_ICON1, IDI_BIG_ICON2, IDI_BIG_ICON3, IDI_BIG_ICON4, IDI_BIG_ICON5, IDI_BIG_ICON6,
IDI_BIG_ICON7};
static long index = 0;
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(icons[index++%7]),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);//SM_CXICON
m_ctrlCountingIcon.SendMessage(STM_SETICON, (WPARAM)hIcon, 0);
}
/*****************************************************************
确定是否退出
*****************************************************************/
void CCountingDlg::OnQuit()
{
// TODO: Add your control notification handler code here
CString str1, str2;
str1.LoadString(IDS_TOQUIT);
str2.LoadString(IDS_MESSAGE);
if(MessageBox(str1, str2, MB_YESNO)==IDNO)
{
return ;
}
CDialog::OnCancel();
}
/*********************************************************
统计c++文件
*********************************************************/
int CCountingDlg::GetCppFileLines(LPCTSTR strFileName, int* pnLength, int *pnCodeLines, int* pnCommentLines, int* pnBlankLines)
{
//there are two methods to count lines in files, by CStdioFile or CFile
*pnLength = 0;
*pnCodeLines = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCodeLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
BOOL bCommentSet = FALSE; //注释行统计标识 有"/*"时TRUE, "*/"时FALSE
BOOL bQuatoSet = FALSE; //字符串统计标识 首次一行有奇数个"时TRUE, 下一行有奇数个"时FALSE
int nLength = file.GetLength();
*pnLength = nLength;
CString bufRead;
int nLineCommentBegin = 0;
while(file.ReadString(bufRead)!=FALSE)
{
BOOL bStatedComment = FALSE;//本行作为注释行是否已统计过
BOOL bStatedCode = FALSE; //本行作为代码行是否已统计过
nLines++;
bufRead.TrimLeft(); //先将文件头的空格或制表符去掉
if(bufRead.GetLength()==0) //为空白行
{
nBlankLines++;
continue;
}
if(bCommentSet && bufRead.Find("*/")==-1)
{
nCommentLines++;
continue;
}
if(bufRead.Find("//")==-1 && bufRead.Find("/*")==-1 && bufRead.Find("*/")==-1)
{//如果本行根本就无注释符,则要不是注释符,要不是代码行
if(bCommentSet)
{
nCommentLines++; continue;
}
else
{
if(bufRead.Find('"')==-1)
{
nCodeLines++; continue;
}
}
}
if(bufRead.Find("//")==0 && !bCommentSet && !bQuatoSet)
{
nCommentLines++;
continue;
}
BOOL bDoubleSplashFound = FALSE;
BOOL bSplashStarFound = FALSE;
for(int i=0; i=2 && (nEndComment == (bufRead.GetLength()-2)) && bCommentSet)
//至少有两个字符 */在该行的最后 前面有/*
{
bCommentSet = FALSE;
nCommentLines ++;
}
else if(nEndComment != -1 && bCommentSet)// */不在该行最后,则需要继续判断
{
bCommentSet = FALSE;
if(nLineCommentBegin == nLines) // /* */ on the same line
nCommentLines++;
CString strRight = bufRead.Right(bufRead.GetLength()-nEndComment-2);
if(strRight.Find("//")!=-1) //it is very strange! such as "code */ (code or blank) // code"
{
strRight.TrimLeft();
if(strRight.Find("//")==0)
nCommentLines++;
}
else if(nLineCommentBegin != nLines && strRight.GetLength()==0)
nCommentLines++;
}
if(bCommentSet)
nCommentLines++;
if(IsOdd(HowManyCharsInString(bufRead, "\"", bCommentSet))&&!bCommentSet)
{
// if(bQuatoSet)
// {//本行继续前一行的字符串
// BOOL bCommentBegin = FALSE;
// for(int i=0; i=2 && (nEndComment == (bufRead.GetLength()-2)) && bCommentSet)
//至少有两个字符 */在该行的最后 前面有/*
{
bCommentSet = FALSE;
nCommentLines ++;
}
else if(nEndComment != -1 && bCommentSet)// */不在该行最后,则需要继续判断
{
bCommentSet = FALSE;
if(nLineCommentBegin == nLines) // /* */ on the same line
nCommentLines++;
bufRead = bufRead.Right(bufRead.GetLength()-nEndComment-2);
if(bufRead.Find("//")!=-1) //it is very strange! such as "code */ (code or blank) // code"
{
bufRead.TrimLeft();
if(bufRead.Find("//")==0)
nCommentLines++;
}
else if(nLineCommentBegin != nLines && bufRead.GetLength()==0)
nCommentLines++;
}
if(bCommentSet)
nCommentLines++;
}
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
//下述代码不是使用CStdioFile,有错误
/* CFile file;
file.Open(strFileName, CFile::modeRead);
int nLines = 0;
int nCodeLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
BOOL bLastSplash = FALSE;
BOOL bDoubleSplash = FALSE;
BOOL bLastStar = FALSE;
BOOL bCommentCount = FALSE;
BOOL bBlankCount = TRUE;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
char buf[255];
int nRead = 0;
while(nLength>0)
{
nRead = file.Read(buf, 250);
if(buf[0] == '*' && bLastSplash)
{
bLastSplash = FALSE;
bCommentCount = TRUE;
}
if(buf[0] == '/' && bLastSplash && !bCommentCount && bBlankCount && !bDoubleSplash)
{
bLastSplash = FALSE;
bDoubleSplash = TRUE;
}
if(buf[0] == '/' && bLastStar)
{
bLastStar = FALSE;
bCommentCount = FALSE;
nCommentLines++;
}
for(int i=0; i=2 && (nEndComment == bufRead.GetLength()-2))
{
bCommentSet = FALSE;
nCommentLines ++;
}
else if(nEndComment != -1)
{
bCommentSet = FALSE;
if(bufRead.Find("--")!=-1) //it is very strange! such as " */ -- "
{
CString sTemp = bufRead.Right(bufRead.GetLength()-nEndComment-3);
sTemp.TrimLeft();
if(sTemp.Find("--")==0)
nCommentLines++;
}
}
if(bCommentSet)
nCommentLines++;
}
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
}
int CCountingDlg::GetVBFileLines(LPCTSTR strFileName, int *pnLength, int *pnCodeLines, int *pnCommentLines, int *pnBlankLines)
{
*pnLength = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCodeLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
CString bufRead;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft();
if(bufRead.GetLength()==0)
{
nBlankLines++;
continue;
}
if(bufRead.Find("'")==0)
{
nCommentLines++;
continue;
}
if(bufRead.Find("'")!=-1)
{
if(m_nStatMethod==0)
nCodeLines++;
else if(m_nStatMethod==1)
{
nCodeLines++;
nCommentLines++;
}
else if(m_nStatMethod==2)
{
nCommentLines++;
}
continue;
}
else
nCodeLines++;
}
*pnCodeLines = nCodeLines;
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
}
int CCountingDlg::GetPerlFileLines(LPCTSTR strFileName, int *pnLength, int *pnCodeLines, int *pnCommentLines, int *pnBlankLines)
{
*pnLength = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCodeLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
CString bufRead;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft();
if(bufRead.GetLength()==0)
{
nBlankLines++;
continue;
}
if(bufRead.Find("#")==0)
{
nCommentLines++;
continue;
}
if(bufRead.Find("#")!=-1)
{
if(m_nStatMethod==0)
nCodeLines++;
else if(m_nStatMethod==1)
{
nCodeLines++;
nCommentLines++;
}
else if(m_nStatMethod==2)
{
nCommentLines++;
}
continue;
}
else
nCodeLines++;
}
*pnCodeLines = nCodeLines;
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
}
int CCountingDlg::GetTxtFileLines(LPCTSTR strFileName, int *pnLength, int *pnCodeLines, int *pnCommentLines, int *pnBlankLines)
{
*pnLength = 0;
*pnCommentLines = 0;
*pnBlankLines = 0;
CStdioFile file;
if(file.Open(strFileName, CFile::modeRead)==FALSE)
return 0;
int nLines = 0;
int nCommentLines = 0;
int nBlankLines = 0;
int nLength = file.GetLength();
m_nSize += nLength;
*pnLength = nLength;
CString bufRead;
while(file.ReadString(bufRead)!=FALSE)
{
nLines++;
bufRead.TrimLeft();
if(bufRead.GetLength()==0)
{
nBlankLines++;
continue;
}
}
*pnCommentLines = nCommentLines;
*pnBlankLines = nBlankLines;
file.Close();
return nLines;
}
/*********************************************************************
* Save as Text file, in which every column has its own width
* input: filename: the save file name
* output: void
**********************************************************************/
void CCountingDlg::SaveAsTextFile(LPCTSTR filename)
{
CFile file(filename, CFile::modeCreate|CFile::modeWrite);
CString strText;
#define COLUMN1_WIDTH 20
#define COLUMN2_WIDTH 30
#define COLUMN3_WIDTH 15
#define COLUMN4_WIDTH 15
#define COLUMN5_WIDTH 15
#define COLUMN6_WIDTH 15
#define COLUMN7_WIDTH 30
strText.LoadString(IDS_FILENAME);
strText = TextAppendSpace(strText, COLUMN1_WIDTH, TRUE);
file.Write(strText, strText.GetLength());//write file name
strText.LoadString(IDS_PATHNAME);
strText = TextAppendSpace(strText, COLUMN2_WIDTH, TRUE);
file.Write(strText, strText.GetLength());//write path name
strText.LoadString(IDS_TOTALLINE);
strText = TextAppendSpace(strText, COLUMN3_WIDTH, FALSE);
file.Write(strText, strText.GetLength());
strText.LoadString(IDS_CODELINE);
strText = TextAppendSpace(strText, COLUMN4_WIDTH, FALSE);
file.Write(strText, strText.GetLength());
strText.LoadString(IDS_COMMENTLINE);
strText = TextAppendSpace(strText, COLUMN5_WIDTH, FALSE);
file.Write(strText, strText.GetLength());
strText.LoadString(IDS_BLANKLINE);
strText = TextAppendSpace(strText, COLUMN6_WIDTH, FALSE);
file.Write(strText, strText.GetLength());
file.Write(" ", 2);
strText.LoadString(IDS_FILETYPE);
strText = TextAppendSpace(strText, COLUMN7_WIDTH, TRUE);
file.Write(strText, strText.GetLength());
file.Write("\r\n", 2);
for(int i=0; i1024)
{
fSize /= 1024.;
strUnit = "KB";
if(fSize>1024)
{
fSize /= 1024.;
strUnit = "MB";
}
}
str1.LoadString(IDS_TOTALSIZE);
str2.Format("%s: %2.2f%s", str1, fSize, strUnit);
file.Write(str2, str2.GetLength());
file.Write("\r\n", 2);
str1.LoadString(IDS_TOTALLINE);
str2.Format("%s: %d (100%%)", str1, m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\r\n", 2);
str1.LoadString(IDS_CODELINE);
str2.Format("%s: %d (%.1f%%)", str1, m_nCodeLines, 100.*m_nCodeLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\r\n", 2);
str1.LoadString(IDS_COMMENTLINE);
str2.Format("%s: %d (%.1f%%)", str1, m_nCommentLines, 100.*m_nCommentLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\r\n", 2);
str1.LoadString(IDS_BLANKLINE);
str2.Format("%s: %d (%2.1f%%)", str1, m_nBlankLines, 100.*m_nBlankLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\r\n", 2);
str1.LoadString(IDS_SAVEOVER);
GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str1);
}
/*********************************************************************
* Save as csv file which can be analysed by Excel conveniently
* input: filename: the save file name
* output: void
**********************************************************************/
void CCountingDlg::SaveAsCSVFile(LPCTSTR filename)
{
CStdioFile file(filename, CFile::modeCreate|CFile::modeWrite);
CString strText;
CString str1, str2, str3, str4, str5, str6, str7;
str1.LoadString(IDS_FILENAME);
str2.LoadString(IDS_PATHNAME);
str3.LoadString(IDS_TOTALLINE);
str4.LoadString(IDS_CODELINE);
str5.LoadString(IDS_COMMENTLINE);
str6.LoadString(IDS_BLANKLINE);
str7.LoadString(IDS_FILETYPE);
strText.Format("%s,%s,%s,%s,%s,%s,%s\n", str1, str2, str3, str4, str5, str6, str7);
file.WriteString(strText);
for(int i=0; i1024)
{
fSize /= 1024.;
strUnit = "KB";
if(fSize>1024)
{
fSize /= 1024.;
strUnit = "MB";
}
}
str1.LoadString(IDS_TOTALSIZE);
str2.Format("%s,%2.2f%s", str1, fSize, strUnit);
file.Write(str2, str2.GetLength());
file.Write("\n", 1);
str1.LoadString(IDS_TOTALLINE);
str2.Format("%s,%d (100%%)", str1, m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\n", 1);
str1.LoadString(IDS_CODELINE);
str2.Format("%s,%d (%2.1f%%)", str1, m_nCodeLines, 100.*m_nCodeLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\n", 1);
str1.LoadString(IDS_COMMENTLINE);
str2.Format("%s,%d (%2.1f%%)", str1, m_nCommentLines, 100.*m_nCommentLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\n", 1);
str1.LoadString(IDS_BLANKLINE);
str2.Format("%s,%d (%2.1f%%)", str1, m_nBlankLines, 100.*m_nBlankLines/m_nTotalLines);
file.Write(str2, str2.GetLength());
file.Write("\n", 1);
str1.LoadString(IDS_SAVEOVER);
GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str1);
}
/*********************************************************************
* Save as Excel file 参考徐景周代码
/////////////////////////////////////////////////////////////////////////////
//名称:OnWriteexcel
//功能:创建并写入数据到Excel文件中
//作者:徐景周(jingzhou_xu@163.net)
//组织:未来工作室(Future Studio)
//日期:2002.9.1
/////////////////////////////////////////////////////////////////////////////
* input: filename: the save file name
* output: void
**********************************************************************/
void CCountingDlg::SaveAsExcelFile(LPCTSTR filename)
{
CDatabase database;
CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安装驱动
CString sSql;
//获取主程序所在路径,存在sPath中
// GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH);
// sPath.ReleaseBuffer ();
TRY
{
// 创建进行存取的字符串
sSql.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",
sDriver, filename, filename);
// 创建数据库 (既Excel表格文件)
if( database.OpenEx(sSql, CDatabase::noOdbcDialog) )
{
// 创建表结构(姓名、年龄)
sSql = "CREATE TABLE 统计结果 (文件名 TEXT, 所在文件夹 TEXT, 总行数 NUMBER, 代码行 NUMBER, 注释行 NUMBER, 空白行 NUMBER, 类型 TEXT)";
database.ExecuteSQL(sSql);
for(int i=0; i1024)
{
fSize /= 1024.;
strUnit = "KB";
if(fSize>1024)
{
fSize /= 1024.;
strUnit = "MB";
}
}
sSql.Format("INSERT INTO 统计结果 (文件名, 所在文件夹) VALUES ('总大小', '%.2f%s')", fSize, strUnit);
database.ExecuteSQL(sSql);
sSql.Format("INSERT INTO 统计结果 (文件名, 所在文件夹) VALUES ('总行数', '%d(100%%)')", m_nTotalLines);
database.ExecuteSQL(sSql);
sSql.Format("INSERT INTO 统计结果 (文件名, 所在文件夹) VALUES ('代码行', '%d(%2.1f%%)')", m_nCodeLines, 100.*m_nCodeLines/m_nTotalLines);
database.ExecuteSQL(sSql);
sSql.Format("INSERT INTO 统计结果 (文件名, 所在文件夹) VALUES ('注释行', '%d(%2.1f%%)')", m_nCommentLines, 100.*m_nCommentLines/m_nTotalLines);
database.ExecuteSQL(sSql);
sSql.Format("INSERT INTO 统计结果 (文件名, 所在文件夹) VALUES ('空白行', '%d(%2.1f%%)')", m_nBlankLines, 100.*m_nBlankLines/m_nTotalLines);
database.ExecuteSQL(sSql);
}
// 关闭数据库
database.Close();
AfxMessageBox("Excel文件保存成功!");
}
CATCH_ALL(e)
{
TRACE1("Excel驱动没有安装: %s",sDriver);
}
END_CATCH_ALL;
CString str;
str.LoadString(IDS_SAVEOVER);
GetDlgItem(IDC_PATH_COUNTING)->SetWindowText(str);
}
/*********************************************************************
* Show the About dialogbox
**********************************************************************/
void CCountingDlg::OnAbout()
{
// TODO: Add your control notification handler code here
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
/*********************************************************************
* Update counting result frequently
* the result including: total files, total size,
* total lines, code lines, comment lines, blank lines
**********************************************************************/
void CCountingDlg::UpdateResult()
{
char sTemp[64]=" ";
//show the number of files
sprintf(sTemp, "%d", m_nFiles);
GetDlgItem(IDC_FILES)->SetWindowText(sTemp);
//show the total size
CString strUnit = "";
float fSize = (float)m_nSize;
if(fSize>1024)
{
fSize /= 1024;
strUnit = "KB";
if(fSize>1024)
{
fSize /= 1024;
strUnit = "MB";
}
}
sprintf(sTemp, "%.2f%s", fSize, strUnit);
GetDlgItem(IDC_SIZES)->SetWindowText(sTemp);
//show total lines
sprintf(sTemp, "%d", m_nTotalLines);
GetDlgItem(IDC_TOTALLINES)->SetWindowText(sTemp);
//show code lines
if(m_nTotalLines!=0)
sprintf(sTemp, "%d(%2.1f%%)", m_nCodeLines, m_nCodeLines*100./m_nTotalLines);
else
sprintf(sTemp, "0(0%%)");
GetDlgItem(IDC_CODELINES)->SetWindowText(sTemp);
//show comment lines
if(m_nTotalLines!=0)
sprintf(sTemp, "%d(%2.1f%%)", m_nCommentLines, m_nCommentLines*100./m_nTotalLines);
else
sprintf(sTemp, "0(0%%)");
GetDlgItem(IDC_COMMENTLINES)->SetWindowText(sTemp);
//show blank lines
if(m_nTotalLines!=0)
sprintf(sTemp, "%d(%2.1f%%)", m_nBlankLines, m_nBlankLines*100./m_nTotalLines);
else
sprintf(sTemp, "0(0%%)");
GetDlgItem(IDC_BLANKLINES)->SetWindowText(sTemp);
}
void CCountingDlg::OnProperty()
{
// TODO: Add your control notification handler code here
CPropertyDlg dlg;
dlg.m_nStatMethod = m_nStatMethod;
dlg.m_strLogFile = m_strLogFile;
if(dlg.DoModal()==IDOK)
{
m_nStatMethod = dlg.m_nStatMethod;
m_strLogFile = dlg.m_strLogFile;
}
}
int CCountingDlg::HowManyCharsInString(CString str, CString chars, BOOL bCommentSet)
{
str.TrimLeft();
int nCount=0;
//要考虑/*/的情形
// if(str.Find("/*/")!=-1)
// {
// CString strLeft = str.Left(str.Find("/*/"));
// if(strLeft.Find("*/")==-1 && chars == "/*" && bCommentSet)
// nCount--;
// if(strLeft.Find("/*/")==-1 && chars == "*/" && !bCommentSet)
// nCount--;
// }
while(str.Find(chars)!=-1)
{
nCount++;
str = str.Right(str.GetLength()-str.Find(chars)-chars.GetLength());
}
return max(nCount, 0);
}
BOOL CCountingDlg::IsOdd(int nQuatos)
{
if(nQuatos%2==0)return FALSE;
return TRUE;
}
BOOL CCountingDlg::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
if(m_nSysTimer!=NULL)
{
KillTimer(m_nSysTimer);
m_nSysTimer = NULL;
}
return CDialog::DestroyWindow();
}