***********************************************声明************************************************************
原创作品,出自 “晓风残月xj” 博客,欢迎转载。转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。
因为各种原因。可能存在诸多不足。欢迎斧正。
****************************************************************************************************************
近期在做安装包解压,涉及到非常多关于路径的操作。当然非常须要调用非常多Windows API函数,本来是没有什么技术含量的,但因为Windows中关于文件夹、路径的操作较为重要。并且当中蕴含着一些重要的编程思想及技巧,所以在此加以总结,希望对以后的学习工作起到作用,同一时候更希望能帮助大家解决这个问题。共同创建一个知识分享型的网络社区。
如今提供下面几个操作方法。持续更新中…
1、在指定路径下创建目录
2、获取程序的安装路径
3、对话框支持文件拖拽
4、获取当前进程已载入模块的文件的完整路径
5、文件(夹)的操作,如复制、删除、移动等
下面是具体介绍。
1、在指定路径下创建目录
void PathRemoveFileSpec(CString& strPath) { int nPos = strPath.ReverseFind(_T('\')); if (nPos == -1) { strPath.Empty(); } else { strPath = strPath.Left(nPos); } } BOOL CreateDeepDirectory(LPCTSTR szPath) { BOOL bRetCode = FALSE; CString strPath(szPath); if (GetFileAttributes(szPath) != INVALID_FILE_ATTRIBUTES) return TRUE; bRetCode = CreateDirectory(szPath, NULL); if (!bRetCode && GetLastError() != ERROR_ALREADY_EXISTS) { PathRemoveFileSpec(strPath); if (strPath.IsEmpty()) return FALSE; bRetCode = CreateDeepDirectory(strPath); if (!bRetCode) return FALSE; bRetCode = CreateDirectory(szPath, NULL); if (!bRetCode && GetLastError() != ERROR_ALREADY_EXISTS) return FALSE; } return TRUE; }
2、获取程序的安装路径
非常多应用程序会在注冊表中存储对应信息,此时能够从注冊表中获取应用程序的安装路径。
//InstallSoftwarePath.h #ifndef _InstallSoftwarePath_H #define _InstallSoftwarePath_H class CInstallSoftwarePath { public: CInstallSoftwarePath(void); ~CInstallSoftwarePath(void); CString GetSoftwarePath(void); private: CString m_cstrSoftwarePath; }; #endif
//InstallSoftwarePath.cpp #include "StdAfx.h" #include "InstallSoftwarePath.h" TCHAR g_szName[] = _T("XXX");//代表应用程序名 CInstallSoftwarePath::CInstallSoftwarePath(void) { m_cstrSoftwarePath=_T(""); } CInstallSoftwarePath::~CInstallSoftwarePath(void) { } CString CInstallSoftwarePath::GetSoftwarePath(void) { HKEY keyFirst = NULL, keySecond = NULL; TCHAR szSub[] = _T("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"); TCHAR szName[200] = {0}; TCHAR szDisplay[200] = {0}; TCHAR szShow[200] = {0}; TCHAR szIcon[200] = {0}; DWORD dwIclen = 200; DWORD dwIndex = 0, dwNameSize = 200, dwShowLen = 200; DWORD m_attr=REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSub, 0, KEY_ALL_ACCESS, &keyFirst)) { while(ERROR_NO_MORE_ITEMS != RegEnumKeyEx(keyFirst, dwIndex, szName, &dwNameSize, 0, NULL, NULL, 0)) { dwIndex++; if (0 != _tcscmp(szName, _T(""))) { _tcscpy(szDisplay, szSub); _tcscat(szDisplay, _T("\")); _tcscat(szDisplay, szName); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDisplay, 0, KEY_ALL_ACCESS, &keySecond)) { memset(szName, 0, sizeof(szName)); memset(szShow, 0, sizeof(szShow)); memset(szIcon, 0, sizeof(szIcon)); dwIclen=200; dwNameSize = 200; dwShowLen = 200; RegQueryValueEx(keySecond, _T("DisplayName"), NULL, &m_attr, (LPBYTE)szName, &dwNameSize); RegQueryValueEx(keySecond, _T("DisplayIcon"), NULL, &m_attr, (LPBYTE)szIcon, &dwIclen); if(0 == _tcscmp(szName, g_szName)) { if (keyFirst) { RegCloseKey(keyFirst); } if (keySecond) { RegCloseKey(keySecond); } m_cstrSoftwarePath=szIcon; m_cstrSoftwarePath.Remove('"'); return m_cstrSoftwarePath; } } memset(szName, 0, sizeof(szName)); memset(szShow, 0, sizeof(szShow)); memset(szDisplay, 0, sizeof(szDisplay)); memset(szIcon, 0, sizeof(szIcon)); dwIclen = 200; dwNameSize = 200; dwShowLen = 200; } } } if (keyFirst) { RegCloseKey(keyFirst); } if (keySecond) { RegCloseKey(keySecond); } m_cstrSoftwarePath = _T(""); return m_cstrSoftwarePath; }GetSoftwarePath返回的就是应用程序g_szName的完整安装路径。
3、对话框支持文件拖拽
第一步、须要加入消息响应
WM_DROPFILES
1)、假设是MFC,操作例如以下:对话框上点击右键,选择Properties->Extended Styles。点选Accept files选项就可以。
2)、假设不是MFC,如ATL、Win32、金山卫士开源码等,操作例如以下:
LONG dwLong = GetWindowLong(GWL_EXSTYLE); SetWindowLong(GWL_EXSTYLE, dwLong|WS_EX_ACCEPTFILES);第二步、文件拖拽消息响应函数
void CMainDlg::OnDropFiles(HDROP hDropInfo) { UINT count; TCHAR strFilePath[MAX_PATH + 1] ; count = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); if(count) { for(UINT i=0; i<count; i++) //支持多个文件的拖拽操作 { int pathLen = DragQueryFile(hDropInfo, i, strFilePath, sizeof(strFilePath)); //strFilePath存储的是当前文件的完整路径+文件名称 //此处能够加入待处理的操作。完毕应用程序的功能 } } DragFinish(hDropInfo); //CDialog::OnDropFiles(hDropInfo);//假设是MFC,最好加入此操作 }
4、获取当前进程已载入模块的文件的完整路径,该模块必须由当前进程载入
如以下的C:UsersjimjxuDesktop我的程序1.cpp源程序运行起来就是 "szPath = C:UsersjimjxuDesktop我的程序Debug1.exe"
#include <windows.h> #include <stdio.h> BOOL GetExactFileName() { TCHAR szPath[MAX_PATH]; if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) { printf("GetModuleFileName failed (%d) ", GetLastError()); return FALSE; } printf("szPath = %s ", szPath); return TRUE; } int main(int argc, TCHAR* argv[]) { GetExactFileName(); return 0; }
5、文件(夹)的操作,如复制、删除、移动等
关于文件的操作。较为简单。能够直接调用CopyFile,其原型为:
BOOL CopyFile( LPCTSTR lpExistingFileName, // pointer to name of an existing file LPCTSTR lpNewFileName, // pointer to filename to copy to BOOL bFailIfExists // flag for operation if file exists ); 当中各參数的意义: LPCTSTR lpExistingFileName, // 你要拷贝的源文件名称 LPCTSTR lpNewFileName, // 你要拷贝的目标文件名称 BOOL bFailIfExists // 假设目标已经存在,true:不拷贝并返回False; false:覆盖目标.关于目录的操作。可能略微复杂一点。目录表现为一组文件的集合,本质上和文件没什么差别。
关于目录的操作,大致有2种方法:
第一种:递归复制单个文件注意处理。推断文件夹与文件。然后创建文件(夹)名称。递归拷贝文件。
另外一种:调用Windows API处理。又分为MFC与Win32程序
假设是MFC程序,能够直接用CFileFind处理。有点第一种方法的味道。详细操作例如以下:
BOOL CopyDirectory(CString strSouDir, CString strDesDir) { CFileFind finder; CString str, strWildcard, strFilePath, strDesFilePath; BOOL bRetCode ; if(strDesDir.Right(1) != _T("\")) strDesDir += _T("\"); if(strSouDir.Right(1) != _T("\")) strSouDir += _T("\"); strWildcard = strSouDir + _T("*.*"); BOOL bContinue = finder.FindFile(strWildcard); while (bContinue) { bContinue = finder.FindNextFile(); if(finder.IsDots()) { continue; } str = finder.GetFileName(); if(finder.IsDirectory()) { CString temstrSouDir = strSouDir + str; CString temstrDesDir = strDesDir + str; CreateDirectory(temstrDesDir, NULL); ret = CopyDirectory(temstrSouDir, temstrDesDir); } else { strFilePath = finder.GetFilePath(); strDesFilePath = strDesDir+str; bRetCode = CopyFile(strFilePath, strDesFilePath, FALSE); if(!bRetCode) break; } } finder.Close(); return bRetCode; }
假设是Win32程序,能够直接调用int SHFileOperation(LPSHFILEOPSTRUCT lpFileOp)处理。当中LPSHFILEOPSTRUCT结果例如以下:1.FO_COPY:复制
typedef struct _SHFILEOPSTRUCT { HWND hwnd; //指向发送消息的窗体 UINT wFunc; //运行的操作 LPCTSTR pFrom; //源文件名称 LPCTSTR pTo ;//目标文件名称 FILEOP_FLAGS fFlags; //操作与确认标识 BOOL fAnyOperationsAborted; //操作是否终止 LPVOID hNameMappings; //文件映射 LPCTSTR lpszProgressTitle; //进度条标题 } SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
详细运行文件的操作仅仅需设置对应的值就可以,关于其它成员变量的设置及说明,请点击说明例如以下:
1.FO_COPY:复制 2.FO_DELETE:删除 3.FO_MOVE:移动 4.FO_RENAME:重命名例如以下一段代码就可以完毕复制目录的操作:
BOOL KWork::CopyDir(LPCTSTR lpszSrcDir, LPCTSTR lpszDstDir) { SHFILEOPSTRUCT sfo; ZeroMemory(&sfo, sizeof(sfo)); sfo.wFunc = FO_COPY; sfo.pFrom = lpszSrcDir; sfo.pTo = lpszDstDir; sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR; int ret = SHFileOperation(&sfo); if ( ret == 0 ) return TRUE; else return FALSE; }当然。对于不同的Windows程序,此处表现不同,是一大坑,详细说明点击说明。
本文章持续更新中…
因为写博客时间有限,加之对VC不熟。难免有错误或不足的地方。欢迎斧正!