vc写的工程源代码打包工具

大部分VC编程的朋友都遇到过这种情况:写过的一大堆工程代码在硬盘里放着,有时候想找某个工程的源代码查看都找不到,同时一些不舍得删又没多大用的工程放在哪儿也占地方,像我就下载了很多教程的配套源代码,大小差不多有两三个多G,放在那儿实在是占地方。而且查看时得一个文件夹一个文件夹的找,太麻烦。所以没事就借用了Mike Benzinger写的的CppToHTML转换代码,写了一个将VC工程目录下的.cpp、.c、.h文件转换成html网页文件,同时将工程所需的所有项目文件、源文件、资源文件打包成rar的小工具。通过这个工具转换之后,再用QuickCHM、EasyCHM或者琐碎打包工具等等将这些转换好的html文件或者rar文件编译成chm帮助文件,即节省了大量空间(两个多G的源代码转换打包之后只有两三百来兆,经过编译成chm之后会更小),也方便查看。

 

源代码打包下载地址:http://download.csdn.net/source/2245312

https://www.sugarsync.com/pf/D737057_194644_70653

程序执行界面:

转换打包好后用QuickCHM编译成的chm文件:

点击CHM中“源代码打包”中的rar可以将rar文件下载保存到本地,就跟VCKBase期刊chm版一样:



以下介绍一下程序中几个关键的地方:
这样的程序当然用对话框比较方便。编辑好界面并添加好相关的变量:
    CString m_PrjPath; //用户所选择的VC 工程所在文件夹路径
    CString m_SavePath; //用户选择的转换后保存到文件夹的位置
    CString m_strShow; //程序执行的结果显示
    BOOL  m_bConverted; 

用户单击选择需转换的VC++工程文件夹的响应函数(这个函数体中查找cpp、h、c文件时用到了唐胜写的一个查找文件类:CFileFindExt,
具体见源代码附件):
void CVCPrjToHtmlDlg::OnBnClickedLiulan1()
{
    // TODO: 在此添加控件通知处理程序代码
    //显示选择文件夹对话框
    CString StrFolder;
    BROWSEINFO bi;    
    memset(&bi, 0, sizeof(BROWSEINFO) );
    bi.hwndOwner = GetSafeHwnd();
    bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
    bi.lpszTitle=L"选择VC工程文件夹";
    LPITEMIDLIST idl=SHBrowseForFolder(&bi);
    if(idl==NULL)
     return;
    SHGetPathFromIDList(idl,StrFolder.GetBuffer(MAX_PATH));
    StrFolder.ReleaseBuffer();
    m_PrjPath=StrFolder;
    UpdateData(false);
     
    //清空文件路径保存链表
    for(int i=0;i<m_Array.GetSize();i++)
    {
        FileInfo* p=(FileInfo*)m_Array.GetAt(i);
        delete p;
    }
    m_Array.RemoveAll();

    FileHead.m_FileNames.RemoveAll(); //清空三个查找文件对象,准备查找文件
    FileCpp.m_FileNames.RemoveAll();
    FileC.m_FileNames.RemoveAll();
    FileHead.SearchFiles(StrFolder,0,0,_T("*.h"));//查找三种类型的文件
    FileCpp.SearchFiles(StrFolder,0,0,_T("*.cpp"));
    FileC.SearchFiles(StrFolder,0,0,_T("*.c"));

    //将查找到的三种类型文件的路径都加入到一个链表中,然后传递给一个新建的线程来开始转换文件
    if(FileHead.m_FileNames.GetSize()>0)
    {
        for(int i=0;i<FileHead.m_FileNames.GetSize();i++)
        {
            CString str=StrFolder+_T("//")+FileHead.m_FileNames.GetAt(i);
            FileInfo* p=new FileInfo;
            p->FileName=FileHead.m_FileNames.GetAt(i);
            p->Path=str;
            m_Array.Add((void*)p);
        }
    }
    if(FileCpp.m_FileNames.GetSize()>0)
    {
        for(int i=0;i<FileCpp.m_FileNames.GetSize();i++)
        {
            CString str=StrFolder+_T("//")+FileCpp.m_FileNames.GetAt(i);
            FileInfo* p=new FileInfo;
            p->FileName=FileCpp.m_FileNames.GetAt(i);
            p->Path=str;
            m_Array.Add((void*)p);
        }
    }
    if(FileC.m_FileNames.GetSize()>0)
    {
        for(int i=0;i<FileC.m_FileNames.GetSize();i++)
        {
            CString str=StrFolder+_T("//")+FileC.m_FileNames.GetAt(i);
            FileInfo* p=new FileInfo;
            p->FileName=FileC.m_FileNames.GetAt(i);
            p->Path=str;
            m_Array.Add((void*)p);
        }
    }
    m_bConverted=false;
}

选择好工程文件夹以及转换后保存的位置之后,点击”开始转换“按钮转换打包:
void CVCPrjToHtmlDlg::OnBnClickedConvert()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(true);
    if(m_PrjPath.IsEmpty())
    {
        AfxMessageBox(_T("请先选择需转换的工程路径!"));
        return;
    }
    if(m_SavePath.IsEmpty())
    {
        AfxMessageBox(_T("请先选择保存路径!"));
        return;
    }
    if(m_bConverted==true)
    {
        AfxMessageBox(_T("该工程刚刚已经转换过!"));
        return;
    }

    GetDlgItem(IDC_CONVERT)->EnableWindow(false);//禁用”开始转换"按钮,以防止用户误操作再次打开转换
    m_strShow.Empty();//清空显示内容
    UpdateData(false);
    CFileStatus status;
    if(!CFile::GetStatus(m_CurrentFolder+_T("//7z.exe"),status))//利用7z的控制台程序将工程打包成rar,这里是将运行所需的7z.exe和7z.dll释放到文件中
    {
        ReleaseEXERes(m_CurrentFolder+_T("//7z.exe"),IDR_7ZEXE,_T("EXE"));
    }
    if(!CFile::GetStatus(m_CurrentFolder+_T("//7z.dll"),status))
    {
        ReleaseEXERes(m_CurrentFolder+_T("//7z.dll"),IDR_7ZDLL,_T("DLL"));
    }

    hThread=CreateThread(NULL,NULL,ConvertThread,LPVOID(this),0,&ThreadID);//开启转换线程,转换需要一定时间,这里为了防止程序出现假死状况,新开一个线程来转换
    WaitForSingleObject(hThread,IGNORE  );
 
    m_bConverted=true;
}



转换线程函数:
DWORD WINAPI ConvertThread(LPVOID lp)
{
    //通过传递过来的参数得到相关变量
    CVCPrjToHtmlDlg* pDlg=(CVCPrjToHtmlDlg*)lp;
    CString m_PrjPath=pDlg->m_PrjPath;
    CString m_SavePath=pDlg->m_SavePath;
    int sep=m_PrjPath.ReverseFind('//');
    CString Path=m_PrjPath.Right(m_PrjPath.GetLength()-sep-1);
    //for循环开始转换文件
    for(int i=0;i<pDlg->m_Array.GetSize();i++)
    {
        FileInfo* p=(FileInfo*)pDlg->m_Array.GetAt(i); 
        CString srcPath=p->Path;
        CString srcName=p->FileName;
        CString strTip=_T("正在转换: ")+srcName;
        pDlg->SendMessage(NM_UPDATE,1,(LPARAM)&strTip);//向主窗口发送消息,更新程序执行状况信息

        /*一系列的文件路径处理,为了保证转换VC工程时相对路径不变,例如原来的VC工程在“D:/编程开发/vc++/MFC练习/Test1”中,用户选择的路径是“D:/编程开发/vc++/MFC练习”,用户选择转换后保存到桌面,则转换后的文件保存在“C:/Users/Administrator/Desktop/MFC练习/Test1”中,并且将头文件和cpp文件分开保存,这样在编译成chm会更方便查看。假如“D:/编程开发/vc++/MFC练习”文件夹下还有其他更多的工程,则程序会将它们一起都转换*/
        int sp=srcName.ReverseFind('//');
        if(sp!=-1)
            srcName=srcName.Right(srcName.GetLength()-sp-1);
        srcName.MakeLower();
        srcPath.MakeLower();
        sp=srcPath.Find(srcName);
        CString prjName=srcPath;
        m_PrjPath.MakeLower();
        prjName.Replace(m_PrjPath+_T("//"),_T(""));
        //sp=prjName.Find('//');
        //prjName=prjName.Left(sp);
        sp=prjName.ReverseFind('//');
        prjName=prjName.Left(sp);
        
        CString folder;
        if(srcName.Right(4)==_T(".cpp") || srcName.Right(2)==_T(".c"))
            folder=m_SavePath+_T("//")+Path+_T("//")+prjName+_T("//")+_T("源文件"); 
        else
            folder=m_SavePath+_T("//")+Path+_T("//")+prjName+_T("//")+_T("头文件");

        SHCreateDirectoryExW(NULL,folder,NULL);
        CString dstPath=folder+_T("//")+srcName+_T(".html");
        ConvertToHtml(srcPath,dstPath); //调用cpptohtml.h中的ConvertToHtml函数转换文件
        delete p;
    }
    pDlg->m_Array.RemoveAll();//清空路径链表

    //查找工程。VC6.0的工程后缀名是dsp,VC7.0(VC2003)、VC8.0(VC2005)等版本的工程后缀名是vcproj。
    CFileFindExt  Filedsp; 
    CFileFindExt      Filevcproj;
    Filedsp.SearchFiles(m_PrjPath,0,0,_T("*.dsp"));
    Filevcproj.SearchFiles(m_PrjPath,0,0,_T("*.vcproj"));
    CString strPack=m_SavePath+_T("//")+Path+_T("//");
    SHCreateDirectoryExW(NULL,strPack,NULL);
    CStringArray  m_Array;
    //转换查找到的工程
    for(int i=0;i<Filevcproj.m_FileNames.GetSize();i++)
    {
        //路径处理,保证转换后的rar文件保存到转好后的相应的工程文件夹内
        CString strPath=m_PrjPath+_T("//")+Filevcproj.m_FileNames.GetAt(i);
        CString strFolder=strPath;
        CString strName=Filevcproj.m_FileNames.GetAt(i);
        int sp=strName.ReverseFind('//');
        if(sp!=-1)
            strName=strName.Right(strName.GetLength()-sp-1);
        strName.MakeLower();
        strFolder.MakeLower();
        strFolder.Replace(strName,_T(""));
        if(!pDlg->IsPacked(strFolder,m_Array))
        {
            m_Array.Add(strFolder);
            CString Release=strFolder.Left(strFolder.GetLength()-1);
            int sep=Release.ReverseFind('//');
            CString prjName=Release.Right(Release.GetLength()-sep-1);
            Release=Release.Left(sep);
            Release+=_T("//Release//");
            CString tip=_T("正在压缩工程:  ")+prjName+_T(".vcproj");
            pDlg->SendMessage(NM_UPDATE,1,(LPARAM)&tip);
            CString prj=strPath;
            prj.MakeLower();
            prj.Replace(m_PrjPath+_T("//"),_T(""));
            int nsp=prj.ReverseFind('//');
            prj=prj.Left(nsp);
            CString PackPath=strPack+prj+_T("//")+_T("源文件打包")+_T("//")+prjName+_T(".rar.rar");
            CFileStatus status;
            if(CFile::GetStatus(PackPath,status))
            {
                CString cs;
                cs.Format(_T("%d"),i);
                PackPath=strPack+prj+_T("//")+_T("源文件打包")+_T("//")+prjName+cs+_T(".rar.rar");
            }

            //筛选打包到rar中的文件类型,只打包工程所需的文件,其他的临时文件等一律不打包,减小体积
            CString Type=_T(" /"")+strFolder+_T("*//*.cpp/" ");
            Type+=_T(" /"")+strFolder+_T("*.cpp/" ");
            Type+=_T(" /"")+strFolder+_T("*.c/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.c/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.h/" ");
            Type+=_T(" /"")+strFolder+_T("*.h/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.vcproj/" ");
            Type+=_T(" /"")+strFolder+_T("*.vcproj/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.rc/" ");
            Type+=_T(" /"")+strFolder+_T("*.rc/" ");
            Type+=_T(" /"")+Release+_T("*.exe/" ");
            Type+=_T(" /"")+Release+_T("*.dll/"  ");
            Type+=_T(" /"")+strFolder+_T("*.exe/" ");
            Type+=_T(" /"")+strFolder+_T("*.dll/" ");
            Type+=_T(" /"")+strFolder+_T("*.lib/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.lib/" ");
            Type+=_T(" /"")+strFolder+_T("*//release//*.exe/" ");
            Type+=_T(" /"")+strFolder+_T("*//release//*.dll/"  ");
            Type+=_T(" /"")+strFolder+_T("res///" ");
            Type+=_T(" /"")+strFolder+_T("*//res///" ");
            /**/
            CString cmdLine=_T("7z.exe a /"")+PackPath+_T("/" ")+Type; //构造命令行
            

            STARTUPINFO si;
            GetStartupInfo(&si);
            si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
            si.wShowWindow=SW_HIDE;
            PROCESS_INFORMATION ProcessInformation;
            int ret=CreateProcess(NULL, cmdLine.GetBuffer(),NULL,NULL,1,0,NULL,NULL, &si,&ProcessInformation); //用构造好的命令行打开7z.exe开始打包
            WaitForSingleObject(ProcessInformation.hProcess,INFINITE);
            CloseHandle(ProcessInformation.hProcess);
        }
    }

    for(int i=0;i<Filedsp.m_FileNames.GetSize();i++)
    {
        CString strPath=m_PrjPath+_T("//")+Filedsp.m_FileNames.GetAt(i);
        CString strFolder=strPath;
        CString strName=Filedsp.m_FileNames.GetAt(i);
        int sp=strName.ReverseFind('//');
        if(sp!=-1)
            strName=strName.Right(strName.GetLength()-sp-1);
        strName.MakeLower();
        strFolder.MakeLower();
        strFolder.Replace(strName,_T(""));
        if(!pDlg->IsPacked(strFolder,m_Array))
        {
            m_Array.Add(strFolder);
            CString Release=strFolder.Left(strFolder.GetLength()-1);
            int sep=Release.ReverseFind('//');
            CString prjName=Release.Right(Release.GetLength()-sep-1);
            CString tip=_T("正在压缩工程:  ")+prjName+_T(".dsp");
            pDlg->SendMessage(NM_UPDATE,1,(LPARAM)&tip);
            CString prj=strPath;
            prj.MakeLower();
            prj.Replace(m_PrjPath+_T("//"),_T(""));
            int nsp=prj.ReverseFind('//');
            prj=prj.Left(nsp);
            CString PackPath=strPack+prj+_T("//")+_T("源文件打包")+_T("//")+prjName+_T(".rar.rar");
            CFileStatus status;
            if(CFile::GetStatus(PackPath,status))
            {
                CString cs;
                cs.Format(_T("%d"),i);
                PackPath=strPack+prj+_T("//")+_T("源文件打包")+_T("//")+prjName+cs+_T(".rar.rar");
            }
            CString Type=_T(" /"")+strFolder+_T("*//*.cpp/" ");
            Type+=_T(" /"")+strFolder+_T("*.cpp/" ");
            Type+=_T(" /"")+strFolder+_T("*.c/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.c/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.h/" ");
            Type+=_T(" /"")+strFolder+_T("*.h/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.dsp/" ");
            Type+=_T(" /"")+strFolder+_T("*.dsp/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.dsw/" ");
            Type+=_T(" /"")+strFolder+_T("*.dsw/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.clw/" ");
            Type+=_T(" /"")+strFolder+_T("*.clw/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.rc/" ");
            Type+=_T(" /"")+strFolder+_T("*.rc/" ");
            Type+=_T(" /"")+strFolder+_T("*.exe/" ");
            Type+=_T(" /"")+strFolder+_T("*.dll/" ");
            Type+=_T(" /"")+strFolder+_T("*.lib/" ");
            Type+=_T(" /"")+strFolder+_T("*//*.lib/" ");
            Type+=_T(" /"")+strFolder+_T("release//*.exe/" ");
            Type+=_T(" /"")+strFolder+_T("*//release//*.exe/" ");
            Type+=_T(" /"")+strFolder+_T("release//*.dll/"  ");
            Type+=_T(" /"")+strFolder+_T("*//release//*.dll/" ");
            Type+=_T(" /"")+strFolder+_T("res///" ");
            Type+=_T(" /"")+strFolder+_T("*//res///" ");
            /**/
            CString cmdLine=_T("7z.exe a /"")+PackPath+_T("/" ")+Type;
            

            STARTUPINFO si;
            GetStartupInfo(&si);
            si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
            si.wShowWindow=SW_HIDE;
            PROCESS_INFORMATION ProcessInformation;
            int ret=CreateProcess(NULL, cmdLine.GetBuffer(),NULL,NULL,1,0,NULL,NULL, &si,&ProcessInformation);
            WaitForSingleObject(ProcessInformation.hProcess,INFINITE);
            CloseHandle(ProcessInformation.hProcess);
        }
    }
    
    pDlg->SendMessage(NM_UPDATE,0,0);
    pDlg->m_bConverted=true;
    return 0;
}

主窗口中刷新显示信息的函数(不知为何,有时候刷新一会儿之后编辑框中显示的信息就不动了,很奇怪,一直没找到原因):
LRESULT CVCPrjToHtmlDlg::OnUpdateTips(WPARAM wParam, LPARAM lParam)
{
    UINT nState=(UINT)wParam;
    if(nState==0)
    {
        UpdateData(true);
        GetDlgItem(IDC_CONVERT)->EnableWindow(true);
        int Len=m_strShow.GetLength();
        CEdit* pEdit=(CEdit*)GetDlgItem(IDC_SHOW);
        pEdit->SetSel(Len,Len,0);
        pEdit->ReplaceSel(_T("/r/n转换完毕/r/n/r/n1、选择VC工程所在的路径/r/n/r/n2、选择转换成html后保存的位置/r/n/r/n3、点击“开始转换”执行转换/r/n/r/n/r/n"));
        m_bConverted=true;
        AfxMessageBox(_T("转换完毕!"));
        return 0;
    }
    else if(nState==1)
    {
        UpdateData(true);
        CString*  strText=(CString*)lParam;
        int Len=m_strShow.GetLength();
        CEdit* pEdit=(CEdit*)GetDlgItem(IDC_SHOW);
        pEdit->SetSel(Len,Len,0);
        pEdit->ReplaceSel(*strText+_T("/r/n"));
        return 0;
    } 
}


以上只是程序中几个关键地方的简单介绍,具体参见源代码。本程序实际上只负责转换和打包,最好是配合QuickCHM、EasyCHM或者琐碎打包工具等等将这些转换好的html文件和rar文件编译成chm帮助文件。
由于能力有限程序中可能出现某些bug,哪位朋友发现后望请留言告知,以待改进,谢谢……

你可能感兴趣的:(自己写的VC小程序,工具,null,chm,path,html,winapi)