解决VC6在win7中不能使用mscomm控件的方法

最近想学习一下上位机的编程语言,也就是VB VC C# Labview之类的。但是,有一个串口程序,是在VB6.0下开发的,运行时,出现了错误。但是Win7 64位已经是VS2008 VS2010等的了,不能安装原来的VC++6.0 VB6.0了。那怎么使用之前的代码与运行之前的程序呢?Win7 兼容性还算是可以的。
这个串口程序使用的是:MSCOMM32.OCX,所以要在win7 上注册这个组件,因为不是DLL文件,可以直接使用。

成功的方法如下:

把下载的mscomm32.ocx 复制到:C:\Windows\SysWOW64目录下(注意这里是win7 64位的)。

注册方法一:以管理员身份运行cmd,输入命令: regsvr32 mscomm32.ocx
注册方法二:用记事本在 C:\Windows\SysWOW64新建一个txt文件,然后 输入:C:\Windows\SysWOW64,保存成1.bat(改文件的扩展名)。然后用管理员身份运行即可。

Crypto++加密解密—— AES(ECB模式)+MAC认证

AES是一种对称密钥加密算法,ECB(Electronic Code Book)是一种加密模式。若对一文本加密,只有算法是不够的,还要选择模式。常用的模式有ECB,CFB,CBC,OFB。除了ECB外后三者都需要初始向量IV(initialization Vector)。(此段为加解密扫盲语,若看不懂需要做点功课了!)。

而MAC认证本身并不对消息加密,只是为了防止消息被非法篡改。本文代码先对消息做个认证然后采用AES加密,最后再还原消息。(初学者之作,大牛绕行)

项目目录如下:

StdAfx.h 头文件代码若下:

  1. #if !defined(AFX_STDAFX_H__3BD17221_972E_411D_871C_4AB7F4CD6B64__INCLUDED_)
  2. #define AFX_STDAFX_H__3BD17221_972E_411D_871C_4AB7F4CD6B64__INCLUDED_
  3. #if _MSC_VER > 1000
  4. #pragma once
  5. #endif // _MSC_VER > 1000
  6. #include <iostream>
  7. using namespace std;
  8. // Crypto++ Library
  9. #ifdef _DEBUG
  10. #  pragma comment( lib, “cryptlibd” )
  11. #else
  12. #  pragma comment( lib, “cryptlib” )
  13. #endif

Crypto__test.cpp源码如下:

  1. #include “stdafx.h”
  2. // Runtime Includes
  3. #include <iostream>
  4. #include <string>
  5. // Crypto++ Includes
  6. #include “default.h”
  7. #include “filters.h” // StringSource and
  8.                      // StreamTransformation
  9. #include “osrng.h”
  10. #include “hex.h”
  11. using namespace std;
  12. using namespace CryptoPP;
  13. //先对消息(message)做MAC认证(messageMACed),然后采用AES—ECB加密模式对认证后的消息加密(CipherText)。对加密的消息(CipherText)解密为带MAC的消息(recoverMACed)然后去掉MAC即可得到原来的消息(recovered)。
  14. int main(int argc, char* argv[])
  15. {
  16.     string message = “I am Houjialin”;
  17.     byte password[] ={ 0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7};//认证使用的密码(密钥)
  18.     string messageMACed,CipherText,recoverMACed,recovered;
  19.     //MAC消息认证
  20.     StringSource(message,truenew DefaultEncryptorWithMAC( password, sizeof(password), new StringSink(messageMACed)));
  21.     //AES—ECB加密
  22.     byte key[ AES::DEFAULT_KEYLENGTH ];//创建密钥
  23.     ::memset( key, 0x01, AES::DEFAULT_KEYLENGTH );//初始化密钥(1填充)
  24.     ECB_Mode< AES >::Encryption  Encryptor( key, sizeof(key));
  25. //ECB属于不带初始向量的分块模式,将原文分块时若不够整块则需要填充,此处的DEFAULT_PADDING即为使用默认数据填充。(若需详细资料可查阅相关Crypto++帮助文档)
  26.     StringSource( messageMACed, true,new StreamTransformationFilter( Encryptor,new StringSink( CipherText ),BlockPaddingSchemeDef::BlockPaddingScheme::DEFAULT_PADDING,true));
  27.     //AES—ECB解密
  28.     ECB_Mode< AES >::Decryption Decryptor( key, sizeof(key) );
  29.     StringSource( CipherText, true,new StreamTransformationFilter( Decryptor,new StringSink( recoverMACed ),BlockPaddingSchemeDef::BlockPaddingScheme::DEFAULT_PADDING,true));
  30.     //去掉MAC
  31.     StringSource(recoverMACed,true,new DefaultDecryptorWithMAC(password,sizeof(password),new StringSink( recovered )));
  32.     cout<<“原始消息:  “<<message<<“\n”<<endl;
  33.     cout<<“认证后的消息: “<<messageMACed<<“\n”<<endl;
  34.     cout<<“加密后的消息: “<<CipherText<<“\n”<<endl;
  35.     cout<<“解密后带MAC的消息: “<<recoverMACed<<“\n”<<endl;
  36.     cout << “去掉MAC后的消息:” << recovered << endl;
  37.     return 0;
  38. }

运行结果如下:

CString,string,char*之间的转换

这三种类型各有各的优点,比如CString比较灵活,是基于MFC常用的类型,安全性也最高,但可移植性最差。string是使用STL时必不可少的类型,所以是做工程时必须熟练掌握的;char*是从学习C语言开始就已经和我们形影不离的了,有许多API都是以char*作为参数输入的。所以熟练掌握三者之间的转换十分必要。

以下我用简单的图示指出三者之间的关系,并以标号对应转换的方法。

1 string to CString

CString.format(“%s”,string.c_str());

2 CString to string

string str(CString.GetBuffer(str.GetLength()));

3 string to char *

char *p=string.c_str();

4 char * to string

string str(char*);

5 CString to char *

strcpy(char,CString,sizeof(char));

6 char * to CString

CString.format(“%s”,char*);

 CString的format方法是非常好用的。string的c_str()也是非常常用的,但要注意和char *转换时,要把char定义成为const char*,这样是最安全的。
以上函数UNICODE编码也没问题:unicode下照用,加个_T()宏就行了,像这样子_T(“%s”)
补充:
CString 可能是 CStringW/CStringA,在与 string 转换时,如果是 CStringW,还涉及编码转换问题。下面以 CStringA 来说明。
1 string to CString
CString.format(“%s”,string.c_str());
CStringA = string.c_str() 就可以了
2 CString to string
string str(CString.GetBuffer(str.GetLength()));
GetBuffer 有参数的话,可能导致内部的分配空间动作,要进行后续 ReleaseBuffer 操作。
string = CStringA
string = CStringA.GetBuffer();
3 string to char *
char *p=string.c_str();
4 char * to string
string str(char*);
5 CString to char *
strcpy(char *,CString,sizeof(char));
按照 3 风格,这里应该 char *  = CStringA; 或者 char *p = CStringA.GetBuffer();
6 char * to CString
CStringA = char * 就可以了

fatal error C1010: unexpected end of file while looking for precompiled header

在编译VC++6.0是,出现

fatal error C1010: unexpected end of file while looking for precompiled header directive

问题详细解释:

致命错误C1010,在寻找预编译指示头文件时,文件未预期结束。就是没有找到预编译指示信息的头文件。

问题一般发生在:

通过添加文件的方式,添加了一些cpp文件到一个MFC的程序,但该cpp文件并不是MFC,是标准C++的。

解决方案1:

右键点击项目工程中的该cpp文件,在菜单Project 》Settings里C++页面的Precomplie Header,设置为第一项:Not using precompiled headers。

解决方案2:

在.cpp文件开头添加包含文件stdafx.h。

#include “stdafx.h”

作者:sdnupeak@sina.com

常见证书格式及相互转换

PKCS 全称是 Public-Key Cryptography Standards ,是由 RSA 实验室与其它安全系统开发商为促进公钥密码的发展而制订的一系列标准,PKCS 目前共发布过 15 个标准。 常用的有:
PKCS#7 Cryptographic Message Syntax Standard
PKCS#10 Certification Request Standard
PKCS#12 Personal Information Exchange Syntax Standard
X.509是常见通用的证书格式。所有的证书都符合为Public Key Infrastructure (PKI) 制定的 ITU-T X509 国际标准。
PKCS#7 常用的后缀是: .P7B .P7C .SPC
PKCS#12 常用的后缀有: .P12 .PFX
X.509 DER 编码(ASCII)的后缀是: .DER .CER .CRT
X.509 PAM 编码(Base64)的后缀是: .PEM .CER .CRT
.cer/.crt是用于存放证书,它是2进制形式存放的,不含私钥。
.pem跟crt/cer的区别是它以Ascii来表示。
pfx/p12用于存放个人证书/私钥,他通常包含保护密码,2进制方式
p10是证书请求
p7r是CA对证书请求的回复,只用于导入
p7b以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。
—————-
小美注:
der,cer文件一般是二进制格式的,只放证书,不含私钥
crt文件可能是二进制的,也可能是文本格式的,应该以文本格式居多,功能同der/cer
pem文件一般是文本格式的,可以放证书或者私钥,或者两者都有
pem如果只含私钥的话,一般用.key扩展名,而且可以有密码保护
pfx,p12文件是二进制格式,同时含私钥和证书,通常有保护密码
怎么判断是文本格式还是二进制?用记事本打开,如果是规则的数字字母,如
—–BEGIN CERTIFICATE—–
MIIE9jCCA96gAwIBAgIQVXD9d9wgivhJM//a3VIcDjANBgkqhkiG9w0BAQUFADBy
—–END CERTIFICATE—–
就是文本的,上面的BEGIN CERTIFICATE,说明这是一个证书
如果是—–BEGIN RSA PRIVATE KEY—–,说明这是一个私钥
文本格式的私钥,也可能有密码保护
文本格式怎么变成二进制? 从程序角度来说,去掉前后的—-行,剩下的去掉回车,用base64解码,就得到二进制了
不过一般都用命令行openssl完成这个工作
—————
一 用openssl创建CA证书的RSA密钥(PEM格式):
openssl genrsa -des3 -out ca.key 1024
二用openssl创建CA证书(PEM格式,假如有效期为一年):
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -config openssl.cnf
openssl是可以生成DER格式的CA证书的,最好用IE将PEM格式的CA证书转换成DER格式的CA证书。
三 x509到pfx
pkcs12 -export –in keys/client1.crt -inkey keys/client1.key -out keys/client1.pfx
四 PEM格式的ca.key转换为Microsoft可以识别的pvk格式。
pvk -in ca.key -out ca.pvk -nocrypt -topvk
五 PKCS#12 到 PEM 的转换
openssl pkcs12 -nocerts -nodes -in cert.p12 -out private.pem
验证 openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem
六 从 PFX 格式文件中提取私钥格式文件 (.key)
openssl pkcs12 -in mycert.pfx -nocerts -nodes -out mycert.key
七 转换 pem 到到 spc
openssl crl2pkcs7 -nocrl -certfile venus.pem -outform DER -out venus.spc
用 -outform -inform 指定 DER 还是 PAM 格式。例如:
openssl x509 -in Cert.pem -inform PEM -out cert.der -outform DER
八 PEM 到 PKCS#12 的转换,
openssl pkcs12 -export -in Cert.pem -out Cert.p12 -inkey key.pem

微信扫码支付后PC端自动跳转

支付前订单状态为未支付

支付后返回后台通知修改订单状态为已支付
用setInterval 3s请求一次后台,当订单状态改变跳转页面

$(document).ready(function () {
	    setInterval("ajaxstatus()", 3000);    
	});
	
	function ajaxstatus() {
	    if ($("#out_trade_no").val() != 0) {
	        $.ajax({
	            url: "URL?tradeno=" + $("#out_trade_no").val(),
	            type: "GET",
	            dataType:"json",
	            data: "",
	            success: function (data) {
// 	            	alert(data);
	                if (data==1) { //订单状态为1表示支付成功
	                   window.location.href = "wxScanSuccessUrl.action"; //页面跳转
	                }
	            },
	            error: function () {
	                 alert("请求订单状态出错"); 
	            }
	        });
	    }
	
	} 

直通串口线与交叉串口线的区分

串口线也分直通和交叉,直通一般用于延长PC与设备,将2、3、5分别连接2、3、5,因为PC上一般为公头,而设备上多为母头,所以正好它们是通用的,既可用于延长也可用于连接;交叉一般用于PC与PC对接,将2对3、3对2、5对5,一般两头都是母头!

计算机出现之前,为连接串口设备,EIA 制定了RS232 标准。PC 机出现后,已有的串口设备成为PC机外设,自然采用RS232 标准。目前PC 机的串行通信接口采用EIA-RS-232C 标准,C 代表1969年最新一次的修改。EIA-RS-232C标准对电器特性、逻辑电平和各种信号线功能作了规定。EIA-RS-232C标准用正负电压来表示逻辑状态,在数据信号线上若电压在-3V~-15V之间表示逻辑1,若电压在+3V~+15V之间表示逻辑0;在控制信号线上若电压在-3V ~-15V 之间表示断开状态,若电压在+3V ~+15V之间表示接通状态。介于-3V ~+3V 之间和低于-15V 、高于+15V 的电压无意义。
而CPU 和终端则采用TTL 电平及正逻辑,TTL 电平用+5V 表示逻辑1,0V 表示逻辑0,它们与EIA采用的电平及负逻辑不兼容,需在接口电路中进行转换。EIA-RS-232C 标准没有定义连接器的物理特征.因此出现了DB-25、DB-15 和DB-9 各种类型的连接器,PC 机的COM1和COM2串行接口采用DB-9连接器。ELA-RS-232C 标准规定,当误码率小于4%时,允许导线长度15m 。实际应用中,当使用9600b /s、普通双绞屏蔽线时,传输距离可达30m ~35m 。PC 机的COM1和COM2两个串行接口采用的DB-9连接器是公( 针) 头,提供异步通信的 9 个引脚功能。分别为:①脚 (DCD) 数据载波检测,②脚 (RXD)接收数据,③脚(TXD) 发送数据,④脚 (DTR) 数据终端准备,⑤脚 (SG) 信号地,⑥脚 (DSR) 数据设备准备好,⑦脚(RaS)请求发送,⑧脚 (CTS) 清除发送,⑨脚 (RI) 振铃指示。DB-9 公 ( 针 ) 头排列顺序如下图上,DB-9母座排列顺序如下右下,针 ( 座 ) 朝向自己。在连接器上标有数字。EIA-RS-232C 标准中 , 有三个发送信号:TXD 、RTS 和DTR,每根线的典型输出电流为± 8mA/±12V 。通常由 RTS 和 DTR 供电的话,可提供约192mW 功率。

结合上述说明,如果不涉及Modem。串口传输数据只要有接收数据端②脚和发送数据端③脚就能实现.应将一个设备的接收数据端与另一设备的发送数据端相连。即接收与发送彼此交叉,信号地对应相接。

问题1:何时用交叉,何时用直连?
标准串口引脚2是RX,引脚3是TX,(即九针串口的2号引脚连接的是主控芯片的RXD引脚,3号引脚连接的是主控芯片的TXD引脚),如果单片机开发板的串口和电脑串口都是标准串口,则俩串口应该用交叉线连接。但现实生活中直连线居多(可能是直连线生产起来没交叉线麻烦吧),为了配合直连线的使用,在画板的时候,把主控芯片的RXD引脚连接至串口的3脚,主控芯片的TXD引脚连接至串口的2脚,这样这个开发板上的串口就不是标准串口了,即2变成TX,3变成RX,和标准串口连接时当然应该使用直连线了。看一个开发板上的串口是标准串口还是非标准串口,根本还是要看原理图是怎么连的!

问题2:如何辨别交叉串口线与直连串口线?
用万用表测一下,如果2和2通,3和3通则为直连串口线;如果2和3通,3和2通则为交叉串口线。
有人困惑母口外面是一块绝缘的橡胶,万用表的探针插不进去怎么测?那就截一小段焊锡丝(我也曾考虑过用金属丝,可是金属丝太细了,我们不能保证它能够跟母口中的金属部分完好接触,焊锡丝粗一点,是可以跟母口内的金属很好地接触的),然后把万用表探针接触焊锡丝来测试即可。
当然了,如果每次拿到一根串口线都要拿个万用表来测测它是直连的还是交叉的岂不是很麻烦,教你一个轻松辨别的好方法,那就是:两头母口是交叉,一公一母是直连。(两头都是公口的串口线好像很少)

COleSafeArray

COleSafeArray

COleSafeArray类是用于处理任意类型和维数的数组的类。COleSafeArray是从OLE
 VARIANT结构派生而来的。OLE 
SAFEARRAY成员函数在可以通过COleSafeArray来访问,就象是特别为一维的字节数组所设计的一个成员函数集。

Class COleSafeArray is a class for working with arrays of arbitrary(任意的) type and dimension(维). COleSafeArray derives from the OLE VARIANT structure. The OLE SAFEARRAY member functions are available through COleSafeArray, as well as a set of member functions specifically designed for one-dimensional arrays of bytes. 构造 COleSafeArray 构造一个COleSafeArray对象

操作 Attach 给COleSafeArray对象以存在的VARIANT数组的控制

Clear 释放基VARIANT中的所有数据
Detach 将VARIANT数组从COleSafeArray对象中分离出来(这将使数据不会被释放)
Win32 API 包装 AccessData 获取一个指向数组数据的指针
AllocData 为数组分配内存
AllocDescriptor 为安全数组描述符分配内存
Copy 创建一个已存在的数组的拷贝
Create 创建一个安全数组
Destroy 销毁一个已经存在的数组
DestroyData 销毁一个安全数组中的数据
DestroyDescriptor 销毁一个安全数组的描述符
GetDim 返回数组的维数
GetElement 获取安全数组中的一个单一元素
GetElemSize 返回安全数组中一个元素的按字节表示的大小
GetLBound 返回一个安全数组任一维的下界
GetUBound 返回一个安全数组任一维的上界
Lock 增加一个数组的加锁计数,并将一个指向数组数据的指针放到数组描述符中
PtrOfIndex 返回一个指向被索引的元素的指针
PutElement 将一个单一的元素放入数组中
Redim 改变一个安全数组的最不重要(最右边)的边界
UnaccessData 减小一个数组的加锁计数,并使由AccessData获得的指针无效
Unlock 减小一个数组的加锁以使它能被释放或改变大小

一维数组操作 CreateOneDim 创建一个一维的COleSafeArray对象
GetOneDimSize 返回一个一维的COleSafeArray对象中的元素个数
ResizeOneDim 改变一个一维的COleSafeArray对象中的元素个数

操作符

operator = 将一些值(包括SAFEARRAY,VARIANT,COleVariant,或COleSafeArray对象)拷贝到COleSafeArray对象中,自动将其他数据类型转换为COleSafeArray
operator == 比较两个不同的数组(SAFEARRAY,VARIANT,ColeVariant,或COleSafeArray对象)

operator << Outputs the contents of a COleSafeArray object to the dump context.
operator LPVARIANT Accesses the underlying VARIANT structure of the COleSafeArray object.
operator LPCVARIANT Accesses the underlying VARIANT structure of the COleSafeArray object.

构造函数
COleSafeArray::COleSafeArray

COleSafeArray();
COleSafeArray( const SAFEARRAY& saSrc, VARTYPE vtSrc );
COleSafeArray( LPCSAFEARRAY psaSrc, VARTYPE vtSrc );
COleSafeArray( const COleSafeArray& saSrc );
COleSafeArray( const VARIANT& varSrc );
COleSafeArray( LPCVARIANT pSrc );
COleSafeArray( const COleVariant& varSrc );

参数: saSrc 要被拷贝到新的COleSafeArray对象中去的已经存在的COleSafeArray对象或SAFEARRAY。
vtSrc 新的COleSafeArray对象的VARTYPE。
psaSrc 一个指向要被拷贝到新的COleSafeArray对象中去的SAFEARRAY的指针。
varSrc 要被拷贝到新的COleSafeArray对象中去的已经存在的VARIANT或者COleVariant。
pSrc 一个指向要被拷贝到新的COleSafeArray对象中去

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表示const
3.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。

CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。

LPCTSTR:
#ifdef _UNICODE
typedef const wchar_t * LPCTSTR;
#else
typedef const char * LPCTSTR;
#endif

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);

二、从其它包含字符串的变量中获取指向该字符串的指针

CString变量
str = “2008北京奥运”;
buf = (LPSTR)(LPCTSTR)str;
BSTR类型的_variant_t变量
v1 = (_bstr_t)”程序员”;
buf = _com_util::ConvertBSTRToString((_bstr_t)v1);

三、字符串转换为其它数据类型
strcpy(temp,”123″);

短整型(int)
i = atoi(temp);
长整型(long)
l = atol(temp);
浮点(double)
d = atof(temp);

四、其它数据类型转换到CString

使用CString的成员函数Format来转换,例如:

整数(int)
str.Format(“%d”,i);
浮点数(float)
str.Format(“%f”,i);
字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值
str = username;

五、BSTR、_bstr_t与CComBSTR

CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。
char *转换到BSTR可以这样: BSTR b=_com_util::ConvertStringToBSTR(“数据”);        //使用前需要加上头文件comutil.h
反之可以使用char *p=_com_util::ConvertBSTRToString(b);

六、VARIANT 、_variant_t 与 COleVariant

VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:
VARIANT va;
int a=2001;
va.vt=VT_I4;       //指明整型数据
va.lVal=a;         //赋值

对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

unsigned char bVal; VT_UI1
short iVal; VT_I2
long lVal;     VT_I4
float fltVal;     VT_R4
double dblVal;     VT_R8
VARIANT_BOOL boolVal;     VT_BOOL
SCODE scode;     VT_ERROR
CY cyVal;     VT_CY
DATE date;     VT_DATE
BSTR bstrVal;     VT_BSTR
IUnknown FAR* punkVal;     VT_UNKNOWN
IDispatch FAR* pdispVal;     VT_DISPATCH
SAFEARRAY FAR* parray;     VT_ARRAY|*
unsigned char FAR* pbVal;     VT_BYREF|VT_UI1
short FAR* piVal;     VT_BYREF|VT_I2
long FAR* plVal;     VT_BYREF|VT_I4
float FAR* pfltVal;     VT_BYREF|VT_R4
double FAR* pdblVal; VT_BYREF|VT_R8
VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL
SCODE FAR* pscode;     VT_BYREF|VT_ERROR
CY FAR* pcyVal;     VT_BYREF|VT_CY
DATE FAR* pdate; VT_BYREF|VT_DATE
BSTR FAR* pbstrVal;     VT_BYREF|VT_BSTR
IUnknown FAR* FAR* ppunkVal;     VT_BYREF|VT_UNKNOWN
IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH
SAFEARRAY FAR* FAR* pparray;     VT_ARRAY|*
VARIANT FAR* pvarVal;     VT_BYREF|VT_VARIANT
void FAR* byref;     VT_BYREF

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
例如:
long l=222;
ing i=100;
_variant_t lVal(l);
lVal = (long)i;

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:
COleVariant v3 = “字符串”, v4 = (long)1999;
CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;

七、其它

对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个16位数据(WORD),例如:
LPARAM lParam;
WORD loValue = LOWORD(lParam);        //取低16位
WORD hiValue = HIWORD(lParam);        //取高16位
对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如:
WORD wValue;
BYTE loValue = LOBYTE(wValue);        //取低8位
BYTE hiValue = HIBYTE(wValue);        //取高8位

如何将CString类型的变量赋给char*类型的变量
1、GetBuffer函数:
使用CString::GetBuffer函数。
char *p;
CString str=”hello”;
p=str.GetBuffer(str.GetLength());
str.ReleaseBuffer();

将CString转换成char * 时
CString str(“aaaaaaa”);
strcpy(str.GetBuffer(10),”aa”);
str.ReleaseBuffer();
当我们需要字符数组时调用GetBuffer(int n),其中n为我们需要的字符数组的长度.使用完成后一定要马上调用ReleaseBuffer();
还有很重要的一点就是,在能使用const char *的地方,就不要使用char *

2、memcpy:
CString mCS=_T(“cxl”);
char mch[20];
memcpy(mch,mCS,20);

3、用LPCTSTR强制转换: 尽量不使用
char *ch;
CString str;
ch=(LPSTR)(LPCTSTR)str;

CString str = “good”;
char *tmp;
sprintf(tmp,”%s”,(LPTSTR)(LPCTSTR)str);

4、
CString Msg;
Msg=Msg+”abc”;
LPTSTR lpsz;
lpsz = new TCHAR[Msg.GetLength()+1];
_tcscpy(lpsz, Msg);
char * psz;
strcpy(psz,lpsz);

CString类向const char *转换
char a[100];
CString str(“aaaaaa”);
strncpy(a,(LPCTSTR)str,sizeof(a));
或者如下:
strncpy(a,str,sizeof(a));
以上两种用法都是正确地. 因为strncpy的第二个参数类型为const char *.所以编译器会自动将CString类转换成const char *.

CString转LPCTSTR (const char *)
CString cStr;
const char *lpctStr=(LPCTSTR)cStr;

LPCTSTR转CString
LPCTSTR lpctStr;
CString cStr=lpctStr;

将char*类型的变量赋给CString型的变量
可以直接赋值,如:
CString myString = “This is a test”;
也可以利用构造函数,如:
CString s1(“Tom”);

将CString类型的变量赋给char []类型(字符串)的变量
1、sprintf()函数
CString str = “good”;
char tmp[200] ;
sprintf(tmp, “%s”,(LPCSTR)str);
(LPCSTR)str这种强制转换相当于(LPTSTR)(LPCTSTR)str
CString类的变量需要转换为(char*)的时,使用(LPTSTR)(LPCTSTR)str

然而,LPCTSTR是const char *,也就是说,得到的字符串是不可写的!将其强制转换成LPTSTR去掉const,是极为危险的!
一不留神就会完蛋!要得到char *,应该用GetBuffer()或GetBufferSetLength(),用完后再调用ReleaseBuffer()。

2、strcpy()函数
CString str;
char c[256];
strcpy(c, str);

char mychar[1024];
CString source=”Hello”;
strcpy((char*)&mychar,(LPCTSTR)source);

关于CString的使用
1、指定 CString 形参
对于大多数需要字符串参数的函数,最好将函数原型中的形参指定为一个指向字符 (LPCTSTR) 而非 CString 的 const 指针。
当将形参指定为指向字符的 const 指针时,可将指针传递到 TCHAR 数组(如字符串 [“hi there”])或传递到 CString 对象。
CString 对象将自动转换成 LPCTSTR。任何能够使用 LPCTSTR 的地方也能够使用 CString 对象。

2、如果某个形参将不会被修改,则也将该参数指定为常数字符串引用(即 const CString&)。如果函数要修改该字符串,
则删除 const 修饰符。如果需要默认为空值,则将其初始化为空字符串 [“”],如下所示:
void AddCustomer( const CString& name, const CString& address, const CString& comment = “” );

3、对于大多数函数结果,按值返回 CString 对象即可。

串的基本运算
对于串的基本运算,很多高级语言均提供了相应的运算符或标准的库函数来实现。
为叙述方便,先定义几个相关的变量:
char s1[20]=”dir/bin/appl”,s2[20]=”file.asm”,s3[30],*p;
int result;
下面以C语言中串运算介绍串的基本运算
1、求串长
int strlen(char *s);            //求串s的长度
【例】printf(“%d”,strlen(s1));       //输出s1的串长12

2、串复制
char *strcpy(char *to,*from);//将from串复制到to串中,并返回to开始处指针
【例】strcpy(s3,s1);     //s3=”dir/bin/appl”,s1串不变

3、联接
char *strcat(char *to,char *from);//将from串复制到to串的末尾,
//并返回to串开始处的指针
【例】strcat(s3,”/”);       //s3=”dir/bin/appl/”
strcat(s3,s2);        //s3=”dir/bin/appl/file.asm”

4、串比较
int strcmp(char *s1,char *s2);//比较s1和s2的大小,
//当s1<s2、s1>s2和s1=s2时,分别返回小于0、大于0和等于0的值
【例】result=strcmp(“baker”,”Baker”);       //result>0
result=strcmp(“12″,”12”);          //result=0
result=strcmp(“Joe”,”joseph”)      //result<0

5、字符定位
char *strchr(char *s,char c);//找c在字符串s中第一次出现的位置,
//若找到,则返回该位置,否则返回NULL
【例】p=strchr(s2,’.’);         //p指向”file”之后的位置
if(p) strcpy(p,”.cpp”);        //s2=”file.cpp”

     注意:
①上述操作是最基本的,其中后 4个操作还有变种形式:strncpy,strncath和strnchr。
②其它的串操作见C的<string.h>。在不同的高级语言中,对串运算的种类及符号都不尽相同
③其余的串操作一般可由这些基本操作组合而成

       【例】求子串的操作可如下实现:
void substr(char *sub,char *s,int pos,int len){
//s和sub是字符数组,用sub返回串s的第pos个字符起长度为len的子串
//其中0<=pos<=strlen(s)-1,且数组sub至少可容纳len+1个字符。
if (pos<0||pos>strlen(s)-1||len<0)
Error(“parameter error!”);
strncpy(sub,&s[pos],len);         //从s[pos]起复制至多len个字符到sub

VC++ 6.0 中使用 MSComm.ocx design-time license

很多人喜欢单独安装VC++6.0,而不是完整安装VS,这样占用空间比较少,启动也快。但是要使用某些ActiveX控件的时候却会出现许可证问题(requires a design-time licence),譬如使用MSComm.ocx。至于ActiveX的许可证体系这里就不说了,简单说就是用来保证第三方ActiveX控件开发者的智力投资的。MSComm.ocx是VS自带的一个进行串口通讯的控件,本来在安装VS的时候会自动把相应的licence发放给用户,但是这个licence是由VB附带提供的,现在我们没有安装VB,因此当我们在插入该控件到我们的项目时,就会出现上述的许可证问题。     我们可以通过安装VB6.0来解决这个问题,但是如果我们平时很少用VB,就为了这个控件而安装的话就有点大材小用了,而且也违背了当初单独安装VC++的初衷。下面还有另外一种方法:在文本文件中输入(注意格式)

REGEDIT4 [HKEY_CLASSES_ROOT\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905] @ = “kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun”

另存为一个注册表文件,如 lic.reg。然后双击。。好了,控件可以使用了。