VC如何得到文件夹的路径
一、
经常需要用到“选择文件夹”对话框,相应的API已经很好用,但稍嫌麻烦,所以我专门将其封装了一下,力求一步到位。
函数封装如下:
CString GetPath()
{
CString strPath = "";
BROWSEINFO bInfo;
ZeroMemory(&bInfo, sizeof(bInfo));
bInfo.hwndOwner = m_hWnd;
bInfo.lpszTitle = _T("请选择路径: ");
bInfo.ulFlags = BIF_RETURNONLYFSDIRS;
LPITEMIDLIST lpDlist; //用来保存返回信息的IDList
lpDlist = SHBrowseForFolder(&bInfo) ; //显示选择对话框
if(lpDlist != NULL) //用户按了确定按钮
{
TCHAR chPath[255]; //用来存储路径的字符串
SHGetPathFromIDList(lpDlist, chPath);//把项目标识列表转化成字符串
strPath = chPath; //将TCHAR类型的字符串转换为CString类型的字符串
}
return strPath;
}
调用时只需要用到以下代码:
CString strPath = GetPath();
则strPath为用户选择的文件夹路径。如果用户点击了对话框的取消键,则strPath为空字符串("");
本文来自CSDN博客,转载请标明出处:https://www.doczj.com/doc/c64474684.html,/zztxl/archive/2009/04/17/4088092.aspx
二、
本程序的功能为:在对话框中的一个命令按钮的事件中,打开一个浏览文件夹对话框,让用户选择文件夹的路径,并把路径的名称显示在标题栏中。
函数代码如下:
void CEyesDectectDlg::OnButtonGetDir()
{
CString strDir;
BROWSEINFO lpbi;
TCHAR lpDir[MAX_PATH];
CString path("");
lpbi.hwndOwner = this->m_hWnd;
lpbi.pidlRoot = NULL; // 默认路径
lpbi.pszDisplayName = lpDir;
lpbi.lpszTitle = _T("请选择文件夹:");
lpbi.ulFlags = BIF_RETURNONLYFSDIRS ;
lpbi.lpfn = NULL;
lpbi.lParam = NULL;
lpbi.iImage = NULL;
LPITEMIDLIST lpidl = :: SHBrowseForFolder(&lpbi);
if(lpidl)
if (SHGetPathFromIDList(lpidl, lpDir))
{
strDir = lpDir;
this->SetWindowText(strDir);
return ;
}
}
常用的宽字符函数和安全CRT函数
宽字符类型和函数是C和C++标准(ANSI/ISO/IEC C 1999和ISO/IEC C++ 1998/2003)新增加的内容,它们是用来支持国际通用的Unicode(1993)字符集的。微软公司从Visual C++ 2005版起,开始严格执行C/C++的新标准。
安全CRT函数是微软公司对C/C++语言的扩展,其中的部分内容已于2003
年提交给ISO作为C/C++标准下一版本的修改建议。在VC05/08中,如果不使用这些安全性函数,编译器会报告警告性错误。
1)常用的宽字符函数
由于Windows NT/2000/XP采用的是Unicode字符编码,字符都是双字节的。所以在MFC编程中,一般需要使用双字节的字符类型wchar_t和对应的字符串及其指针类型LPCWSTR和LPCTSTR,并在常数字符串前添加了L转换符,串长计算
函数不能用strlen而改用wcslen,串格式打印函数也不能用sprintf,而是改用swprintf(字符和串格式符也从%c和%s改为%lc和%ls)。
wchar_t类型,在标准C++中为内置的数据类型和关键字;在C99标准中则为typedef类型,其等价的数据类型与具体的实现有关,在Win32和VC中定义为:
typedef unsigned short wchar_t; (双字节的无符号短整数)下面是若干常用的宽字符函数(包含在ISO C99 / ISO C++的标准库中):#include
size_t wcslen(const wchar_t *s);
int wprintf(const wchar_t * format, ...);
int wscanf(const wchar_t * format, ...);
int swprintf(wchar_t * s, size_t n, const wchar_t * format, ...);
int swscanf(const wchar_t * s, const wchar_t * format, ...);
long int wcstol(const wchar_t * nptr, wchar_t ** endptr, int base); float wcstof(const wchar_t * nptr, wchar_t ** endptr);
double wcstod(const wchar_t * nptr, wchar_t ** endptr);
#include
errno_t _itow_s( int value, wchar_t *buffer, size_t sizeInCharacters, int radix );
errno_t _ultow_s( unsigned long value, wchar_t *str, size_t sizeOfstr, int radix );
size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ); size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count );
2)常用的安全CRT函数
安全CRT(C Runtime Library = C运行时间库)函数,是微软公司对C/C++语言的扩展。它在原来函数名后添加了“_s”后缀;一般返回出错代码;并将原来的函数返回值,作为一个参数,添加到函数输入参数列表的最后;对带缓冲区参数的函数,还添加了表示缓冲区大小的输入参数,以防止内存溢出。
在VC05/08中,如果不使用这些安全性函数,编译器会报告警告性错误。
下面是若干常用的安全CRT函数:
char *gets_s( char *buffer, size_t sizeInCharacters); //
errno_t _itoa_s( int value, char *buffer, size_t sizeInCharacters, int radix ); //
errno_t _itow_s( int value, wchar_t *buffer, size_t sizeInCharacters, int radix ); //
errno_t _ultoa_s( unsigned long value, char *str, size_t sizeOfstr, int radix ); //
errno_t _ultow_s( unsigned long value, wchar_t *str, size_t sizeOfstr, int radix ); //
int printf_s( const char *format [, argument]... ); //
int wprintf_s( const wchar_t *format [, argument]... ); //
int scanf_s( const char *format [, argument]... ); //
int wscanf_s( const wchar_t *format [, argument]... ); //
int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ... ); //
int swprintf_s( wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format [, argument]...); //
int sscanf_s( const char *buffer, const char *format [, argument ] ...);
//
int swscanf_s( const wchar_t *buffer, const wchar_t *format [, argument ] ...); //
int fprintf_s( FILE *stream, const char *format [, argument ]...); //
int fwscanf_s( FILE *stream, const wchar_t *format [, argument ]... );
//
int fscanf_s( FILE *stream, const char *format [, argument ]... ); //
int fwscanf_s( FILE *stream, const wchar_t *format [, argument ]... );
//
errno_t strcpy_s( char *strDestination, size_t sizeInBytes, const char *strSource ); //
errno_t wcscpy_s( wchar_t *strDestination, size_t sizeInWords, const wchar_t *strSource ); //
errno_t fopen_s( FILE** pFile, const char *filename, const char *mode ); //
errno_t _wfopen_s( FILE** pFile, const wchar_t *filename, const wchar_t *mode ); //
errno_t mbstowcs_s( size_t *pConvertedChars, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count ); //
#include
typedef int errno_t;
typedef unsigned short wchar_t;
#ifdef _WIN64
typedef unsigned __int64 size_t;
#else
typedef _W64 unsigned int size_t;
#endif
3)[宽]字符串转换
可以利用L运算符和若干函数在[单字节/多字节的]普通字符串和[双字节的]宽字符串之间进行相互转换。
●char -> wchar_t
?L运算符
在串常量前加上L运算符,可以将普通字符串转换为宽字符串;例如:
wchar_t *wstr = L"A string to a wide character string.";
CString str = L"A string to a wide character string.";
MessageBox(L"创建位图出错!", L"错误");
?AllocSysString函数
可以利用CString类的AllocSysString()函数来将普通字符串转换成宽
字符串:
BSTR AllocSysString() const;
其中BSTR相当于wchar_t *的typedef类型。例如:
CString str("A string to a wide character string.");
wchar_t *wstr = str.AllocSysString();
MessageBox(wstr);
说明:CString类是VC中定义的MFC/ATL共享模板类CStringT的一个实现:template< typename BaseType, class StringTraits > class CStringT :
public CSimpleStringT StringTraits > ::c_bIsMFCDLLTraits> // typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString; // ?mbstowcs[_s]函数 可以用 数: size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ); // 成功返回被转换的字符数,失败返回-1 // 若wcstr = NULL,则返回所需宽字符串的大小(宽字符数)errno_t mbstowcs_s( size_t *pConvertedChars, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count ); // 成功返回0 来将普通[多字节]字符串转换为宽字符串。例如: char *str = "A sample string."; wchar_t wstr[80]; size_t cn = 0; // 输出参数,用于存放被转换的字符数,包括null 结束符'\0' if (!mbstowcs_s(&cn, wstr, 80, str, strlen(str))) MessageBox(wstr); else MessageBox(L"转换字符串出错!"); wchar_t -> char(只能用于西文串,不能用于中文串) 只能利用 size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count ); errno_t wcstombs_s( size_t *pConvertedChars, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count ); 来将宽字符串转换为普通[多字节]字符串。例如: char str[80]; wchar_t *wstr = L"A sample string."; size_t cn = 0; // 输出参数,用于存放被转换的字符数,包括null 结束符'\0' if (wcstombs_s(&cn, str, 80, wstr, wcslen(wstr))) MessageBox(L" 转换字符串出错!"); 又例如: int m, n; const size_t bufSize = 300; char buf[bufSize]; wchar_t wbuf[bufSize]; CString fn = pDoc->GetPathName(); wcscpy_s(wbuf, bufSize, fn); size_t cn = 0; wcstombs_s(&cn, buf, bufSize, wbuf, bufSize); FILE *stream; if (!fopen_s(&stream, buf, "rt")) { fscanf_s(stream, "%d %d", &m, &n); //…… } 算法中的精确时间计数器的应用 评价一个算法的好坏,在运行时所消耗的时间是一个很重要的参数,可以反应出该算法的时间复杂度。要测试一个程序运行时所消耗的时间,我们可以写出很多种算法。很多编译器都提供了相关的时间函数库,还有系统的API等等。但是,我们会发现这些函数在程序中根本本能得到满意的结果。有时候设计得很好的算法,或者很小的算法,在运行的时候非常快,在1ms以内,这时候要测试这个算法所消耗的时间就是一件不容易的事情。 在头文件time.h中有个函数clock(),返回clock_t的类型,可以通过两次调用clock函数,来确定时间间隔。API中有一个函数叫做GetTickCount的函数,可以得到当前计算机运行的时间,它返回一个DWORD 值。在程序短之前加入一句DWORD t=GetTickCount();在程序段后加入t=GetTickCount()-t,则t的结果就是此程序段运行的时间。但是我们会发现很多程序段的结果输出都是0ms,所以我们需要比这个精度更高的函数。有没有这样的函数呢,通过查询MSDN,发现有两个函数满足要求,QueryPerformanceFrequency 和QueryPerformanceCounter,它可以精确到0.5微秒,具体说明可以参见MSDN。为了方便我们以后在对算法时间的计算,我们把他封装成一个计时器类: #include #include using namespace std; class TimeTake{ public: TimeTake():dCount(0) { // 获得计数器的时钟频率 QueryPerformanceFrequency(&lPoint); dFreq=(double)lPoint.QuadPart; } ~TimeTake() { } void print() { cout< } void start() { //第一次取计数器的值 QueryPerformanceCounter(&lPoint); lPart=lPoint.QuadPart; } void end() { //再一次取计数器的值并计算中间的时间间隔,表示成ms QueryPerformanceCounter(&lPoint); dCount=(double(lPoint.QuadPart-lPart)/dFreq)*1000; } private: LARGE_INTEGER lPoint; LONGLONG lPart; double dFreq, dCount; }; 我们可以写三个算法,用其对他们进行测试,下面几个算法都是求最大公约数的问题,第二个是第一个算法的改进,第三个是求使得a*m+b*n=d的最大公因数,详细算法如下: DWORD mode1(DWORD m,DWORD n) { int r=m%n; while(r!=0) { m=n; n=r; r=m%n; } return n; } DWORD mode2(DWORD m,DWORD n) { DWORD r,result; while(1) { r=m%n; if(r==0) { result=n; break; } m=n%r; if(m==0) { result=r; break; } n=r%m; if(n==0) { result=m; break; } } return result; } //求接a,b使得am+bn=d,d为最大公倍数DWORD mode(DWORD m,DWORD n,int& a,int& b) { int al,bl; //求解al,bl使得al*m+bl*n=c; DWORD c,d,q,r,t; c=m; d=n; b=al=1; while(1) { q=c/d; r=c%d; if(r==0) break; else { c=d; d=r; t=al; al=a; a=t-q*a; t=bl; bl=b; b=t-q*b; } } return d; } 然后编写主程序进行测试: int _tmain(int argc, _TCHAR* argv[]) { TimeTake tk; int a,b; DWORD m,n,d1,d2;