vc++.NET调用oracle10g

/*远程连接*/ 
try
    {
     CString ConnStr;
    ConnStr.Format("Provider=%s;Password=%s;Persist Security Info=True;User ID=%s;Data Source=%s",dbclass,dlg.m_SetDBPWD,dlg.m_SetDBUSER,dlg.m_SetDBNM );      
    _bstr_t  connectstr=ConnStr;   
       pConn->Open(connectstr,"","",adModeUnknown);
    if(hr != S_OK)
    {
      return ;
    }
  
    }catch(_com_error &ex)
    {
。。。。
}
/*查询*/ 
pRst->CursorLocation=adUseClient;
//adOpenStatic缺点不能及时更新
     pRst->Open(sql.AllocSysString(),_variant_t((IDispatch*)pConn,TRUE),adOpenDynamic,adLockOptimistic,adCmdText);
20:51 | 添加评论| 固定链接| 引用通告 (0)| 记录它

winpcap获取网络设备

在捕获网络设备的时候,我的笔记本会返回一个拨号器,一个以太网卡两个设备。
后来安装了虚拟机,设备一下变成了四个。代码如下:
for(d=alldevs,idx=1; d; d=d->next , idx++)
 {
    name.Format("%s",d->name);  
    if (d->description)
   des.Format("%s",d->description);
   else
   des.Format("(No description available)");   
   m_AdapterList.InsertItem( LVIF_TEXT|LVIF_STATE, idx-1, "", 0, 0,0, 0); //输出到list 控件   m_AdapterList.SetItem(idx-1,1,LVIF_TEXT,TEXT(name +des),0,0,0,0);      
  flag = true;
 }
别忘了将所选择索引传递到捕捉函数之后要减一。

20:37 | 添加评论| 固定链接| 引用通告 (0)| 记录它
4月2日

VC++.net 2003 捕获局域网组播数据包

接到任务书捕捉局域网内组播数据包程序,开发环境vs2003+oracle10g
1。
基于winpcap开放源码,顺便说一下raw socket也不错:
安装winpcap_3_1。
2。 
附加依赖项中添加:
wsock32.lib ws2_32.lib wpcap.lib

3。
设置include,lib库目录位置
待续。。。

14:34 | 添加评论| 固定链接| 引用通告 (0)| 记录它

VC++.NET2003操作oracle10g

ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口。ADO 使您能够编写应用程序以通过 OLE.DB 提供者访问和操作数据库服务器中的数据。ADO 最主要的优点是易于使用、速度快、内存支出少和磁盘遗迹小。ADO 在关键的应用方案中使用最少的网络流量,并且在前端和数据源之间使用最少的层数,所有这些都是为了提供轻量、高性能的接口。之所以称为 ADO,是用了一个比较熟悉的暗喻,OLE 自动化接口。

OLE DB是一组”组件对象模型”(COM) 接口,是新的数据库低层接口,它封装了ODBC的功能,并以统一的方式访问存储在不同信息源中的数据。OLE DB是Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB 为任何数据源提供了高性能的访问,这些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定义业务对象等等。也就是说,OLE DB 并不局限于 ISAM、Jet 甚至关系数据源,它能够处理任何类型的数据,而不考虑它们的格式和存储方法。

最近做了个网路抓取数据包程序,把包数据插入oracle10g中,考虑传统ODBC,DAO方式,也考虑Pro*C的开发,比较了一下选用ado方式比较适用现在的通讯项目,所以操作数据库:
1.在stdafx.h中加入
#import "c:/program files/common files/system/ado/msado15.dll"  no_namespace  rename("EOF","adoEOF")
2.建立connection,recordset指针操作记录:
注:本例中data字段长度操作是根据实际情况考虑了截断,因为有时候sniffer到的数据太大了,又不需要所有数据。VARCHAR2(VARCHAR),描述变长字符串。它的声明方式如下VARCHAR2(L),L为字符串长度,没有缺省值,作为变量最大32767个字节,作为数据存储在ORACLE8中最大为4000。在多字节语言环境中,实际存储的 字符个数可能小于L值,例如:当语言环境为中文(SIMPLIFIED CHINESE_CHINA.ZHS16GBK)时, 一个VARCHAR2(200)的数据列可以保存200个英文字符或者100个汉字字符。 LONG,在数据库存储中可以用来保存高达2G的数据,作为变量,可以表示一个最大长度为32760字节的可变字符串。
//
 //打开连接
 //
 if(FAILED(::CoInitialize(NULL)))
 {
  ::MessageBox(NULL,_T("初始化com失败"),_T("错误"),MB_OK);
  exit(-1);
 }
HRESULT hr;
         CString dbclass="MSDAORA",m_SetDBUSER="tester",m_SetDBPWD="tester",m_SetDBNM="orcl";
 
hr=pConn.CreateInstance("ADODB.Connection");
     if(hr != S_OK)
     {
      return ;
     }

   //
  //登陆
  //
  try
    {
     CString ConnStr;    
       ConnStr.Format("Provider=%s;User ID=%s;Password=%s;Data   Source=%s",dbclass,m_SetDBUSER,m_SetDBPWD,m_SetDBNM);  //ConnStr.Format("DRIVER=Microsoft ODBC for Oracle;UID=%s;PWD=%s;SERVER=%s",dlg.m_SetDBUSER,dlg.m_SetDBPWD,dlg.m_SetDBNM);
       _bstr_t  connectstr=ConnStr;         
       pConn->Open(connectstr,"","",adModeUnknown);
    if(hr != S_OK)
    {
      return ;
    }
  
    }catch(_com_error &ex)
    {
     AfxMessageBox("捕获得错误原因:/n"+ex.Description());
      m_SetDBNM=_T("svorcl");
      m_SetDBUSER=_T("tester");
      m_SetDBPWD=_T("tester");

    
    }
//
       //验证
       //
    try
    { 
     _RecordsetPtr  pRst;
      hr=pRst.CreateInstance("ADODB.Recordset");
      _variant_t RecordAffected;
      CString sql;
      sql.Format( "select  user from  TB_USER where  /"C01/"=/'%s/' and /"C02/"=/'%s/'", m_SetDBUSER, m_SetDBPWD);        
      pRst->CursorLocation=adUseClient;
      pRst->Open(sql.AllocSysString(),_variant_t((IDispatch*)pConn,TRUE),adOpenStatic,adLockOptimistic,adCmdText);
      // pRst = pConn->Execute(sql.AllocSysString(),&RecordAffected,adCmdText);
     
      if(pRst->adoEOF)
      {
        AfxMessageBox("登陆失败!");
     if(pRst->State)  pRst->Close();
        pRst.Release();
     if(pConn->State) pConn->Close();
      pConn.Release();
    
     m_SetDBUSER.Empty();
     m_SetDBPWD.Empty();
    
      }
  
      
      pRst->Close();
      pRst.Release();
   
      }catch(_com_error &e)
        {    
     AfxMessageBox( "捕获得错误原因:/n请检查数据库安装配置!/n"+e.Description());
     exit(1);
        }

    
 //
 //存储
 //
 HRESULT hrr;
 _RecordsetPtr pRst;
 hrr=pRst.CreateInstance("ADODB.Recordset");
 if(hr !=S_OK)
 {
   AfxMessageBox("不能建立记录指针实例!");
  return;
 }
 
DWORD  num; 
 DWORD byteswritten;
 char dataBuf[1024*2];
 memset(dataBuf,0,sizeof(dataBuf));
 CString protocol="TESTUDP";
 CString s_address="0.0.0.0";
 CString s_port="99";
 CString d_address="0.0.0.0";
 CString d_port="99";
 CString  size="88";
 CString  tdata="''?'";
 tdata.Replace("'","|");
 CString   m_userID="tester";
 try
 { 
  CString sql_=NULL; 
  sql_.Format("insert into TB_PACK(ID,CLASSNAME,SOURCE,SPORT,DES,DPORT,LEN,PDATA,ITIME,OPUSER) values(TB_PACK_IDSEQ.nextval,/'%s/',/'%s/',/'%s/',/'%s/',/'%s/',/'%s/',/' %s /',SYSDATE,/'%s/' )",protocol, s_address, s_port, d_address, d_port, size, tdata,m_userID);
   strcpy(dataBuf,sql_);
  _bstr_t  sql=sql_;
   pRst->CursorLocation=adUseClient;  
    //pRst->Open(sql ,_variant_t((IDispatch*)pConn,TRUE),adOpenDynamic,adLockOptimistic,adCmdText);
   pConn->Execute(sql,NULL,adCmdText);
 
 
 }catch (_com_error &ex)
 {
       
  CString filename="errSQLlog.txt";
  WIN32_FIND_DATA  fd;
  HANDLE hd=::FindFirstFile((LPCTSTR)filename,&fd);
        if(hd !=INVALID_HANDLE_VALUE )
     {
       
    HANDLE  handle= CreateFile(
       filename,    // 要打开的文件名
       GENERIC_WRITE, // 文件的操作属性
       0, // 文件共享属性
       NULL, // 文件安全特性
       OPEN_EXISTING, //文件操作 OPEN_EXISTING
       FILE_ATTRIBUTE_NORMAL, // 文件属性
       NULL      // 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
       );
        
    ::SetFilePointer(handle,0,0,FILE_BEGIN);
    ::WriteFile(handle,dataBuf,sizeof(dataBuf),&num,NULL);
    ::WriteFile(handle, "/r/n", 2, &byteswritten, NULL);
    ::ZeroMemory(dataBuf,sizeof(dataBuf));
    ::CloseHandle(handle);  
}else
      {
        
    HANDLE  handle= CreateFile(
          filename,    // 要打开的文件名
          GENERIC_WRITE, // 文件的操作属性
          0, // 文件共享属性
          NULL, // 文件安全特性
          OPEN_ALWAYS, //文件操作 OPEN_EXISTING
          FILE_ATTRIBUTE_NORMAL, // 文件属性
          NULL      // 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
          );
        
    ::SetFilePointer(handle,0,0,FILE_BEGIN);
    ::WriteFile(handle,dataBuf,sizeof(dataBuf),&num,NULL);
    ::WriteFile(handle, "/r/n", 2, &byteswritten, NULL);
    ::ZeroMemory(dataBuf,sizeof(dataBuf));
    //::SetFilePointer(handle,0,0,FILE_BEGIN);
    //::ReadFile(handle,Buffer,sizeof(Buffer),&Num,NULL);
    ::CloseHandle(handle);  
  
    }
    

  
AfxMessageBox("存储错误原因:"+ex.Description());
  return;
 }
      //pRst->Close();
   pRst.Release();
3.顺便提一下oracle数据类型和游标的操作 
8i 的数据类型

数据类型 参数 描述
number(m,n) m=1 to 38
n=-84 to 127
可变长的数值列,允许0、正值及负值,m是所有有效数字的位数,n是小数点以后的位数。如:number(5,2),则这个字段的最大值是99,999,如果数值超出了位数限制就会被截取多余的位数。如:number(5,2),但在一行数据中的这个字段输入575.316,则真正保存到字段中的数值是575.32。如:number(3,0),输入575.316,真正保存的数据是575。
char(n) n=1 to 2000字节 定长字符串,n字节长,如果不指定长度,缺省为1个字节长(一个汉字为2字节)
long 可变长字符列,最大长度限制是2GB,用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。long是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
varchar2(n) n=1 to 4000字节 可变长的字符串,具体定义时指明最大长度n,这种数据类型可以放数字、字母以及ASCII码字符集(或者EBCDIC等数据库系统接受的字符集标准)中的所有符号。如果数据长度没有达到最大值n,Oracle 8i会根据数据大小自动调节字段长度,如果你的数据前后有空格,Oracle 8i会自动将其删去。VARCHAR2是最常用的数据类型。可做索引的最大长度3209。
date 从公元前4712年1月1日到公元4712年12月31日的所有合法日期,Oracle 8i其实在内部是按7个字节来保存日期数据,在定义中还包括小时、分、秒。缺省格式为DD-MON-YY,如07-11-00 表示2000年11月7日。
raw(n) n=1 to 2000 可变长二进制数据,在具体定义字段的时候必须指明最大长度n,Oracle 8i用这种格式来保存较小的图形文件或带格式的文本文件,如Miceosoft Word文档。raw是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
long raw 可变长二进制数据,最大长度是2GB。Oracle 8i用这种格式来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件。在同一张表中不能同时有long类型和long raw类型,long raw也是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
blob
clob
nclob
三种大型对象(LOB),用来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件,最大长度是4GB。
LOB有几种类型,取决于你使用的字节的类型,Oracle 8i实实在在地将这些数据存储在数据库内部保存。可以执行读取、存储、写入等特殊操作。
bfile 在数据库外部保存的大型二进制对象文件,最大长度是4GB。这种外部的LOB类型,通过数据库记录变化情况,但是数据的具体保存是在数据库外部进行的。Oracle 8i可以读取、查询BFILE,但是不能写入。大小由操作系统决定。

9i 的数据类型

名称 含义
Char 用于描述定长的字符型数据,长度<= 2000 字节
varchar2 用于描述变长的字符型数据,长度<= 4000 字节
nchar 用来存储Unicode字符集的定长字符型数据,长度<= 1000 字节
nvarchar2 用来存储Unicode字符集的变长字符型数据,长度<= 1000 字节
number 用来存储整型或者浮点型数值
Date 用来存储日期数据
Long 用来存储最大长度为2GB的变长字符数据
Raw 用来存储非结构化数据的变长字符数据,长度<= 2000 字节
Long raw 用来存储非结构化数据的变长字符数据,长度<= 2GB
rowid 用来存储表中列的物理地址的二进制数据,占用固定的10个字节
Blob 用来存储多达4GB的非结构化的二进制数据
Clob 用来存储多达4GB的字符数据
nclob 用来存储多达4GB的Unicode字符数据
Bfile 用来把非结构化的二进制数据存储在数据库以外的操作系统文件中
urowid 用来存储表示任何类型列地址的二进制数据
float 用来存储浮点数

Recordset对象 Recordset对象代表一个表的记录集或者命令
执行的结果,在记录集中,总是有一个当前的记录。记录集是ADO管理
数据的基本对象,所有的Recordset对象都按照行列方式的表状结构进
行管理,每一行对应一个记录(Record),每一列对应一个域(Field)。
Recordset对象也通过游标对记录进行访问,在ADO中,游标分为以下4种
:
    静态游标提供对数据集的一个静态拷贝,允许各种移动操作,包括
前移、后移等等,但其他用户所做的操作反映不出来。
    动态游标允许各种移动操作,包括前移、后移等等,并且其他用户
所做的操作也可以直接反映出来。
    前向游标允许各种前向移动操作,不能向后移动,并且其他用户所
做的操作也可以直接反映出来。
    键集(keyset)游标 类似于动态游标,也能够看到其他用户所做的
数据修改,但不能看到其他用户新加的记录,也不能访问其他用户删除
的记录。
    Recordset对象的用法如下:
    a.利用CursorType属性设置游标类型。
    b.通过Open方法打开记录集数据,既可以在Open之前对ActiveCon
nection属性赋值, 指定Recordset对象使用连接对象,也可以直接在O
pen方法中指定连接串参数,ADO将创建一个内部连接,即使连接串与外
部的连接对象相同,它也使用新的连接对象。
    c.Recordset对象刚打开时,当前记录被定位在首条记录,并且BOF
和EOF标志属性为F alse,如果当前记录集为空记录集,则BOF和EOF标
志属性为True。
    d.通过MoveFirst、MoveLast、MoveNext和MovePrevious方法可
以对记录集的游标进行移动操作。如果OLE DB提供者支持相关功能的
话,可以使用AbsolutePosition、Absol utePage和Filter属性对当前
记录重新定位。
    e.ADO提供了两种记录修改方式:立即修改和批修改。在立即修改
方式下,一旦调用U pdate方法,则所有对数据的修改立即被写到底层
的数据源。在批修改方式下,可以对多条记录进行修改,然后调用Upda
teBatch方法把所有的修改递交到底层数据源。递交之后,可以用Stat
us属性检查数据冲突。
    Recordset对象是ADO数据操作的核心,它既可以作为Connection
对象或Command对象执行特定方法的结果数据集,也可以独立于这两个
对象而使用,由此可以看出ADO对象在使用上的灵活性。
    上面3个对象都包含一个Property对象集合的属性,通过Property
对象可使ADO动态暴露出底层OLE DB提供者的性能。由于并不是所有
的底层提供者都有同样的性能,所以ADO 允许用户动态访问底层提供
者的能力。这样既使得ADO很灵活,又提供了很好的扩展性。
    ADO的其他集合对象及其元素对象,都用在特定的上下文环境中,
比如Parameter对象一定要与某个Command对象相联系后,才能真正起
作用。而另外三个对象Field、Error和Property对象只能依附于其父
对象,不能单独创建这些对象。

14:22 | 添加评论| 固定链接| 引用通告 (0)| 记录它

VC字符串转换

一、BSTR、LPSTR和LPWSTR
   在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 UNICODE
  typedef LPWSTR LPTSTR;
  typedef LPCWSTR LPCTSTR;
#else
  typedef LPSTR LPTSTR;
  typedef LPCSTR LPCTSTR;
#endif

二、CString、CStringA 和 CStringW

  Visual C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位Unicode字符),在ANSI中等价于char。wchar_t通常定义为unsigned short。由于CString在MFC应用程序中经常用到,这里不再重复。

三、VARIANT、COleVariant 和_variant_t

  在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

struct tagVARIANT {
  VARTYPE vt;
  union {
   short iVal; // VT_I2.
   long lVal; // VT_I4.
   float fltVal; // VT_R4.
   double dblVal; // VT_R8.
   DATE date; // VT_DATE.
   BSTR bstrVal; // VT_BSTR.
   …
   short * piVal; // VT_BYREF|VT_I2.
   long * plVal; // VT_BYREF|VT_I4.
   float * pfltVal; // VT_BYREF|VT_R4.
   double * pdblVal; // VT_BYREF|VT_R8.
   DATE * pdate; // VT_BYREF|VT_DATE.
   BSTR * pbstrVal; // VT_BYREF|VT_BSTR.
  };
};

  显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如:

VARIANT va;
:: VariantInit(&va); // 初始化
int a = 2002;
va.vt = VT_I4; // 指明long数据类型
va.lVal = a; // 赋值

  为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:

  VariantInit —— 将变量初始化为VT_EMPTY;

  VariantClear —— 消除并初始化VARIANT;

  VariantChangeType —— 改变VARIANT的类型;

  VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。

  COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大大的功能,当对象构造时首先调用VariantInit进行初始化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作,当VARIANT对象不在有效范围时,它的析构函数就会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。除此之外,COleVariant的赋值操作符在与VARIANT类型转换中为我们提供极大的方便。例如下面的代码:

COleVariant v1("This is a test"); // 直接构造
COleVariant v2 = "This is a test";
// 结果是VT_BSTR类型,值为"This is a test"
COleVariant v3((long)2002);
COleVariant v4 = (long)2002;
// 结果是VT_I4类型,值为2002

  _variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在Visual C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:

  #include "comutil.h"

  #pragma comment( lib, "comsupp.lib" )

四、CComBSTR和_bstr_t

  CComBSTR是对BSTR数据类型封装的一个ATL类,它的操作比较方便。例如:

CComBSTR bstr1;
bstr1 = "Bye"; // 直接赋值
OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符
CComBSTR bstr2(wcslen(str)); // 定义长度为5
wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中
CComBSTR bstr3(5, OLESTR("Hello World"));
CComBSTR bstr4(5, "Hello World");
CComBSTR bstr5(OLESTR("Hey there"));
CComBSTR bstr6("Hey there");
CComBSTR bstr7(bstr6);
// 构造时复制,内容为"Hey there"

  _bstr_t是是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib。

五、BSTR、char*和CString转换

  (1) char*转换成CString

  若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:

char chArray[] = "This is a test";
char * p = "This is a test";

  或

LPSTR p = "This is a test";

  或在已定义Unicode应的用程序中

TCHAR * p = _T("This is a test");

  或

LPTSTR p = _T("This is a test");
CString theString = chArray;
theString.Format(_T("%s"), chArray);
theString = p;

  (2) CString转换成char*

  若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:

  方法一,使用强制转换。例如:

CString theString( "This is a test" );
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

  方法二,使用strcpy。例如:

CString theString( "This is a test" );
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString);

  需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。

  方法三,使用CString::GetBuffer。例如:

CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();
// 在这里添加使用p的代码
if(p != NULL) *p = _T('/0');
s.ReleaseBuffer();
// 使用完后及时释放,以便能使用其它的CString成员函数

  (3) BSTR转换成char*

  方法一,使用ConvertBSTRToString。例如:

#include
#pragma comment(lib, "comsupp.lib")
int _tmain(int argc, _TCHAR* argv[]){
BSTR bstrText = ::SysAllocString(L"Test");
char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
SysFreeString(bstrText); // 用完释放
delete[] lpszText2;
return 0;
}

  方法二,使用_bstr_t的赋值运算符重载。例如:

_bstr_t b = bstrText;
char* lpszText2 = b;

  (4) char*转换成BSTR

  方法一,使用SysAllocString等API函数。例如:

BSTR bstrText = ::SysAllocString(L"Test");
BSTR bstrText = ::SysAllocStringLen(L"Test",4);
BSTR bstrText = ::SysAllocStringByteLen("Test",4);

  方法二,使用COleVariant或_variant_t。例如:

//COleVariant strVar("This is a test");
_variant_t strVar("This is a test");
BSTR bstrText = strVar.bstrVal;

  方法三,使用_bstr_t,这是一种最简单的方法。例如:

BSTR bstrText = _bstr_t("This is a test");

  方法四,使用CComBSTR。例如:

BSTR bstrText = CComBSTR("This is a test");

  或

CComBSTR bstr("This is a test");
BSTR bstrText = bstr.m_str;

  方法五,使用ConvertStringToBSTR。例如:

char* lpszText = "Test";
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);

  (5) CString转换成BSTR

  通常是通过使用CStringT::AllocSysString来实现。例如:

CString str("This is a test");
BSTR bstrText = str.AllocSysString();

SysFreeString(bstrText); // 用完释放

  (6) BSTR转换成CString

  一般可按下列方法进行:

BSTR bstrText = ::SysAllocString(L"Test");
CStringA str;
str.Empty();
str = bstrText;

  或

CStringA str(bstrText);

  (7) ANSI、Unicode和宽字符之间的转换

  方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。

  方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如:

TCHAR tstr[] = _T("this is a test");
wchar_t wszStr[] = L"This is a test";
String* str = S”This is a test”;

  方法三,使用ATL 7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式:

  其中,第一个C表示“类”,以便于ATL 3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面是一些示例代码:

LPTSTR tstr= CA2TEX<16>("this is a test");
LPCTSTR tcstr= CA2CT("this is a test");
wchar_t wszStr[] = L"This is a test";
char* chstr = CW2A(wszStr);

13:54 | 添加评论| 固定链接| 引用通告 (0)| 记录它
3月9日

实现树型控件的背景位图

在实现树型控件的背景位图之前,我们首先介绍一下树型控件的基本使用方法。树形控件在系统中大量被使用,例如Windows资源管理器就是一个典型的例子。树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上又允许有一个或多个或没有子结点。
MFC中使用CTreeCtrl类来封装树形控件的各种操作,通过调用BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );创建一个窗口,dwStyle中可以使用以下一些树形控件的专用风格:TVS_HASLINES 在父/子结点之间绘制连线;TVS_LINESATROOT 在根/子结点之间绘制连线;TVS_HASBUTTONS 在每一个结点前添加一个按钮,用于表示当前结点是否已被展开;TVS_EDITLABELS 结点的显示字符可以被编辑;TVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点;TVS_DISABLEDRAGDROP 不允许Drag/Drop;TVS_NOTOOLTIPS 不使用ToolTip显示结点的显示字符。
在树形控件中每一个结点都有一个句柄(HTREEITEM),同时添加结点时必须提供的参数是该结点的父结点句柄(其中根Root结点只有一个,既不可以添加也不可以删除),利用HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST )可以添加一个结点,pszItem为显示的字符,hParent代表父结点的句柄,当前添加的结点会排在hInsertAfter表示的结点的后面,返回值为当前创建的结点的句柄。
如果你希望在每个结点前添加一个小图标,就必需先调用CTreeCtrl类的成员函数CImageList* SetImageList( CImageList * pImageList, int nImageListType ),指明当前控件所使用的图像列表(ImageList),nImageListType为TVSIL_NORMAL。在调用完成后控件中使用图片以设置的ImageList中图片为准。然后调用HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST)添加结点,其中参数nImage为结点没被选中时所使用图片序号,nSelectedImage为结点被选中时所使用图片序号。
此外CTreeCtrl还提供了一些函数用于得到/修改控件的状态:
·HTREEITEM GetSelectedItem( )将返回当前选中的结点的句柄;
·BOOL SelectItem( HTREEITEM hItem )将选中指明结点;
·BOOL GetItemImage( HTREEITEM hItem, int& nImage, int& nSelectedImage ) / BOOL SetItemImage( HTREEITEM hItem, int nImage, int nSelectedImage )用于得到/修改某结点所使用图标索引;
·CString GetItemText( HTREEITEM hItem ) /BOOL SetItemText( HTREEITEM hItem, LPCTSTR lpszItem )用于得到/修改某一结点的显示字符;
·BOOL DeleteItem( HTREEITEM hItem )用于删除某一结点,BOOL DeleteAllItems( )将删除所有结点。
此外如果想遍历树可以使用下面的函数:
·HTREEITEM GetRootItem( )得到根结点;
·HTREEITEM GetChildItem( HTREEITEM hItem )得到子结点;
·HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem )得到指明结点的上/下一个兄弟结点;
·HTREEITEM GetParentItem( HTREEITEM hItem )得到父结点。
树形控件的消息映射使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode为通知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void OnXXXTree(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于树形控件可能取值和对应的数据结构为:
·TVN_SELCHANGED 在所选中的结点发生改变后发送,所用结构:NMTREEVIEW;
·TVN_ITEMEXPANDED 在某结点被展开后发送,所用结构:NMTREEVIEW;
·TVN_BEGINLABELEDIT 在开始编辑结点字符时发送,所用结构:NMTVDISPINFO;
·TVN_ENDLABELEDIT 在结束编辑结点字符时发送,所用结构:NMTVDISPINFO;
·TVN_GETDISPINFO 在需要得到某结点信息时发送,(如得到结点的显示字符)所用结构:NMTVDISPINFO;
对于Visual C++ MFC提供的标准树型控件CTreeCtrl来说,并不支持背景位图,所以如果需要实现背景位图就需要先让其在内存CDC对象上对TREEVIEW缺省绘图,然后在选择背景位图,与缺省位图合成,即采用贴图的方式,把标准的TREEVIEW窗口贴在底图上。这个操作在内存中完成。同时为了避免闪烁,必须重载OnItemexpanding()和OnItemexpanded()这两个函数。SetRedraw函数主要保证其不要在子节点弹出时重画,而是在子节点已经扩展后重画。为此,例程中定义了一个CTreeCtrl类的子类CmyTreeCtrl,并重载了以下几个成员函数:
BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
void CMyTreeCtrl::OnPaint()
void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)
   二、编程步骤
1、 启动Visual C++6.0,生成一个基于对话框的项目Tree,在框架上放置一个树形控制件,其ID标志符为:IDC_TREE1;
2、 创建CmyTreeCtrl类后,使用CLASSWIZARD为其添加消息映射:
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED,OnItemexpanded) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
  消息响应函数:
afx_msg void OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);
  3、 将树型控件与CmyTreeCtrl类建立关联,在对话框中添加变量CMyTreeCtrl m_CtrlTree;
4、 制作一个准备作为树形控件背景的位图;
5、 修改对话框的初始化函数BOOL CTreeDlg::OnInitDialog();
6、 添加代码,编译运行程序。 
三、实现代码

/
#if !defined(AFX_TREEDLG_H__D82DB384_F574_44A7_96DA_6EC9068E22B1__INCLUDED_)
#define AFX_TREEDLG_H__D82DB384_F574_44A7_96DA_6EC9068E22B1__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/// CTreeDlg dialog
#include "MyTreeCtrl.h"
class CTreeDlg : public CDialog
{
 // Construction
 public:
  CTreeDlg(CWnd* pParent = NULL); // standard constructor

  // Dialog Data
  //{{AFX_DATA(CTreeDlg)
   enum { IDD = IDD_TREE_DIALOG };
   CMyTreeCtrl m_CtrlTree;
  //}}AFX_DATA

  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CTreeDlg)
   protected:
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  //}}AFX_VIRTUAL

  // Implementation
 protected:
  HICON m_hIcon;

  // Generated message map functions
  //{{AFX_MSG(CTreeDlg)
   virtual BOOL OnInitDialog();
   afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
   afx_msg void OnPaint();
   afx_msg HCURSOR OnQueryDragIcon();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

#endif

// MyTreeCtrl.cpp : implementation file

#include "StdAfx.h"
#include "Tree.h"
#include "MyTreeCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// CMyTreeCtrl

CMyTreeCtrl::CMyTreeCtrl()
{}

CMyTreeCtrl::~CMyTreeCtrl()
{}

BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
 //{{AFX_MSG_MAP(CMyTreeCtrl)
  ON_WM_PAINT()
  ON_WM_ERASEBKGND()
  ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
  ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CMyTreeCtrl message handlers
BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
{
 // if this is not the first call then delete gdi objects
 if( m_bitmap.m_hObject != NULL )
  m_bitmap.DeleteObject();

  HBITMAP hbmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
LpszResource, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);

 if( hbmp == NULL )
  return FALSE;
 m_bitmap.Attach( hbmp );
 return TRUE;
}

LRESULT CMyTreeCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 // TODO: Add your specialized code here and/or call the base class
 return CTreeCtrl::WindowProc(message, wParam, lParam);
}

void CMyTreeCtrl::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 CRect rcclient;
 GetClientRect(&rcclient);

 // create a compatible memory dc
 CDC memdc;
 memdc.CreateCompatibleDC(&dc);
 CBitmap bitmap;
 bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
 memdc.SelectObject( &bitmap );
 CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);
 CDC maskdc;
 maskdc.CreateCompatibleDC(&dc);
 CBitmap maskbitmap;
 maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
 maskdc.SelectObject( &maskbitmap );
 maskdc.BitBlt( 0, 0, rcclient.Width(), rcclient.Height(), &memdc,
 rcclient.left, rcclient.top, SRCCOPY);
 CBrush brush;
 brush.CreatePatternBrush(&m_bitmap);
 dc.FillRect(rcclient, &brush);
 memdc.SetBkColor(RGB(0,0,0));
 memdc.SetTextColor(RGB(255,255,255));
 memdc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left,  rcclient.top, SRCAND);
 dc.SetBkColor(RGB(255,255,255));
 dc.SetTextColor(RGB(0,0,0));
 dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left, rcclient.top, SRCAND);
 dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &memdc, rcclient.left, rcclient.top,SRCPAINT);
 brush.DeleteObject();
}

BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)
{
 // TODO: Add your message handler code here and/or call default
 return TRUE;
}

void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
{
 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
 // TODO: Add your control notification handler code here
 Invalidate();
 SetRedraw(TRUE);
 *pResult = 0;
}

void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
 // TODO: Add your control notification handler code here
 SetRedraw(FALSE);

 *pResult = 0;
}

///
BOOL CTreeDlg::OnInitDialog()
{
 CDialog::OnInitDialog();
 // Add "About..." menu item to system menu.
 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);
 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu-> AppendMenu(MF_SEPARATOR);
   pSysMenu-> AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }
 // Set the icon for this dialog. The framework does this automatically
 // when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE); // Set big icon
 // TODO: Add extra initialization here
 m_CtrlTree.SetBKImage("IDB_BITMAP1");
 SetIcon(m_hIcon, FALSE); // Set small icon
 TVINSERTSTRUCT tvInsert;
 tvInsert.hParent = NULL;
 tvInsert.hInsertAfter = NULL;
 tvInsert.item.mask = TVIF_TEXT;
 tvInsert.item.pszText = _T("Visual C++编程实例");
 HTREEITEM hCountry = m_CtrlTree.InsertItem(&tvInsert);
 HTREEITEM hPA = m_CtrlTree.InsertItem(TVIF_TEXT,
 _T("文章中心"), 0, 0, 0, 0, 0, hCountry, NULL);
 HTREEITEM hWA = m_CtrlTree.InsertItem(_T("代码中心"),0, 0, hCountry, hPA);
 m_CtrlTree.InsertItem(_T("全屏幕程序的实现"), hPA, TVI_SORT);
 m_CtrlTree.InsertItem(_T("实现窗口的任意分割"), hPA, TVI_SORT);
 m_CtrlTree.InsertItem(_T("实现菜单的自绘"), hPA, TVI_SORT);
 m_CtrlTree.InsertItem(_T("实现全屏幕显示的代码"), hWA, TVI_SORT);
 m_CtrlTree.InsertItem(_T("窗口任意分割的代码"), hWA, TVI_SORT);
 m_CtrlTree.InsertItem(_T("菜单自绘代码"), hWA, TVI_SORT);
 m_CtrlTree.Expand(hCountry,TVE_EXPAND);
 return TRUE; // return TRUE unless you set the focus to a control
}

   四、小结

  到此为止,本例通过实现树形控件的背景位图介绍了一些树视图控件编程方法,包括树视图控件的建立、节点值的赋予等。当然,它应用的方面很广,使用方法也很多。这里仅仅是涉及到了构建树视图控件的基本框架,读者朋友们可以在此基础上,可进行扩展,从而完成更强大的功能,感兴趣的读者不妨自己扩展该控件试试。

vc++.NET调用oracle10g相关推荐

  1. 来总结一下在VC中调用COM组件的方法

    来总结一下在VC中调用COM组件的方法(大家来补充) [问题点数:50分,结帖人_foo] http://bbs.csdn.net/topics/50319093 发表于: 2004-04-17 16 ...

  2. VC输出调用出错信息

    VC输出调用出错信息 很多时候要使用GetLastError函数来获取函数调用的出错代码,但仅仅是代码并不够,我们还需要知道错误代码所代表的具体信息.在<Windows核心编程>中提到过一 ...

  3. C#与VC相互调用之VC调用C#的DLL库

    介绍 在之前的博文 C#与VC相互调用之C#调用VC的DLL https://blog.csdn.net/xinxin_2011/article/details/86704660 里面讲了C#程序如何 ...

  4. VC中调用并获取外部程序输出

    VC上调用外部程序的方法大家应该很熟悉,比如ShellExecute,CreateProcess. 例子: system("D://adb.exe devices >c://temp. ...

  5. VC++ ADO调用存储过程方法

    一.调用基本过程 关于ADO调用存储过程一般是按照以下步骤进行: 1.生成并初始化一个_CommandPtr对象:指定CommandType为存储过程. 2.生成调用存储过程需要的参数,这些参数都是_ ...

  6. vc只能调用matlab子函数,Vc++6.0调用matlab的数学库函数

    Vc++6.0调用matlab的数学库函数 前段时间在摸索如何在VC++6.0当中调用Matlab的里的数学库函数.当时弄得我很是郁闷,现在想想,自已走了很多弯路,原来,是如些的简单.所以,与出来和大 ...

  7. 如何在VC中调用第三方lib库(step by step)

    我们以调用Kvaser的库文件为例. 第三方的库一般会提供两个文件,一个是库文件.一个是头文件. Kvaser的库文件为canlib32.lib . 头文件为canlib.h 该库文件里,提供了一个名 ...

  8. vc只能调用matlab子函数,VC调用matlab函数

    最近在学习matlab,先试一个VC调用matlab函数的简单例子 用的是VC++6.0,matlab7.8也就是matlabR2009 首先在matlab下设置环境 >> mbuild ...

  9. VC如何调用DLL文件

    调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同.Windows提供了两种将DLL映像到进程地址空间的方法: 1. 隐式的加载 ...

最新文章

  1. 使用mybatis-generator-core实现自动创建项目
  2. NodeJS安装及部署(Linux系统)
  3. visual studio 2015安装 无法启动程序,因为计算机丢失D3DCOMPILER_47.dll 的解决方法
  4. 从事人工智能要学计算机什么专业,人工智能专业需要什么学历
  5. Qt学习之C++基础
  6. BinaryViewer(二进制查看器)使用教程(附下载)
  7. 常用模板 UPD12/4
  8. HJQ巨佬のTwelveFold Way 手稿电子版
  9. 计算机宏如何设置方法,excel 如何启用宏的方法,以及如何设置excel启用宏
  10. SQL题目练习---三表联查
  11. 原创 | DDD领域驱动设计第一话
  12. 关于流程管理的这些事:项目流程及方法工具
  13. 中华好诗词大学季第二季(五)
  14. java利用ffmpeg将amr、caf转mp3格式
  15. 详细 | 图神经网络从入门到入门
  16. Android ObjectAnimator类:手把手带你自定义属性动画
  17. 程序人生--2010年(60)
  18. 网站加入百度云加速后,出现Error520源站返回未知错误怎么办?
  19. 微信小程序scroll-into-view实现页面定位
  20. 细说Java性能测试第一课 Jmeter导读

热门文章

  1. 如何用 Redis 查询 “附近的人” ?
  2. 简单几步解决svchost占用内存过高问题
  3. debussy和nlint常用快捷键
  4. matlab专业代做hslogic,MATLAB代做|FPGA代做--OLA算法的仿真与分析
  5. Spring | 深入理解面向切面编程(AOP)
  6. windows 消息处理
  7. 2018年北京理工大学计算机学院保研夏令营机试A组
  8. 南京廖华里mysql测试题1答案_MySQL数据库考试试题及答案
  9. 如何利用命令查询优化网站收录状况
  10. 江苏图采之证件照上传