BSTR VC++
VC转换格式
CString ,BSTR ,LPCTSTR之间关系和区别CString是一个动态TCHAR数组,BSTR是一种专有格式的字符串(需要用系统提供的函数来操纵,LPCTSTR只是一个常量的TCHAR指针。
CString 是一个完全独立的类,动态的TCHAR数组,封装了 + 等操作符和字符串操作方法。
typedef OLECHAR FAR* BSTR;typedef const char * LPCTSTR;vc++中各种字符串的表示法首先char* 是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。
LP的含义是长指针(long pointer)。
LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。
而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。
1.LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的.2.C表示const3.T是什么东西呢,我们知道TCHAR在采用Unicode方式编译时是wchar_t,在普通时编译成char.为了满足程序代码国际化的需要,业界推出了Unicode标准,它提供了一种简单和一致的表达字符串的方法,所有字符中的字节都是16位的值,其数量也可以满足差不多世界上所有书面语言字符的编码需求,开发程序时使用Unicode(类型为wchar_t)是一种被鼓励的做法。
LPWSTR与LPCWSTR由此产生,它们的含义类似于LPSTR与LPCSTR,只是字符数据是16位的wchar_t而不是char。
然后为了实现两种编码的通用,提出了TCHAR的定义:如果定义_UNICODE,声明如下:typedef wchar_t TCHAR;如果没有定义_UNICODE,则声明如下:typedef char TCHAR;LPTSTR和LPCTSTR中的含义就是每个字符是这样的TCHAR。
C语言_bstr_t和CComBSTR
C语言_bstr_t和CComBSTRbstr_t在VC中是为了兼容BSTR类型而增加的,也就是为了实现LPCSTR与BSTR转换。
它需要头文件#includebstr_t 是BSTR的包装类转换方法LPSTR strDemo="Test";bstr_t bstr(strDemo);建议加上try,catch,用于catch(_com_error &e)The following pseudocode shows the typical use of CComBSTR:HRESULT CMyObject::MyMethod(IOtherObject* pSomething){CComBSTR bstrText(L"Hello");bstrText += " again"; // LPCSTR conversionbstrText.ToUpper();pSomething->Display(bstrText); // [in] parameterMessageBoxW(0, bstrText, L"Test", MB_OK); // Assumes Windows NT}As you can see, CComBSTR significantly simplifies the use of BSTRs. Four uses of CComBSTR, however, require special care:Freeing the BSTR explicitlyUsing CComBSTR as an [out] parameterUsing a CComBSTR automatic variable in right-side assignmentsUsing a CComBSTR member variable in right-side assignments当在BSTR*所在的位置作为一个[out]参数传递CComBSTR时,你必须先调用Empty 释放string的内容,就象下面这样:HRESULT CMyObject::MyMethod2(ISomething* p, /*[out]*/ BSTR* pbstr){CComBSTR bstrText;bstrText = L"Some assignment"; // BSTR is allocated.bstrText.Empty(); // Must call empty beforepSomething->GetText(&bstrText); // using as an [out] parameter.if(bstrText != L"Schaller")bstrText += "Hello"; // Convert from LPCSTR.}因为在重写BSTR内容之前方法COM 为[out] 参数的规则是并不调用sysfreestring。
_bstr_t 类型,BSTR类型和CString类型到底有什么区别
bstr_t类型到底是类型呢?用的时候也可以直接_bstr_t bstr="abcd";还可以_bstr_t bstr="abcd";CString str=(char *)bstr;//_bstr_t莫非是指针?指针可以赋常量字符串?我在ADO数据库编程中用如下语句:CString str=(m_RecordSet->GetCollect("Name")).bstrV al;//m_RecordSet是_RecordsetPtr类型(m_RecordSet->GetCollect("Name")).bstrV al是BSTR类型说明BSTR可以直接赋给CString类型,从编译器中得知BSTR是unsigned short*类型,怎么可以直接赋给CString对象呢?实在不清楚这三个的本质区别,请高手指点!网友回复:CString str=(char *)bstr;//_bstr_t莫非是指针?指针可以赋常量字符串?\_bstr_t有这几个成员operator const wchar_t*( ) const throw( );operator wchar_t*( ) const throw( );operator const char*( ) const;operator char*( ) const;网友回复:我搜集的资料:May this can help you.7.关于CString和其他一些自动化类型的相互转换问题.未参考的资源: 在各种字符串类型之间进行转换/zh-cn/library/ms235631.aspx类型类别:CString ,V ARIANT,BSTR,_t_btr,等预备知识:BSTR:根据MSDN,他的内部结构为:4字节的长度前缀(字节单位),字符串(宽),2字节结束标志0x0000.平常的BSTR是指向字符串的第一字节,并非前缀.比如定义BSTR myBstr=L”I am a happy BSTR”,这样其实不正确,并没有正确生成前缀.应该这样: BSTR MyBstr = SysAllocString(L"I am a happy BSTR");这样就会在内存分配时就会加上前缀和结束标志.BSTR(Basic STRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。
vc获取机器码
NULL, // Default COM authentication settings
EOAC_NONE, // No special options
WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumObject);
ULONG uCount = 1, uReturned;
IWbemClassObject * pClassObject = NULL;
hRes = pEnumObject->Reset();
CString disID = GetCpuID(L"select * from Win32_DisplayConfiguration", L"Caption");
}
CLSID_WbemAdministrativeLocator,
NULL ,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER ,
IID_IUnknown ,
( void ** ) & pIWbemLocator
) ;
if (SUCCEEDED(hRes))
CString strCpuID = GetCpuID(L"select * from Win32_Processor", L"ProcessorId");
CString hardDiskID = GetCpuID(L"select * from Win32_DiskDrive", L"SerialNumber");
vc串口通讯控件MSComm编程详解
vc串口通讯控件MSComm编程详解在mfc中进行串口通讯最简单的方法莫过于在对话框中使用MSCOMM控件了,MSComm通信控件提供了一系列标准通信命令的接口,它允许建立串口连接,可以连接到其他通信设备(如Modem).还可以发送命令、进行数据交换以及监视和响应在通信过程中可能发生的各种错误和事件,从而可以用它创建全双工、事件驱动的、高效实用的通信程序。
一、用MSComm控件通信1.串口通信基础知识一般悦来,计算机都有一个或多个串行端口,它们依次为com1、Com2、…,这些串口还提供了外部设备与pC进行数据传输和皿信的通道。
这些串口在CPU和外设之间充当解释器的角色。
当字符数据从CPU 发送给外设时,这些字符数据将被转换成串行比特流数据;当接收数据时,比特流数据被转换为字符数据传递给CPU,再进一步说,在操作系统方面,Windows用通信驱动程序(COMM.DRV)调用API函数发送和接收数据,当用通信控件或声明调用API函数时,它门由COMM. DRV解释并传递给设备驱动程序,作为一个vB程序员,要编写通信程序.只需知道通信控件提供给Windows通信AP1函数的接口即可.换句话说,只需设定和监视通信控件的属性和事件即可。
2.使用Mscomm控件在开始使用MSComm控件之前。
需要先了解其属性、事件或错误属性描述CommPort 设置或返回通信端口号Settings 以字符串的形式设置或返回波特率、奇偶校验、数据位和停止位PortOpen 设置或返回通信端口的状态。
也可以打开和关闭端口Input 返回和删除接收缓冲区中的字符Output 将字符串写入发送缓冲区CommEvent属性为通信事件或错误返回下列值之一。
在该控件的对象库中也可以找到这些常量。
常量值描述ComEventBreak 1001 收到了断开信号ComEventCTSTO 1002 Clear To Send Timeout。
如何利用VC自动生成
如何利用VC自动生成随着科技的不断发展,越来越多的智能化工具开始进入我们的生活。
其中,VC(Virtual Copywriter)自动生成文章的工具越来越受到欢迎。
VC可以根据用户输入的关键词和需求,自动地生成具有逻辑清晰、结构合理、语言流畅的文章,大大节省了撰写文章的时间和精力。
首先,我们需要根据具体的关键词和需求确定文章的主题。
例如,如果我们要写一篇关于“如何提高免疫力”的文章,那么关键词就可以是“免疫力、健康、锻炼、饮食”等。
然后,我们需要选择一个适合的模板和格式,以便更好地呈现文章的内容。
接下来,我们就可以利用VC自动生成文章了。
对于每个关键词,VC 都会自动地生成一个独立的段落。
例如,对于“免疫力”这个关键词,VC可能会生成以下段落:“免疫力是指身体对疾病的抵抗力,可以通过锻炼和饮食等方式来提高。
”在这个段落中,不仅包含了关键词“免疫力”,还介绍了提高免疫力的方法和意义。
然后,我们可以将这些段落按照需要的顺序进行排版。
例如,我们可以将关于“免疫力”的段落放在文章开头,将关于“健康”的段落放在中间,将关于“锻炼”和“饮食”的段落放在结尾。
通过这种方式,我们可以轻松地完成一篇结构合理、逻辑清晰的文章。
总之,VC自动生成文章的工具可以帮助我们快速生成文章,提高工作效率。
我们也需要注意一些问题。
例如,VC生成的段落可能不够自然,有些表达可能不太符合中文的习惯。
因此,我们需要在VC生成的基础上,进行一些手动修改和调整,以确保文章的质量。
引言:随着现代技术的不断发展,越来越多的计算机软件开始采用自动化文档生成技术,以减轻人工编写文档的负担,提高工作效率。
其中,VC++是一种广泛使用的编程语言和开发工具,具有高度的可操作性和灵活性。
本文将探讨如何使用VC++自动生成Word文档,并介绍相关的关键技术和处理方法。
背景知识:VC++是一种由Microsoft开发的面向对象的编程语言和集成开发环境(IDE)。
关于VC中的字符串
关于VC中的字符串一. 字符类型和字符串(1) char,wchar_t,CHAR,BYTE,UCHAR,WCHAR,TCHAR,TBYTEchar 是C语言标准数据类型,字符型,至于由几个字节组成通常由编译器决定,一般一个字节。
wchar_t 是char的Unicode版本。
相当于unsigned short。
一般两个字节。
CHAR 和WCHAR分别是char和wchar_t的别名,决不会等同。
TCHAR 是两面派,在当前编译方式为Unicode时等价于WCHAR,而ANSI(默认)方式时又等价于CHAR。
BYTE 和UCHAR都相当于unsigned char,在取得字符编码(00~FF)的时候非常有用。
TBYTE 也是两面派,在当前编译方式为Unicode时等价于WCHAR,而ANSI(默认)方式时又等价于BYTE。
(2) PSTR,PWSTR,PCSTR,PCWSTR,LPSTR,LPWSTR,LPCSTR,LPCWSTRtypedef CHAR *PSTR;typedef WCHAR *PWSTR;typedef CONST CHAR *PCSTR;typedef CONST WCHAR *PCWSTR;typedef CHAR *LPSTR;typedef WCHAR *LPWSTR;typedef __nullterminated CONST CHAR *LPCSTR;typedef CONST WCHAR *LPCWSTR;(3) PTSTR,LPTSTR,PCTSTR,LPCTSTR在ANSI编译方式下,PTSTR和LPTSTR等价于LPSTR,在Unicode下等价于LPWSTR。
在ANSI编译方式下,PCTSTR和LPCTSTR等价于LPCSTR,在Unicode下等价于LPCWSTR。
(4) CStringA,CStringW,CString,XCHAR,YCHAR,PXSTR,PYSTR,PCXSTR,PCYSTRCstringA是由CHAR组成的字符串CStringW是由WCHAR组成的字符串CString是由TCHAR组成的字符串XCHAR表示和字符串组成字符相同的字符,YCHAR表示和字符串组成字符不同的字符PXSTR表示和字符串组成字符相同的字符串,PYSTR表示和字符串组成字符不同的字符串PCXSTR表示和字符串组成字符相同的CONST字符串,PCYSTR表示和字符串组成字符不同的CONST字符串(5) BSTR OLECHAR这两个和OLE以及COM技术有关,面向32位系统。
CString,int,string,char,BSTR之间的转换
一.CString, int, string, char*之间的转换string 转CStringCString.Format("%s", string.c_str());char 转CStringCString.Format("%s", char*);char 转stringstring s(char *);string 转char *char *p = string.c_str();CString 转stringstring s(CString.GetBuffer());1.string -> CStringCString. Format("%s", string.c_str());用c_str()确实比data()要好.2.char -> stringstring s(char *);你的只能初始化,在不是初始化的地方最好还是用assign().3.CString -> stringstring s(CString.GetBuffer());GetBuffer()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间.《C++标准函数库》中:有三个函数可以将字符串的内容转换为字符数组和C—string1.data(),返回没有”\0“的字符串数组2.c_str(),返回有”\0“的字符串数组3.copy()CString 和int互转将字符转换为整数,可以使用atoi、_atoi64或atol.将数字转换为CString变量,可以使用CString的Format函数。
如(1)CString s;int i = 64;s.Format("%d", i)Format函数的功能很强,值得你研究一下。
(2)void CStrDlg::OnButton1(){// TODO: Add your control notification handler code hereCString ss="1212.12";int temp=atoi(ss); //字符转换为整数CString aa;aa.Format("%d",temp); //整数转换为字符AfxMessageBox("var is " + aa);}CString和char*互转(1)char * -> CStringCString strtest;char * charpoint;charpoint="give string a value";strtest=charpoint;(2)CString -> char *charpoint=strtest.GetBuffer(strtest.GetLength());标准C里没有string,char *==char []==string可以用CString.Format("%s",char *)这个方法来将char *转成CString。
vc中数据的转换
WORD wReserved3;
union {
ULONGLONG ullVal; /* VT_UI8 */
首页 资讯 空间 学生 论坛 博客 下载 读书 网摘 程序员 外包 商城 书店 网址 CTO 乐知教育 D9区
qipnx的专栏
条新通知 登录 注册 欢迎 退出 我的博客 配置 写文章 文章管理 博客首页 全站 当前博客 空间 博客 好友 相册 留言 用户操作
[留言] [发消息] [加为好友]
CY cyVal; /* VT_CY */
DATE date; /* VT_DATE */
BSTR bstrVal; /* VT_BSTR */
LONGLONG * pllVal; /* VT_BYREF|VT_I8 */
FLOAT * pfltVal; /* VT_BYREF|VT_R4 */
DOUBLE * pdblVal; /* VT_BYREF|VT_R8 */
IUnknown ** ppunkVal; /* VT_BYREF|VT_UNKNOWN */
IDispatch ** ppdispVal; /* VT_BYREF|VT_DISPATCH */
SAFEARRAY ** pparray; /* VT_BYREF|VT_ARRAY */
IUnknown * punkVal; /* VT_UNKNOWN */
IDispatch * pdispVal; /* VT_DISPATCH */
SAFEARRAY * parray; /* VT_ARRAY */
USHORT uiVal; /* VT_UI2 */
ULONG ulVal; /* VT_UI4 */
char,CHAR,TCHAR,LPSTR,LPCSTR,WCHAR ,CString
char是C语言标准数据类型,字符型,至于由几个字节组成通常由编译器决定,一般一个字节。
Windows为了消除各编译器的差别,重新定义了一些数据类型。
CHAR为单字节字符。
还有个WCHAR为Unicode字符,即不论中英文,每个字有两个字节组成。
如果当前编译方式为ANSI(默认)方式,TCHAR等价于CHAR,如果为Unicode方式,TCHAR等价于WCHAR。
LPCSTR 相当于CONST CHAR * 和LPSTR 相当于CHAR *。
TCHAR 与Char的区别:TCHAR是通过条件宏定义定义出来的类型。
如果定义了_UNICODE,TCHAR就是wchar_t,即unsigned short,否则,TCHAR就是char。
char,TCHAR,WCHAR区别#ifdef UNICODEtypedef wchar_t TCHAR;#elsetypedef unsigned char TCHAR;#endiftypedef unsigned char CHAR;typedef unsigned wchar_t WCHAR;由此可以看出,CHAR实施上就是unsigned char,WCHAR为宽字符,而TCHAR根据是否支持unicode而不同。
在程序使用sizeof(TCAHR),当默认设置时,这个值是1;当定义UNICODE宏时,这个值是2。
另外:CString与char之间的转换:char *buf;CString str=_T("renjingwei");buf=str.GetBuffer(10);另外给出MSDN中各个变量说明:BOOL A Boolean value.//这个BOOL和bool是有区别的,BOOL是个宏定义,是0或1(TRUE OR FALSE);而bool是布尔类型,可以是true or falsechar是C语言标准数据类型,字符型,至于由几个字节组成通常由编译器决定,一般一个字节。
VC++中数据类型转换大全
vc数据类型转换大全(转载)int i = 100;long l = 2001;float f=300.2;double d=12345.119;char username[]=”程佩君”;char temp[200];char *buf;CString str;_variant_t v1;_bstr_t v2;一、其它数据类型转换为字符串短整型(int)itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制itoa(i,temp,2); ///按二进制方式转换长整型(long)ltoa(l,temp,10);浮点数(float,double)用fcvt可以完成转换,这是MSDN中的例子:int decimal, sign;char *buffer;double source = 3.1415926535;buffer = _fcvt( source, 7, &decimal, &sign );运行结果:source: 3.1415926535 buffer: ‘31415927′ decimal: 1 sign: 0decimal表示小数点的位置,sign表示符号:0为正数,1为负数CString变量str = “2008北京奥运”;buf = (LPSTR)(LPCTSTR)str; //这个因为buf是个char*变量先把CString 变量转换为const char*类型的再变为char*类型的上面的CString转换为char*型号的必须经过两次反之的直接赋值就可以BSTR变量BSTR bstrValue = ::SysAllocStri ng(L”程序员”);char * buf = _com_util::ConvertBSTRToString(bstrValue); SysFreeString(bstrValue);一定注意凡是定义的指针变量一定要用delete显示删除AfxMessageBox(buf);delete(buf);CComBSTR变量CComBSTR bstrVar(”test”);char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str); AfxMessageBox(buf);delete(buf);_bstr_t变量_bstr_t类型是对BSTR的封装,因为已经重载了=操作符,所以很容易使用_bstr_t bstrVar(”test”);const char *buf = bstrVar;///不要修改buf中的内容_bstr_t实际上是个字符指针型的AfxMessageBox(buf);通用方法(针对非COM数据类型)用sprintf完成转换char buffer[200];char c = ‘1′;int i = 35;long j = 1000;float f = 1.7320534f;sprintf( buffer, “%c”,c);sprintf( buffer, “%d”,i);sprintf( buffer, “%d”,j);sprintf( buffer, “%f”,f);二、字符串转换为其它数据类型strcpy(temp,”123″);短整型(int)i = atoi(temp);长整型(long)l = atol(temp);浮点(double)d = atof(temp);CString变量CString name = temp;BSTR变量BSTR bstrValue = ::SysAllocString(L”程序员”);…///完成对bstrValue的使用SysFreeString(bstrValue);CComBSTR变量CComBSTR类型变量可以直接赋值CComBSTR bstrVar1(”test”);CComBSTR bstrVar2(temp);_bstr_t变量_bstr_t类型的变量可以直接赋值_bstr_t bstrVar1(”test”);_bstr_t bstrVar2(temp);三、其它数据类型转换到CString使用CString的成员函数Format来转换,例如:整数(int)str.Format(”%d”,i);浮点数(float)str.Format(”%f”,i);字符串指针(char*)等已经被CString构造函数支持的数据类型可以直接赋值str = username;对于Format所不支持的数据类型,可以通过上面所说的关于其它数据类型转化到char*的方法先转到char *,然后赋值给CString变量。
浅谈c++字符类型总结区别wchar_t,char,WCHAR
浅谈c++字符类型总结区别wchar_t,char,WCHAR1、区别wchar_t,char,WCHARANSI:即 char,可⽤字符串处理函数:strcat( ),strcpy( ), strlen( )等以str打头的函数。
UNICODE:wchar_t是Unicode字符的数据类型,它实际定义在⾥:typedef unsigned short wchar_t;另外,在头⽂件中有这样的定义:typedef wchar_t WCHAR; 所以WCHAR实际就是wchar_twchar_t 可⽤字符串处理函数:wcscat(),wcscpy(),wcslen()等以wcs打头的函数。
为了让编译器识别Unicode字符串,必须以在前⾯加⼀个“L”,例如: wchar_t *szTest=L"This is a Unicode string.";2、TCHAR在C语⾔⾥⾯提供了 _UNICODE宏(有下划线),在Windows⾥⾯提供了UNICODE宏(⽆下划线),只要定了_UNICODE 宏和UNICODE宏,系统就会⾃动切换到UNICODE版本,否则,系统按照ANSI的⽅式进⾏编译和运⾏。
只定义了宏并不能实现⾃动的转换,他还需要⼀系列的字符定义⽀持。
1. TCHAR如果定义了UNICODE宏则TCHAR被定义为wchar_t。
typedef wchar_t TCHAR;否则TCHAR被定义为char typedef char TCHAR;2. LPTSTR如果定义了UNICODE宏则LPTSTR被定义为LPWSTR。
typedef LPTSTR LPWSTR;否则TCHAR被定义为char typedef LPTSTR LPSTR;说明:在使⽤字符串常量的时候需要使⽤_TEXT(“MyStr”)或者_T("")来⽀持系统的⾃动转换。
3、BSTRBSTR是⼀个带长度前缀的字符串,主要由操作系统来管理的,所以要⽤api.主要⽤来和VB打交道的(VB⾥的string就是指它)要操作它的API函数有很多.⽐如SysAllocString,SysFreeString等等.vc⾥封装它的类如_bstr_t,及ATL中的CComBSTR等.⼀个 BSTR 由头部和字符串组成,头部包含了字符串的长度信息,字符串中可以包含嵌⼊的 null 值。
VC++ BSTR 处理
1How to use BSTR1.1BSTR分析BSTR设计对于C++程序员好坏参半。
一方面,BSTR可以被用于大多数需要OLECHAR 数组作为参数的函数。
另一方面,不能用熟悉的C/C++函数进行对BSTR的分配、释放和处理,例如malloc, free, new, delete, lstrcat, and lstrlen 等函数不能用于处理BSTR。
就像对接口指针和类指针的处理不一样,对BSTR的处理和对TCHAR*的处理也不一样。
B STR是一种C语言方式的类型定义方式,这种定义方式提高了BSTR在C++的应用效率,但是也带来了很多的潜在风险,它使程序员失去了利用编译器检查潜在问题的机会。
1.2BSTR使用基本规则∙在对BSTR进行读取操作的时候,可以把BSTR看作OLECHAR数组。
BSTR可以用于c onst wchar_t*(LPCTSTR/ LPCWSTR/ cosnt TCHAR*/ cosnt WCHAR* in Unicode project),不能用于需要wchar_t* (LPTSTR/ LPWSTR/ TCHAR*/ WCHAR* inUnicode project)的地方。
∙如果有相应的BSTR处理函数,必须使用BSTR处理函数,不要使用普通字符串函数。
特别是一个BSTR包含多个字符串(也就是,包含多个0结束符)的情况。
在对BSTR进行修改(包括创建和释放时),必须使用BSTR的专用函数。
主要要保证对字符长度前缀的的长度域,应该使用BSTR处理函数计算长度。
正确修改。
不要直接读取BSTR∙NULL是BSTR的有效值。
按照约定,它可以被看作含有0个字符的字符串。
BSTR变量必须等于NULL,或者正确分配的BSTR指针。
在改变BSTR变量的之前,必须释放原来指向的BSTR。
不要把BSTR直接初始化成常量字符指针,例如,BSTR bs = L””。
∙Automation会cache BSTR使用的空间,以提高SysAllocString/SysFreeString 的性能,会给测试发现问题带来困难。
VC++常用数据类型
VC++常用数据类型在Visual C++.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。
之所以出现类似上述的这些数据类型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。
那么什么是BSTR、LPSTR以及LPWSTR呢?BSTR(Basic STRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。
它被描述成一个与自动化相兼容的类型。
由于操作系统提供相应的API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种场合下得到广泛使用。
图1描述了BSTR的结构,其中DWORD值是字符串中实际所占用的字节数,且它的值是字符串中Unicode字符的两倍。
LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。
LPSTR被定义成是一个指向以NULL(‘/0’)结尾的8位ANSI 字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。
在VC++中,还有类似的字符串类型,如LPTSTR、LPCTSTR等,它们的含义如图2所示。
例如,LPCTSTR是指“long pointer to a constant generic string”,表示“一个指向一般字符串常量的长指针类型”,与C/C++的const char*相映射,而LPTSTR映射为char*。
一般地,还有下列类型定义:#ifdef UNICODEtypedef LPWSTR LPTSTR;typedef LPCWSTR LPCTSTR;#elsetypedef LPSTR LPTSTR;typedef LPCSTR LPCTSTR;#endif二、CString、CStringA 和CStringWVisual C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。
CString的Format方法使用技巧小结
CString的Format方法使用技巧小结CString的Format方法使用技巧小结在VC中经常用到Format()来输出一个特定类型的变量到窗口上,该函数使用起来比较方便,但是如果对其函数中的参数不很熟悉的话用起来也是比较麻烦的。
因此,归纳了一下,以供大家查询之用:1).格式说明格式说明总是以%字符开始,以不同类型数据的格式方式%号:%d输出带符号十进制数%o输出无符号八进制数%x输出无符号十六进制数%u输出无符号数%c输出单个字符%s输出一串字符%f输出实数(6位小数)%e以指数形式输出实数%g选用f与e格式中输出宽度较小的格式,不输出0%ld输入输出long型数据%lf输入输出double型数据m.n中,m为数据输出宽度,n为输出小数位数比如常见的int、float和double这些数字类型转换为CString字符串只需一行代码就可以实现。
1、int转换为CString:CString str;int number=15;//str="15"str.Format(_T("%d"),number);//str="15"(前面有两个空格;4表示将占用4位,如果数字超过4位将输出所有数字,不会截断)str.Format(_T("%4d"),number);//str="0015"(.4表示将占用4位,如果数字超过4位将输出所有数字,不会截断)str.Format(_T("%.4d"),number);long转换为CString的方法与上面相似,只需要把%d改为%ld 就可以了。
2、double转换为CString:CString str;double num=1.46;//str="1.46"str.Format(_T("%lf"),num);//str="1.5"(.1表示小数点后留1位,小数点后超过1位则四舍五入)str.Format(_T("%.1lf"),num);//str="1.4600"str.Format(_T("%.4f"),num);//str=" 1.4600"(前面有1个空格)str.Format(_T("%7.4f"),num);float转换为CString的方法也同上面相似,将lf%改为f%就可以了。
CString, BSTR, LPCTSTR之间得关系和区别
CString是一個動態TCHAR陣列,BSTR是一種專有格式的字串(需要用系統提供的函數來操縱,LPCTSTR只是一個常量的TCHAR指標。
CString 是一個完全獨立的類,動態的TCHAR陣列,封裝了+ 等操作符和字串操作方法。
typedef OLECHAR FAR* BSTR;typedef const char * LPCTSTR;vc++中各種字串的標記法首先char* 是指向ANSI字元陣列的指標,其中每個字元佔據8位元(有效資料是除掉最高位元的其他7位),這裡保持了與傳統的C,C++的相容。
LP的含義是長指針(long pointer)。
LPSTR是一個指向以…\0‟結尾的ANSI字元陣列的指標,與char*可以互換使用,在win32中較多地使用LPSTR。
而LPCSTR中增加的…C‟的含義是“CONSTANT”(常量),表明這種資料類型的實例不能被使用它的API 函數改變,除此之外,它與LPSTR是等同的。
1.LP表示長指針,在win16下有長指針(LP)和短指針(P)的區別,而在win32下是沒有區別的,都是32位.所以這裡的LP和P是等價的.2.C表示const3.T是什麼東西呢,我們知道TCHAR在採用Unicode方式編譯時是wchar_t,在普通時編譯成char.為了滿足程式碼國際化的需要,業界推出了Unicode標準,它提供了一種簡單和一致的表達字串的方法,所有字元中的位元組都是16位元的值,其數量也可以滿足差不多世界上所有書面語言字元的編碼需求,開發程式時使用Unicode(類型為wchar_t)是一種被鼓勵的做法。
LPWSTR與LPCWSTR由此產生,它們的含義類似於LPSTR與LPCSTR,只是字元資料是16位元的wchar_t而不是char。
然後為了實現兩種編碼的通用,提出了TCHAR的定義:如果定義_UNICODE,聲明如下:typedef wchar_t TCHAR;如果沒有定義_UNICODE,則聲明如下:typedef char TCHAR;LPTSTR和LPCTSTR中的含義就是每個字元是這樣的TCHAR。
VC++实现基于MODBUS协议通信程序
MASTER:static unsigned char auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40} ;static unsigned char auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,0x40} ;unsigned short CRC16(unsigned char* puchMsg, unsigned char usDataLen)/* message to calculate CRC upon *//* quantity of bytes in message */{unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */unsigned uIndex ; /* w ill index into CRC lookup table */while (usDataLen--) /* pass through message buffer */{uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC *///这几条没看明白uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];uchCRCLo = auchCRCLo[uIndex] ;}*puchMsg++ = uchCRCHi;*puchMsg = uchCRCLo;retur n (uchCRCHi << 8 | uchCRCLo) ;}BOOL CSer ialmodbusDlg::OnInitD ialog(){CDialog::OnInitDialog();SetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herem_MSC omm.SetCommPort(1);//在设置选项里的por t值不能初始时未能传递过来m_MSComm.SetInputMode(1);m_MSComm.SetInBufferSize(1024);m_MSComm.SetOutBufferSize(512);m_MSComm.SetR Threshold(1);m_MSComm.SetInputLen(0);m_MSComm.SetSettings("9600,n,8,1");if(!m_MSComm.GetPortOpen())m_MSC omm.SetPortOpen(TRUE);elseMessageBox("打开串口出错");m_MSComm.GetInput();//先预读以清除残留数据retur n TRUE; // return TRUE unless you set the focus to a control}void CSer ialmodbusDlg::open_serial(){if(!m_MSComm.GetPortOpen())m_MSC omm.SetPortOpen(TRUE);//打开串口//应该还有一些后续的操作情形,暂时留待协议能完成之后再行添加}void CSer ialmodbusDlg::close_serial(){if(m_MSC omm.GetPortOpen())m_MSC omm.SetPortOpen(FALSE);}BEGIN_EVEN TSIN K_MAP(CSerialmodbusDlg, CDialog)//{{AFX_EVEN TSINK_MAP(CSerialmodbusDlg)ON_EVEN T(CSerialmodbusDlg, IDC_MSCOMM1, 1 /* OnComm */, OnOnCommMscomm1, VTS_NONE) //}}AFX_EVEN TSINK_MAPEND_EVEN TSINK_MAP()void CSer ialmodbusDlg::OnOnCommMscomm1(){V ARIAN T variant_inp;COleSafeArray safearray_inp;long length,i;BYTE data[4096];unsigned char sendback[8];CStr ing strtemp;CStr ing strDisp;int nEvent=m_MSC omm.GetCommEvent();int k;switch (nEvent)//接收缓冲区内有字符{case 2:k=m_MSComm.GetInBufferCount();if(k>0){variant_inp=m_MSComm.GetInput();//读取缓冲区内的数据safearray_inp=var iant_inp;//将VARIAN T型变量转换为C oleSafeArray型变量length=safearray_inp.GetOneDimSize();//确定数据长度for(i=0;i<length;i++)safearray_inp.GetElement(&i,data+i);//将数据转换为BYTE型数组for(i=0;i<length;i++){BYTE bt=*(char*)(data+i);//字符型*(sendback+i)=*(char*)(data+i);strtemp.Format("%02X",bt);//将字符送入临时变量strtemp存放strDisp+=strtemp;//加入接收编辑框对应字符串}int nlen=m_ctrlEditRec.GetWindowTextLength();m_ctrlEditRec.SetSel(nlen+1,nlen);m_ctrlEditRec.ReplaceSel(strDisp);if(strDisp!="ffff"){C Str ing str_modbus[11];for(i=0;i<11;i++){str_modbus[i]=strDisp.Mid(i*2,2);}CEdit* pedit=(CEdit*)GetD lgItem(IDC_EDIT_DEVICE);pedit->SetW indow Text(str_modbus[0]);CEdit* pedit1=(CEdit*)GetDlgItem(IDC_EDIT_FUNCTION);pedit1->SetWindowText(str_modbus[1]);CEdit* pedit2=(CEdit*)GetDlgItem(IDC_EDIT_FIRST_ADDRESS);pedit2->SetWindowText(str_modbus[2]);CEdit* pedit3=(CEdit*)GetDlgItem(IDC_EDIT_DATA_NUM);pedit3->SetWindow Text(str_modbus[3]+str_modbus[4]+" "+str_modbus[5]+str_modbus[6]+" "+str_modbus[7]+str_modbus[8]);CEdit* pedit4=(CEdit*)GetDlgItem(IDC_EDIT_CHECK_CRC);pedit4->SetWindowText(str_modbus[9]+str_modbus[10]);}else{AfxMessageBox("数据发送有误,请重新发送!");}break;}}}void CSer ialmodbusDlg::OnSendButton()// TODO: Add your control notification handler code heresendbuf();}void CSer ialmodbusDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call default//UpdateData(true);//sendbuf();CDialog::OnTimer(nIDEvent);}void CSer ialmodbusDlg::sendbuf(){unsigned char arr_cmd[] = {0x01,0x03,0x00,0x25,0x00,0x03,0xff,0xff};//arr_cmd[0] = m_nAddress[m_nCurModule-1];unsigned short CRC = CRC16(arr_cmd,6);/*arr_cmd[6] = (unsigned char) CRC;arr_cmd[7]= (unsigned char) (CRC >> 8);*/CStr ing str_cmd(arr_cmd);BSTR bstr_cmd ;bstr_cmd = SysAllocStringByteLen((char*) arr_cmd,8); //分配BSTR资源TRACE("String len of bstr_cmd =%d\n",SysStringByteLen(bstr_cmd));VARIAN T var;Var iantInit(&var); //初始化VARIAN Tvar.vt = VT_BSTR;var.bstrVal = bstr_cmd;//设置BSTR类型和值m_MSComm.SetN ullD iscard(FALSE); //接收时保留NULL字符CByteArray cba_cmd; //使用CByteArray发送字符(因中有字符NULL-0) for(int i=0;i<8;i++){cba_cmd.Add(arr_cmd[i]);}m_MSComm.SetOutput(COleV ariant(cba_cmd));SysFreeStr ing(bstr_cmd);}SLAVE:static unsigned char auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40} ;static unsigned char auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,0x40unsigned short CRC16(unsigned char* puchMsg, unsigned char usDataLen)/* message to calculate CRC upon *//* quantity of bytes in message */{unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */unsigned uIndex ; /* w ill index into CRC lookup table */while (usDataLen--) /* pass through message buffer */{uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC *///这几条没看明白uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];uchCRCLo = auchCRCLo[uIndex] ;}*puchMsg++ = uchCRCHi;*puchMsg = uchCRCLo;retur n (uchCRCHi << 8 | uchCRCLo) ;}BOOL CSer ialmodbus2Dlg::OnInitDialog(){CDialog::OnInitDialog();m_MSComm.SetCommPort(2);//在设置选项里的port值不能初始时未能传递过来m_MSComm.SetInputMode(1);m_MSComm.SetInBufferSize(1024);m_MSComm.SetOutBufferSize(512);m_MSComm.SetR Threshold(1);m_MSComm.SetInputLen(0);m_MSComm.SetSettings("9600,n,8,1");if(!m_MSComm.GetPortOpen())m_MSC omm.SetPortOpen(TRUE);elseMessageBox("打开串口出错");m_MSComm.GetInput();//先预读以清除残留数据retur n TRUE; // return TRUE unless you set the focus to a control}void CSer ialmodbus2Dlg::open_serial(){if(!m_MSComm.GetPortOpen())m_MSC omm.SetPortOpen(TRUE);//打开串口//应该还有一些后续的操作情形,暂时留待协议能完成之后再行添加void CSer ialmodbus2Dlg::close_serial(){if(m_MSC omm.GetPortOpen())m_MSC omm.SetPortOpen(FALSE);}void CSer ialmodbus2Dlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call default//UpdateD ata(true);// Combine(m_device, m_funccode,m_faddress,m_datanum);CDialog::OnTimer(nIDEvent);}BEGIN_EVEN TSIN K_MAP(CSerialmodbus2Dlg, CD ialog)//{{AFX_EVEN TSINK_MAP(CSerialmodbus2Dlg)ON_EVEN T(CSerialmodbus2Dlg, IDC_MSCOMM1, 1 /* OnComm */, OnC omm, VTS_NONE) //}}AFX_EVEN TSINK_MAPEND_EVEN TSINK_MAP()void CSer ialmodbus2Dlg::OnComm(){VARIAN T variant_inp;COleSafeArray safearray_inp;long length,i;BYTE data[4096];unsigned char sendback[100];CStr ing strtemp;CStr ing strDisp;int nEvent=m_MSC omm.GetCommEvent();int k;switch (nEvent)//接收缓冲区内有字符{case 2:k=m_MSComm.GetInBufferCount();if(k>0){variant_inp=m_MSComm.GetInput();//读取缓冲区内的数据safearray_inp=var iant_inp;//将VARIAN T型变量转换为C oleSafeArray型变量length=safearray_inp.GetOneDimSize();//确定数据长度for(i=0;i<length;i++)safearray_inp.GetElement(&i,data+i);//将数据转换为BYTE型数组for(i=0;i<length;i++){BYTE bt=*(char*)(data+i);//字符型*(sendback+i)=*(char*)(data+i);strtemp.Format("%02X",bt);//将字符送入临时变量strtemp存放strDisp+=strtemp;//加入接收编辑框对应字符串}C Str ing str_crc;str_crc.Format("%c%c",sendback[6],sendback[7]);unsigned short CRC = CRC16(sendback,6);C Str ing str_check;str_check.Format("%c%c",sendback[6],sendback[7]);if(str_check==str_crc){int nlen=m_ctrlEditRec.GetWindowTextLength();m_ctrlEditRec.SetSel(nlen+1,nlen);m_ctrlEditRec.ReplaceSel(strDisp);C Str ing str_modbus[8];for(i=0;i<8;i++){str_modbus[i]=strDisp.Mid(i*2,2);}Str ing2Hex(strDisp,sendback);unsigned char arr_cmd[] = {sendback[0],sendback[1],0x06,0x08,0x2C,0x08,0x2A,0x08,0x2C,0xff,0xff};sendbuf(arr_cmd);/* CByteArray cba_cmd; //使用C ByteArray发送字符(因中有字符NULL-0)for(int i=0;i<11;i++){cba_cmd.Add(arr_cmd[i]);}m_MSC omm.SetOutput(COleV ariant(arr_cmd));*/CEdit* pedit=(CEdit*)GetD lgItem(IDC_EDIT_DEVICE);pedit->SetW indow Text(str_modbus[0]);CEdit* pedit1=(CEdit*)GetDlgItem(IDC_EDIT_FUNCTION);pedit1->SetWindowText(str_modbus[1]);CEdit* pedit2=(CEdit*)GetDlgItem(IDC_EDIT_FIRST_ADDRESS);pedit2->SetWindowText(str_modbus[2]+str_modbus[3]);CEdit* pedit3=(CEdit*)GetDlgItem(IDC_EDIT_DATA_NUM);pedit3->SetWindowText(str_modbus[4]+str_modbus[5]);CEdit* pedit4=(CEdit*)GetDlgItem(IDC_EDIT_CHECK_CRC);pedit4->SetWindowText(str_modbus[6]+str_modbus[7]);}else{unsigned char arr_cmd[]={0xff,0xff};CByteArray cba_cmd; //使用CByteArray发送字符(因中有字符NULL-0) for(int i=0;i<2;i++){cba_cmd.Add(arr_cmd[i]);}m_MSComm.SetOutput(COleV ariant(cba_cmd));}}break;}}int CSer ialmodbus2Dlg::Str ing2Hex(CString str, unsigned char senddata[]){int hexdata,lowhexdata;int hexdatalen=0;int len=str.GetLength();//senddata.SetSize(len/2);for(int i=0;i<len;){char lstr,hstr=str[i];if(hstr==' '){i++;continue;}i++;if(i>=len)break;lstr=str[i];hexdata=ConvertHexChar(hstr);lowhexdata=ConvertHexChar(lstr);if((hexdata==16)||(lowhexdata==16))br eak;elsehexdata=hexdata*16+lowhexdata;i++;senddata[hexdatalen]=(char)hexdata;hexdatalen++;}//senddata.SetSize(hexdatalen);retur n hexdatalen;}char CSer ialmodbus2Dlg::ConvertHexC har(char ch){if((ch>='0')&&(ch<='9'))return ch-0x30;else if((ch>='A')&&(ch<='F'))return ch-'A'+10;else if((ch>='a')&&(ch<='f'))return ch-'a'+10;else return (-1);}void CSer ialmodbus2Dlg::sendbuf(unsigned char arr_cm d[]){//unsigned char arr_cmd[] = {0x01,0x03,0x00,0x25,0x00,0x03,0xff,0xff};unsigned short CRC = CRC16(arr_cmd,9);CStr ing str_cmd(arr_cmd);BSTR bstr_cmd ;bstr_cmd = SysAllocStringByteLen((char*) arr_cmd,11); //分配BSTR资源TRACE("String len of bstr_cmd =%d\n",SysStringByteLen(bstr_cmd));VARIAN T var;Var iantInit(&var); //初始化VARIAN Tvar.vt = VT_BSTR;var.bstrVal = bstr_cmd;//设置BSTR类型和值m_MSComm.SetN ullD iscard(FALSE); //接收时保留NULL字符CByteArray cba_cmd; //使用CByteArray发送字符(因中有字符NULL-0) for(int i=0;i<11;i++){cba_cmd.Add(arr_cmd[i]);}m_MSComm.SetOutput(COleV ariant(cba_cmd));SysFreeStr ing(bstr_cmd);}。
VC++ CString的操作
vc中的CString的操作原著:Joseph M. Newcomer翻译:littleloach原文出处:codeproject:CString Management通过阅读本文你能学习怎么有效地使用CString。
CString 是一种非常有用的数据类型。
他们非常大程度上简化了MFC中的许多操作,使得MFC在做字符串操作的时候方便了非常多。
不管怎样,使用CString有非常多特别的技巧,特别是对于纯C背景下走出来的程式员来说有点难以学习。
这篇文章就来讨论这些技巧。
使用CString能让你对字符串的操作更加直截了当。
这篇文章不是CString的完全手册,但囊括了大部分常见基本问题。
这篇文章包括以下内容:CString 对象的连接格式化字符串(包括int 型转化为CString )CString 型转化成int 型CString 型和char* 类型的相互转化char* 转化成CStringCString 转化成char* 之一:使用LPCTSTR强制转化CString 转化成char* 之二:使用CString对象的GetBuffer方法CString 转化成char* 之三: 和控件的接口CString 型转化成BSTR 型;BSTR 型转化成CString 型;V ARIANT 型转化成CString 型;载入字符串表资源;CString 和临时对象;CString 的效率;总结下面我分别讨论。
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类替你完成。
VB中String的用法及原理
VB中String的⽤法及原理在各种不同开发语⾔中,字符串类型显然是最常见,也是最常⽤的。
常⽤代表它最易⽤,是这样吗?未必,越简单,越普通,你会忽视,内⾥隐藏着的陷井更容易使你中招。
它往往是绊脚⽯,或者程序中性能的瓶颈。
本⾝,我对VB语⾔及相关应⽤并不太熟,只不过近期编码⽤到,有些体会。
⼀: 先来总结⼀下,常⽤编程语⾔的字串表达⽅式:C: char(wchat_t) * 或 []: 字符数组来表⽰字符串,以0结尾,⽆长度标识。
配⼀堆操作函数,不好记,不好⽤。
C++: std::string basic_string<>的特化版本. 注意:其内在的数据区由默认的内存管理器分配。
对象哈,提供还算好⽤的⽅法。
MFC: CString 标准的C++类. 数据项:LPTSTR ⼀堆可⽤的⽅法。
Windows普通API DLL: LPTSTR 采⽤C标准的0结束字串Windows扩展COM中: BSTR OLE标准, 头上带长度标识的字符串.中: ;" /> VB中: String 实际上就是OLE标准的BSTR好了,我们关⼼的是BSTR。
看看BSTR到底是什么东东。
1.0:看看在Windows SDK中的定义:typedef OLECHAR* BSTR;typedef WCHAR OLECHAR;typedef wchar_t WCHAR;所以,它实际上是宽字符指针。
1.1:它的内存结构呢?很容易查到资料。
前置四字节,内置字串的长度,后⾯是字串内容,原则上并不以'/0'结尾,长度由前置值决定。
所以,它⼜不简简单单就是宽字符指针。
但从基本类型定义上来看,它与宽字符指针是可以划等号的。
1.2:那VB中的String也就明⽩了。
实际上是地址,是字串的⾸地址(注意:不是长度的⾸地址)另外,String是可以装载中间带'/0'字符的字串的,只不过,⼀些显⽰函数可能将其省略。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1Why need BSTRCOM是一种跨编程语言的平台,需要提供语言无关的数据类型。
多数编程语言有自己的字符串表示。
∙C++ 字符串是以0结束的ASCII或Unicode字符数组∙Visual Basic字符串是一个ASCII字符数组加上表示长度的前缀。
∙Java字符串是以0结束的Unicode字符数组。
需要定义一种通用的字符串类型,可以很容易的匹配到不同编程语言。
在C++中,就是BSTR。
2What is BSTR2.1BSTR 简介"Basic STRing"的简称,微软在COM/OLE中定义的标准字符串数据类型。
对于C++,Windows头文件wtypes.h中定义如下:typedef wchar_t WCHAR;typedef WCHAR OLECHAR;typedef OLECHAR __RPC_FAR *BSTR;;2.2BSTR实现在COM中,字符用16-bit OLECHAR表示,这样使COM可以支持各种code pages,包括Unicode。
对于windows系统,可以简单理解为OLECHAR使用的就是Unicode 。
OLECHAR串与单字节字符串很类似,是一个以null结尾的buffer。
唯一的区别是每个字符占两个字节,而不是一个0 1 2 3 4 5 6 7 8 9 0 1| H | E | L | L | O | \0|^OLCHARFigure 1. Format of an OLECHAR string.使用以Null结尾的简单字符串在COM component间传递不太方便。
因此,标准BSTR是一个有长度前缀和null结束符的OLECHAR数组。
BSTR的前4字节是一个表示字符串长度的前缀。
BSTR长度域的值是字符串的字节数,并且不包括0结束符。
由于是Unicode串,所以字符数是字节数的一半。
这种方式的优点是允许程序员在BSTR串中间嵌入NULL字符。
但是,BSTR的前四个字节表示长度,而OLECHAR数组的前四字节表示前两个字符。
这种情况下,对于C++程序,如何实现BSTR和OLECHAR的交换?答案是COM提供了两个BSTR分配用的API:SysAllocString / SysReallocString。
函数返回的指针指向BSTR的第一个字符,而不是BSTR在内存的第一个字节。
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 50a000000 | H | E | L | L | O | \0|^BSTRFigure 2. Format of a BSTR.下面是SysAllocString和SysFreeString的伪代码。
BSTR SimpleSysAllocString( const OLECHAR * sz)if ( sz == NULL) return NULL;BYTE* buf = new BYTE[sizeof(INT32) + (wcslen(sz)+1)*sizeof(OLECHAR) ];if(buf == NULL){return NULL;}else{INT32 len = wcslen(sz) * sizeof(OLECHAR);*((INT32*) buf) = len;wcscpy( (WCHAR*)(buf+sizeof(INT32)), sz);return (BSTR)(buf+sizeof(INT32));}}VOID SimpleSysFreeString( BSTR bstr){if(bstr != NULL){BYTE* start = (BYTE*)bstr - sizeof(INT32);delete []start;}}3When to use BSTR只有在你不得不用的时候。
使用BSTR一般有以下几种情况:∙COM interface接口定义,并且不希望额外提供custom marshaling库(MDIL生成或开发人员自己订制),必须使用BSTR传递字符串。
使用C/C++类型的字符串在COM DLL传递字符串,表面上可以使用,但违背了COM的基本规则,并且给以后的扩展留下了隐患。
例如,把一个In-process COM Object(简单说COM DLL)改成out-of-process object(COM EXE)。
理论上,客户端的代码应该不做任何改变。
但如果是用了C/C++字符串,又希望只使用系统的automation mashaller(Oleaut32.dll),就会出错。
∙如果可以提供custom marshaling,也推荐使用BSTR。
∙客户要求接口必须使用BSTR,和客户讨论后,不能修改。
∙使用的外部库的接口使用BSTR不使用的情况:∙不推荐在IDL结构体中定义BSTR成员,会给结构体的复制和释放带来麻烦。
最好直接使用限定最大长度的TCHAR数组。
如果确实需要传递变长字符串,BSTR应该被定义成独立的参数或者使用独立的get/set接口。
∙尽可能缩小的BSTR及相关类型的作用域范围。
类的成员变量和函数参数不使用BSTR。
局部变量要尽快释放类的内部不使用BSTR。
代码处理逻辑中只在接口直接相关部分使用BSTR。
接收到一个BSTR时,尽量立刻变成C/C++的字符串副本进行处理。
在需要传递BSTR参数前产生BSTR,用过立即释放。
1How to use BSTR1.1BSTR分析BSTR设计对于C++程序员好坏参半。
一方面,BSTR可以被用于大多数需要OLECHAR数组作为参数的函数。
另一方面,不能用熟悉的C/C++函数进行对BSTR的分配、释放和处理,例如malloc, free, new, delete, lstrcat, and lstrlen 等函数不能用于处理BSTR。
就像对接口指针和类指针的处理不一样,对BSTR的处理和对TCHAR*的处理也不一样。
BSTR是一种C语言方式的类型定义方式,这种定义方式提高了BSTR在C++的应用效率,但是也带来了很多的潜在风险,它使程序员失去了利用编译器检查潜在问题的机会。
1.2BSTR使用基本规则∙在对BSTR进行读取操作的时候,可以把BSTR看作OLECHAR数组。
BSTR可以用于const wchar_t*(LPCTSTR/ LPCWSTR/ cosnt TCHAR*/ cosnt WCHAR* in Unicode project),不能用于需要wchar_t* (LPTSTR/ LPWSTR/ TCHAR*/ WCHAR* in Unicode project)的地方。
∙如果有相应的BSTR处理函数,必须使用BSTR处理函数,不要使用普通字符串函数。
特别是一个BSTR包含多个字符串(也就是,包含多个0结束符)的情况。
在对BSTR进行修改(包括创建和释放时),必须使用BSTR的专用函数。
主要要保证对字符长度前缀的正确修改。
不要直接读取BSTR的长度域,应该使用BSTR处理函数计算长度。
∙NULL是BSTR的有效值。
按照约定,它可以被看作含有0个字符的字符串。
BSTR变量必须等于NULL,或者正确分配的BSTR指针。
在改变BSTR变量的之前,必须释放原来指向的BSTR。
不要把BSTR直接初始化成常量字符指针,例如,BSTR bs = L””。
∙Automation会cache BSTR使用的空间,以提高SysAllocString/SysFreeString 的性能,会给测试发现问题带来困难。
如果可能推荐在调试时使用Compuware DevPartner 7.x及更高版本的工具。
1.3BSTR参数使用多数时候,BSTR是被用于函数参数。
关于BSTR参数的使用规则是BSTR类型的基础。
只有熟练掌握,才能分析warpper 类或转换函数的正确性。
基本原则:在给by-reference[in/out]参数赋一个新的值前,被调用者负责释放。
其他情况,都是调用者负责释放。
调用者使用BSTR的规则如下:·释放被调用函数返回的BSTR,或者被调用函数通过by-reference返回的BSTR。
HRESULT IWebBrowser2::get_StatusText( BSTR FAR* pbstr );//...BSTR bstrStatus;pBrowser->get_StatusText( &bstrStatus );// shows using the Win32 function// to freee the memory for the string:::SysFreeString( bstrStatus );·释放通过by-value方式传给其他函数的BSTR.//.hHRESULT IWebBrowser2::put_StatusText( BSTR bstr );//.cpp// shows using the Win32 function// to allocate memory for the string:BSTR bstrStatus = ::SysAllocString( L"Some text" );if (bstrStatus == NULL)return E_OUTOFMEMORY;pBrowser->put_StatusText( bstrStatus );// Free the string:::SysFreeString( bstrStatus );//...被调用者按照如下规则处理BSTR:·如果一个BSTR参数是by-reference方式,在给参数赋新值之前,Free以前的值。
如果没有给参数赋的新值,不要Free传入值。
void RefreshBSTR(BSTR& bs)// bs is an [in/out] parameter. BSTR* is the same{// using the bs hereDosomething(bs);// if (bs is about to be updated)ASSERT(bs != NULL);::Sys Re allocString(bs, _T(“NEW STRING”));// Sys Re allocString will call SysFreeString and// SysAllocString in sequence// If bs is only [out] parameter, SysAllocString// should be called here.}·不要Free通过by-value传入的BSTR。