通过阅读本文你可以学习如何有效地使用 CString。

  CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作,使得MFC在做字符串操作的时候方便了很多。不管怎样,使用CString有很多特殊的技巧,特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。
  使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册,但囊括了大部分常见基本问题。

这篇文章包括以下内容:

  1. CString 对象的连接

  2. 格式化字符串(包括 int 型转化为 CString )
  3. CString 型转化成 int 型
  4. CString 型和 char* 类型的相互转化
  5. char* 转化成 CString
  6. CString 转化成 char* 之一:使用LPCTSTR强制转化
  7. CString 转化成 char* 之二:使用CString对象的GetBuffer方法
  8. CString 转化成 char* 之三: 和控件的接口
  9. CString 型转化成 BSTR 型;
  10. BSTR 型转化成 CString 型;
  11. VARIANT 型转化成 CString 型;
  12. 载入字符串表资源;
  13. CString 和临时对象;
  14. CString 的效率;
  15. 总结

下面我分别讨论。

1、CString 对象的连接

  能体现出 CString 类型方便性特点的一个方面就字符串的连接,使用 CString 类型,你能很方便地连接两个字符串,正如下面的例子:

CString gray("Gray");CString cat("Cat");CString graycat = gray + cat;

要比用下面的方法好得多:

char gray[] = "Gray";char cat[] = "Cat";char * graycat = malloc(strlen(gray) + strlen(cat) + 1);strcpy(graycat, gray);strcat(graycat, cat);

2、格式化字符串

  与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString 对象的Format()方法:

CString s;s.Format(_T("The total is %d"), total);

  用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由CString类替你完成。
  格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧,比如,把一个整数转化成CString类型,可用如下方法:

CString s;s.Format(_T("%d"), total);

  我总是对我的字符串使用_T()宏,这是为了让我的代码至少有Unicode的意识,当然,关于Unicode的话题不在这篇文章的讨论范围。_T()宏在8位字符环境下是如下定义的:

#define _T(x) x // 非Unicode版本(non-Unicode version)

而在Unicode环境下是如下定义的:

#define _T(x) L##x // Unicode版本(Unicode version)

所以在Unicode环境下,它的效果就相当于:

s.Format(L"%d", total);

  如果你认为你的程序可能在Unicode的环境下运行,那么开始在意用 Unicode 编码。比如说,不要用 sizeof() 操作符来获得字符串的长度,因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节,比如在我需要获得字符长度的时候,我会用一个叫做DIM的宏,这个宏是在我的dim.h文件中定义的,我会在我写的所有程序中都包含这个文件:

#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )

  这个宏不仅可以用来解决Unicode的字符串长度的问题,也可以用在编译时定义的表格上,它可以获得表格的项数,如下:

class Whatever { ... };Whatever data[] = {   { ... },    ...   { ... },};for(int i = 0; i < DIM(data); i++) // 扫描表格寻找匹配项。

  这里要提醒你的就是一定要注意那些在参数中需要真实字节数的API函数调用,如果你传递字符个数给它,它将不能正常工作。如下:

TCHAR data[20];lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!lstrcpyn(data, longstring, DIM(data) - 1); // RIGHTWriteFile(f, data, DIM(data), &bytesWritten, NULL); // WRONG!WriteFile(f, data, sizeof(data), &bytesWritten, NULL); // RIGHT

造成以上原因是因为lstrcpyn需要一个字符个数作为参数,但是WriteFile却需要字节数作为参数。
同样需要注意的是有时候需要写出数据的所有内容。如果你仅仅只想写出数据的真实长度,你可能会认为你应该这样做:

WriteFile(f, data, lstrlen(data), &bytesWritten, NULL); // WRONG

但是在Unicode环境下,它不会正常工作。正确的做法应该是这样:

WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &bytesWritten, NULL); // RIGHT

  因为WriteFile需要的是一个以字节为单位的长度。(可能有些人会想“在非Unicode的环境下运行这行代码,就意味着总是在做一个多余的乘1操作,这样不会降低程序的效率吗?”这种想法是多余的,你必须要了解编译器实际上做了什么,没有哪一个C或C++编译器会把这种无聊的乘1操作留在代码中。在Unicode环境下运行的时候,你也不必担心那个乘2操作会降低程序的效率,记住,这只是一个左移一位的操作而已,编译器也很乐意为你做这种替换。)
  使用_T宏并不是意味着你已经创建了一个Unicode的程序,你只是创建了一个有Unicode意识的程序而已。如果你在默认的8-bit模式下编译你的程序的话,得到的将是一个普通的8-bit的应用程序(这里的8-bit指的只是8位的字符编码,并不是指8位的计算机系统);当你在Unicode环境下编译你的程序时,你才会得到一个Unicode的程序。记住,CString 在 Unicode 环境下,里面包含的可都是16位的字符哦。

3、CString 型转化成 int 型

  把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。
  虽然通常你怀疑使用_atoi()函数是一个好的选择,它也很少会是一个正确的选择。如果你准备使用 Unicode 字符,你应该用_ttoi(),它在 ANSI 编码系统中被编译成_atoi(),而在 Unicode 编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol(),它们都能把字符串转化成任意进制的长整数(如二进制、八进制、十进制或十六进制),不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。看下面的例子:

CString hex = _T("FAB");CString decimal = _T("4011");ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));
软件开发中几个常用功能的实现(转)
发现有些作用,所以转载过来. 

在进行软件开发过程中间,有很多小功能的实现,虽然这些东西你可以不用,但是如果应用仂将会是你的程序更具有专业性。

一、设置程序自动运行。

  很多监控软件要求软件能够在系统重新启动后不用用户去点击图标启动项目,而是直接能够启动运行,方法是写注册表Software//Microsoft//Windows//CurrentVersion//Run。参考程序可以见下:(查找程序目录的执行文件,存在则进行添加注册表操作)

HKEY RegKey;
         CString sPath;
         GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
         sPath.ReleaseBuffer();
         int nPos;
    nPos=sPath.ReverseFind('//');
    sPath=sPath.Left(nPos);
    CString lpszFile=sPath+"//****.exe";//这里加上你要查找的执行文件名称
    CFileFind fFind;
    BOOL bSuccess;
    bSuccess=fFind.FindFile(lpszFile);
    fFind.Close();
    if(bSuccess)
    {
        CString fullName;
        fullName=lpszFile;
        RegKey=NULL;
        RegOpenKey(HKEY_LOCAL_MACHINE,"Software//Microsoft//Windows//CurrentVersion//Run",&RegKey);
        RegSetValueEx(RegKey,"*****",0,REG_SZ,(const unsigned char*)(LPCTSTR)fullName,fullName.GetLength());//这里加上你需要在注册表中注册的内容
        this->UpdateData(FALSE);
    }
    else
    {
        theApp.SetMainSkin();
        ::AfxMessageBox("没找到执行程序,自动运行失败");
        exit(0);
    }

二、自动配置数据源

  很多的程序都要用到数据库结合的操作,这里举例ACCESS,因为ACCESS在中小型VC系统开发中是最常用到的,如果程序的移植,如果对于很初级的用户来说,你还需要他到配置面板中进行数据源配置的话,那就有点说不过去了。

#include <odbcinst.h>
         //配置数据源,数据库在应用程序目录下,这里比如数据库文件名为***.mdb,程序运行时候可以将数据库文件拷贝到程序目录下面。
    CString sPath;
    GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH);
    sPath.ReleaseBuffer();
    int nPos;
    nPos=sPath.ReverseFind('//');
    sPath=sPath.Left(nPos);
    CString lpszFileName = sPath + "//***.mdb";//这里修改成你的数据库文件名称
    CFileFind  fFind;
    if(!fFind.FindFile(lpszFileName))
    {
        ::AfxMessageBox("没有找到数据库");
        exit(0);
    }
    CString szDesc;
    szDesc.Format( "DSN=****;Description=****;DESCRIPTION=The DataBase For ***;FIL=MicrosoftAccess;DEFAULTDIR=%s;DBQ=%s;" ,sPath,lpszFileName);//这里***号可以添加成你的描述

//添加数据源
    if(!::SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft Access Driver (*.mdb)",(LPCSTR)szDesc))
    {
        ::AfxMessageBox("32位ODBC数据源配置错误!");
        exit(0);
    }

三、设置显示模式:

  很多的程序的移植的运行环境是改变的。有可能你的原来开发环境是1024X768,但是到了那些显示器大于17的时候(分辨率超过你的开发时的分辨率时),程序的显示可能就不好看了。

DEVMODE lpDevMode;
    lpDevMode.dmPelsHeight=768;//Y方向象素点
    lpDevMode.dmPelsWidth=1024;//X方向象素点
    lpDevMode.dmDisplayFrequency=85;//屏幕刷新率
    lpDevMode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
    ChangeDisplaySettings(&lpDevMode,0);

四、在你的程序中间加载其他应用程序:

  你的程序除了调用到各个模块进行协同工作外(DLL),还有可能调用不是同一个开发环境下的应用程序,比如VC环境下调用DELPHI,VB开发的执行程序,你就可以用到下面的方法(将调用的应用程序拷贝程序目录中):

CString sPath;
    GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH);
    sPath.ReleaseBuffer();
    int nPos;
    nPos=sPath.ReverseFind('//');
    sPath=sPath.Left(nPos);
    CString lpszFileName = sPath + "//***.exe";//这里修改成你的调用应用程序的文件名称
    CFileFind  fFind;
    if(!fFind.FindFile(lpszFileName))
    {
        ::AfxMessageBox("没有找到调用的应用程序!");
        return FALSE;
    }
    else
        ShellExecute(NULL,NULL,_T("***.exe"),NULL,sPath,NULL);

五、结束进程:

  在你的程序中结束别的程序进程,采用的方法是进行进程列举,然后采用查找的方法进行:

#include "TLHELP32.H"
         DWORD ProcessID[50];
    CString kkk[50];
    HANDLE SnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32* info=new PROCESSENTRY32;
    PROCESSENTRY32 ProcessInfo;//声明进程信息变量
    ProcessInfo.dwSize=sizeof(ProcessInfo);//设置ProcessInfo的大小
    //返回系统中第一个进程的信息
    BOOL Status=Process32First(SnapShot,&ProcessInfo);
    int m_nProcess=0;
    while(Status)
    {
        CString s,str1,str2;
        s.Format("%d",ProcessInfo.cntThreads);
        str1.Format("%s",ProcessInfo.szExeFile);
        str1=ProcessInfo.szExeFile;
        kkk[m_nProcess]=ProcessInfo.szExeFile;
        ProcessID[m_nProcess]=ProcessInfo.th32ProcessID;
        if(str1=="***.exe")//***.exe就是你要结束的进程的名称
        {
            HANDLE ProcessHandle;
            ProcessHandle=OpenProcess (PROCESS_ALL_ACCESS,FALSE,ProcessID[m_nProcess]);
            TerminateProcess(ProcessHandle,0);    
        }
        Status=Process32Next(SnapShot,&ProcessInfo);
        m_nProcess++;
    }

出处:vchelp.net
  责任编辑:leelee

[04-8-12 10:01] 作者:戚高
posted @ 2006-12-06 14:33 ESHIDA 阅读(68) | 评论 (0) | 编辑 收藏

2006年11月30日 #

使用CTimeSpan进行时间比较
今天遇到一个两个CTime时间进行比较的问题
开始我把CTime 转成year,month,day,hour....
进行比较,
后来发现用CTimeSpan可以很容易的比较....

CTime tmr1,tmr2;
tmr1=...
tmr2=//...
CTimeSpan tmr3 = tmr2 - tmr1;
LONGLONG longsum = tmr3.GetToalSecond();
if (longsum < 10 && longsum>-10)
{
    //如果两个时间的秒数相差20秒之内....
}

posted @ 2006-11-30 17:29 ESHIDA 阅读(567) | 评论 (0) | 编辑 收藏

2006年11月29日 #

托盘图标类ShellIcon

我写的最简单的托盘图标管理类
http://www.cppblog.com/Files/EShida/TrayIcon.rar

posted @ 2006-11-29 12:51 ESHIDA 阅读(67) | 评论 (0) | 编辑 收藏

2006年11月24日 #

CString 类的几则技巧
以前做程序遇到的小问题

1. 将CString 转为WCHAR *
    CString str;
     WCHAR * p = str.AllocSysString() ;
  --------or - -----------
   WCHAR *p = CT2W(str);

2. 转为LPCWSTR 
   LPCWSTR strW= T2CW_EX( str, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );

3. 转为char * / LPSTR
   char *p  =  str.GetBuffer(str.GetLength());

4. 转为int
   CString str = "23";
   UINT uint;
   sscanf(str, "%d", uint);

5. 转为LPCTSTR
  LPCTSTR = str; //比较直接 :)

6. 从string建立CString;
  CString str;
  string st;
  str =   st.c_str ()

CString类的转换相关推荐

  1. MFC常用类、成员函数、数组类、Cstring类、CTime类、CPoint类

    MFC数组类CByteArray: CDWordArray: CPtrArray: CUIntArray: CWordArray: CStringArray: 常用成员函数 1.int Add( AR ...

  2. MFC中char*,string和CString之间的转换

    string是使用STL时必不可少的类型,所以是做工程时必须熟练掌握的: char*是从学习C语言开始就已经和我们形影不离的了,有许多API都是以char*作为参数输入的.所以熟练掌握三者之间的转换十 ...

  3. 转:char*, char[] ,CString, string的转换

    转:char*, char[] ,CString, string的转换 (一) 概述 string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准 ...

  4. BSTR、char* 和 CString 之间的转换 (转)

    BSTR.char* 和 CString 之间的转换 (1) char*转换成CString 若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行.例如: c ...

  5. CString类(转)

    CString类功能强大,比STL的string类有过之无不及.新手使用CString时,都会被它强大 的功能所吸引.然而由于对它内部机制的不了解,新手在将CString向C的字符数组转换时 容易出现 ...

  6. MFC中的CString类使用方法指南

    MFC中的CString类使用方法指南 原文出处:codeproject:CString Management [禾路:这是一篇比较老的资料了,但是对于MFC的程序设计很有帮助.我们在MFC中使用字符 ...

  7. CString char BSTR 转换

    一.CString, int, string, char*之间的转换 string 转 CString CString.Format("%s", string.c_str()); ...

  8. VC++开发学习一(MFC中的CString类的常用的方法技巧介绍)

    ①.CString 类对象的初始化: CString str; CString str1(_T("abc")); CString str2 = _T("defg" ...

  9. Visual Studio/MFC编程入门之MFC常用类:CString类

    上一节讲了分割窗口的有关知识,本节开始讲解MFC的一些常用类,先来说说CString类.在内容开始前为大家介绍一款MFC界面开发控件: Xtreme Toolkit Pro | 免费下载:是屡获殊荣的 ...

最新文章

  1. linux 内核阻塞,linux内核阻塞IO
  2. springMVC 处理json 及 HttpMessageConverter 接口
  3. [Lintcode]41. Maximum Subarray/[Leetcode]53. Maximum Subarray
  4. maven-compiler-plugin 找不到 rt.jar
  5. python上传文件到onedrive_基于Python的onedrive文件本地化浏览系统–PyOne
  6. Command 模式 Step by Step
  7. NSTimer--转
  8. vmware vcenter orchestrator configuration提示“用户名密码错误或登录失败超过次数被锁定”...
  9. 算法与数据结构1800题 树和二叉树
  10. C++排列组合及应用
  11. (附源码)计算机毕业设计SSM基于远程协作的汽车故障诊断系统
  12. CG CTF RE Py交易
  13. solidity的函数修改器(modifier)
  14. birthday中文是什么_birthday是什么意思_birthday在线翻译_英语_读音_用法_例句_海词词典...
  15. ElasticSearch_高级_(集群+分片)
  16. 信息化时代下,企业面临的5个数据安全威胁
  17. Mathematica基础及应用
  18. MATLAB帝国(主义)竞争算法求解超市物流配送选址问题实例
  19. 金山毒霸服务器2008系统,金山毒霸可以在服务器系统上安装吗
  20. 【PaddlePaddle】使用高层API导入、导出模型

热门文章

  1. python小课骗局-python小课值吗
  2. 有必要学python吗-学习Python有必要去培训机构吗?
  3. python解释器运行代码-python解释器怎么运行
  4. python 模拟浏览器下载文件-Python 模拟浏览器 获取SVN 文件
  5. python编程难吗-Python、C+这些编程语言难吗?十岁女孩告诉你答案
  6. 学会python之后-【一点资讯】学会Python后,人生简直开挂了!
  7. python课程怎么样-python课程体系是怎么样的?
  8. python语言入门电子版-python从入门到精通pdf
  9. 自学python可以找到好的工作吗-通过自学python能找到工作吗
  10. python正则表达式语法-python正则表达式语法大全讲解教程实例一