vc小知识2

VC中的SAFEARRAY类型
SAFEARRAY
  SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元 素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。在VARIANT的vt成员的 值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。 SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。 
  使用SafeArray的具体步骤: 
  方法一: 
  包装一个SafeArray: 
  (1). 定义变量,如: 
  VARIANT varChunk; 
  SAFEARRAY *psa; 
  SAFEARRAYBOUND rgsabound[1]; 
  (2). 创建SafeArray描述符: 
  uIsRead=f.Read(bVal,ChunkSize);//read array from a file. 
  if(uIsRead==0)break; 
  rgsabound[0].cElements =uIsRead; 
  rgsabound[0].lLbound = 0; 
  psa = SafeArrayCreate(VT_UI1,1,rgsabound); //创建一个SAFEARRAY数组
  (3). 放置数据元素到SafeArray: 
  for(long index=0;index<uIsRead;index++) 
  { 
  if(FAILED(SafeArrayPutElement(psa,&index,&bVal))) 
  ::MessageBox(NULL,"出毛病了。","提示",MB_OK | MB_ICONWARNING); 
  } 
  一个一个地放,挺麻烦的。 
  (4). 封装到VARIANT内: 
  varChunk.vt = VT_ARRAY|VT_UI1; 
  varChunk.parray = psa; 
  这样就可以将varChunk作为参数传送出去了。 
  读取SafeArray中的数据的步骤: 
  (1). 用SafeArrayGetElement一个一个地读 
  BYTE buf[lIsRead]; 
  for(long index=0;index<lIsRead;index++) 
  { 
  ::SafeArrayGetElement(varChunk.parray,&index,buf+index); 
  } 
  就读到缓冲区buf里了。 
  方法二: 
  使用SafeArrayAccessData直接读写SafeArray的缓冲区: 
  (1). 读缓冲区: 
  BYTE *buf; 
  SafeArrayAccessData(varChunk.parray, (void **)&buf); 
  f.Write(buf,lIsRead); 
  SafeArrayUnaccessData(varChunk.parray); 
  (2). 写缓冲区: 
  BYTE *buf; 
  ::SafeArrayAccessData(psa, (void **)&buf); 
  for(long index=0;index<uIsRead;index++) 
  { 
  buf=bVal; 
  } 
  ::SafeArrayUnaccessData(psa); 
  varChunk.vt = VT_ARRAY|VT_UI1; 
  varChunk.parray = psa; 
  这种方法读写SafeArray都可以,它直接操纵SafeArray的数据缓冲区,比用SafeArrayGetElement和 SafeArrayPutElement速度快。特别适合于读取数据。但用完之后不要忘了调用::SafeArrayUnaccessData (psa),否则会出错的。 
  如果SafeArray中存的是BSTR的二维数组,则代码如下:
  if(varChunk.vt = VT_ARRAY | VT_BSTR)
  {
  BSTR* buf;
  long LBound; // 数组下界
  long UBound; // 数组上界
  SafeArrayAccessData(varChunk.parray, (void **)&buf); 
  SafeArrayGetLBound(varChunk.parray, 1, &LBound);
  SafeArrayGetUBound(varChunk.parray, 1, &UBound);
  for(long i = LBound; i < UBound; i ++)
  {
  CString str(buf);
  MessageBox(str);
  }
  SafeArrayUnaccessData(varChunk.parray);
  }
以上摘自百度 http://baike.baidu.com/view/1907445.htm
常用的SafeArray处理函数。

1.1.1    建立SafeArray


SAFEARRAY* SafeArrayCreate( VARTYPE vt,      //数组中元素的类型
unsigned int cDims,                                           //数组的维数
SAFEARRRAYBOUND * rgsabound    //指向SAFEARRAYBOUND结构体的指针,用于指定将要分配的数组的大小
);
SAFEARRAY SafeArrayCreateEx(VARTYPE vt,unsigned int cDims,SAFEARRRAYBOUND * rgsabound,PVOID pvExtra);
 
SAFEARRAY* SafeArrayCreateVector(VARTYPE vt, long lLbound, unsigned int cElements);
SAFEARRAY* SafeArrayCreateVectorEx(VARTYPE vt, long lLbound,unsigned int cElements,
LPVOID pvExtra);

SafeArrayCreate用于建立多维普通数组。SafeArrayCreateEx用于建立多维自定义类型或接口指针数组。SafeArrayCreateVector用于建立一维普通数组。SafeArrayCreateVectorEx用于建立一维自定义类型或接口指针数组。

1.1.2            释放数组


HRESULT SafeArrayDestroy(SAFEARRAY * psa);

SafeArrayDestroy用于释放创建的SafeArray数组。

1.1.3            访问数据


HRESULT SafeArrayAccessData(SAFEARRAY * psa, void HUGEP ** ppvData);
HRESULT SafeArrayUnaccessData(SAFEARRAY * psa);

SafeArrayAccessData函数返回数组的指针。而SafeArrayUnaccessData释放通过SafeArrayAccessData所取得的指针。

 


15:20 |  添加评论 |  固定链接 |  写入日志 |  VC学习
4月18日
MFC中无边框窗口的拖动的实现
    

    对于一般的窗口(指窗口本身没有被FLASH等其自身之外的任何控件覆盖的窗口)而言的做法是:为窗口类添加WM_LBUTTONDOWN消息响应

    void   CXXXXDialog::OnLButtonDown(UINT   nFlags,   CPoint   point)  
{  PostMessage(WM_NCLBUTTONDOWN,   HTCAPTION,   MAKELPARAM(point.x,   point.y));  
} 要记得添加消息映射,不然这个代码是不起作用的。

     但是,若整个窗口都被FLASH等完全覆盖,这是若添加此消息响应函数,将不会响应该消息,原因在于当用鼠标点击窗口时,WM_LBUTTONDOWN消息被覆盖在窗口表面的FLASH所捕获因此得不到处理。这种情况下应该换一种处理办法,将发送WM_NCLBUTTONDOWN消息放到PreTranslateMessage函数中进行处理,这样原窗口就可以捕获到WM_NCLBUTTONDOWN消息,从而可以实现无边框窗口的拖动了。

代码如下:

BOOL C***Dlg::PreTranslateMessage(MSG* pMsg)

{

if (pMsg->message == WM_LBUTTONDOWN)

 {

         PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);

 }

 return CDialog::PreTranslateMessage(pMsg);

}

由以上两种情况可以看出,要实现无边框窗口的拖动,主要是WM_NCLBUTTONDOWN和HTCAPTION参数的组合。具体为什么是这两个参数组合可以实现无边框窗口的拖动还不明白,有待进一步学习。


16:27 |  添加评论 |  固定链接 |  写入日志 |  VC学习
MFC中去掉View类边框的办法
      所做的模块主界面是一个视类窗口,视类窗口以外的菜单之类的都被去掉了。由于视类窗口的四周都用FLASH覆盖,因此视类窗口中的边框就和FLASH很不协调,影响了整个界面的美观。于是,要求必须去掉视类的边框。从网上找了很久,谢天谢地,总算找到了一个有效的办法,搬到自己的代码中试了试,还真的奏效!作为备忘,将其置于此。
      
先要去掉C***view的边框:
首先在C***类中重载PreCreateWindow函数,代码如下:   
  BOOL   C***View::PreCreateWindow(CREATESTRUCT&   cs)   
  {   
  //   TODO:   Modify   the   Window   class   or   styles   here   by   modifying   
  //     the   CREATESTRUCT   cs   
   cs.style   &=~WS_BORDER;//加入的代码   
   return   CView::PreCreateWindow(cs);   
  }   
  然后再去掉外部Frame的客户区边框,代码如下:   
  BOOL   CMainFrame::PreCreateWindow(CREATESTRUCT&   cs)   
  {   
  if(   !CFrameWnd::PreCreateWindow(cs)   )   
  return   FALSE;   
  //   TODO:   Modify   the   Window   class   or   styles   here   by   modifying   
  //     the   CREATESTRUCT   cs   
    
  cs.dwExStyle&=~WS_EX_CLIENTEDGE;//加入的代码,一定要在CFrameWnd::PreCreateWindow(cs)之后执行   
  return   TRUE;   
  }
摘自 http://topic.csdn.net/t/20051219/15/4468019.html
   在此,感谢提供此解决方案的朋友!感谢CSDN!
13:52 |  添加评论 |  固定链接 |  写入日志 |  VC学习
4月2日
(转)Visual C ADO数据库编程入门

http://hi.baidu.

一、在VC++中使用ADO编程
ADO实际上就是由一组Automation对象构成的组件,因此可以象使用其它任何Automation对象一样使用ADO。ADO中最重要的对象 有三个:Connection、Command和Recordset,它们分别表示连接对象、命令对象和记录集对象。如果您熟悉使用MFC中的ODBC类 (CDatabase、CRecordset)编程,那么学习ADO编程就十分容易了。
使用ADO编程时可以采用以下三种方法之一:
1、使用预处理指令#import
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "EndOfFile") 
但要注意不能放在stdAfx.h文件的开头,而应该放在所有include指令的后面。否则在编译时会出错。
程序在编译过程中,VC++会读出msado15.dll中的类型库信息,自动产生两个该类型库的头文件和实现文件msado15.tlh和 msado15.tli(在您的Debug或Release目录下)。在这两个文件里定义了ADO的所有对象和方法,以及一些枚举型的常量等。我们的程序 只要直接调用这些方法就行了,与使用MFC中的COleDispatchDriver类调用Automation对象十分类似。
2、使用MFC中的CIDispatchDriver
就是通过读取msado15.dll中的类型库信息,建立一个COleDispatchDriver类的派生类,然后通过它调用ADO对象。
3、直接用COM提供的API
如使用如下代码:
CLSID clsid; 
HRESULT hr = ::CLSIDFromProgID(L"ADODB.Connection", &clsid); 
if(FAILED(hr))
{...}
::CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IDispatch, (void **)
&pDispatch); 
if(FAILED(hr))
{...} 
以上三种方法,第一和第二种类似,可能第一种好用一些,第三种编程可能最麻烦。但可能第三种方法也是效率最高的,程序的尺寸也最小,并且对ADO的控制能力也最强。
据微软资料介绍,第一种方法不支持方法调用中的默认参数,当然第二种方法也是这样,但第三种就不是这样了。采用第三种方法的水平也最高。当你需要绕过ADO而直接调用OLE DB底层的方法时,就一定要使用第三种方法了。
ADO编程的关键,就是熟练地运用ADO提供的各种对象(object)、方法(method)、属性(property)和容器(collection)。另外,如果是在MS SQL或Oracle等大型数据库上编程,还要能熟练使用SQL语言。
二、使用#import方法的编程步骤
这里建议您使用#import的方法,因为它易学、易用,代码也比较简洁。
1、添加#import指令
打开stdafx.h文件,将下列内容添加到所有的include指令之后:
#include //Include support for VC++ Extensions
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "adoEOF") 
其中icrsint.h文件包含了VC++扩展的一些预处理指令、宏等的定义,用于COM编程时使用。
2、定义_ConnectionPtr型变量,并建立数据库连接
建立了与数据库服务器的连接后,才能进行其他有关数据库的访问和操作。ADO使用Connection对象来建立与数据库服务器的连接,所以它相当于 MFC中的CDatabase类。和CDatabase类一样,调用Connection对象的Open方法即可建立与服务器的连接。
数据类型 _ConnectionPtr实际上就是由类模板_com_ptr_t而得到的一个具体的实例类,其定义可以到msado15.tlh、comdef.h 和comip.h这三个文件中找到。在msado15.tlh中有:
_COM_SMARTPTR_TYPEDEF(_Collection, __uuidof(_Collection)); 
经宏扩展后就得到了_ConnectionPtr类。_ConnectionPtr类封装了Connection对象的Idispatch接口指针, 及一些必要的操作。我们就是通过这个指针来操纵Connection对象。类似地,后面用到的_CommandPtr和_RecordsetPtr类型也 是这样得到的,它们分别表示命令对象指针和记录集对象的指针。
(1)、连接到MS SQL Server
注意连接字符串的格式,提供正确的连接字符串是成功连接到数据库服务器的第一步,有关连接字符串的详细信息参见微软MSDN Library光盘。
本例连接字符串中的server_name,database_name,user_name和password在编程时都应该替换成实际的内容。
_ConnectionPtr pMyConnect=NULL; 
HRESULT hr=pMyConnect.CreateInstance(__uuidof(Connection))); 
if(FAILED(hr))return; 
_bstr_t strConnect="Provider=SQLOLEDB; Server=server_name; "
"Database=database_name; uid=user_name; pwd=password; "; 
//connecting to the database server now:
try{pMyConnect->Open(strConnect,"","",NULL); }
catch (_com_error &e)
{
::MessageBox(NULL,e.Description(),"警告",MB_OK │ MB_ICONWARNING); 

注意Connection对象的Open方法中的连接字符串参数必须是BSTR或_bstr_t类型。另外,本例是直接通过OLE DB Provider建立连接,所以无需建立数据源。
(2)、通过ODBC Driver连接到Database Server连接字符串格式与直接用ODBC编程时的差不多:
_bstr_t strConnect="DSN=datasource_name; Database=database_name; uid=user_name; pwd=password; "; 
此时与ODBC编程一样,必须先建立数据源。
3、定义_RecordsetPtr型变量,并打开数据集
定义_RecordsetPtr型变量,然后通过它调用Recordset对象的Open方法,即可打开一个数据集。所以Recordset对象与MFC中的CRecordset类类似,它也有当前记录、当前记录指针的概念。如:
_RecordsetPtr m_pRecordset; 
if(!FAILED(m_pRecordset.CreateInstance( __uuidof( Recordset )))
{
m_pDoc->m_initialized=FALSE; 
return; 
}
try{
m_pRecordset->Open(_variant_t("mytable"),
_variant_t((IDispatch *)pMyConnect,true), adOpenKeyset,
adLockOptimistic, adCmdTable); 
}
catch (_com_error &e)
{
::MessageBox(NULL,"无法打开mytable表。","提示",
MB_OK │ MB_ICONWARNING); 

Recordset对象的Open方法非常重要,它的第一个参数可以是一个SQL语句、一个表的名字或一个命令对象等等;第二个参数就是前面建立的连接对象的指针。此外,用Connection和Command对象的Execute方法也能得到记录集,但是只读的。
4、读取当前记录的数据
我认为读取数据的最方便的方法如下:
try{
m_pRecordset->MoveFirst(); 
while(m_pRecordset->adoEOF==VARIANT_FALSE) 
{
//Retrieve column's value: 
CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem
(_variant_t("name"))->Value); 
short cAge=(short)(m_pRecordset->Fields->GetItem
(_variant_t("age"))->Value); 
//Do something what you want to do:
......
m_pRecordset->MoveNext(); 
}
}//try
catch (_com_error &e)
{
CString str=(char*)e.Description(); 
::MessageBox(NULL,str+"\n又出毛病了。","提示",
MB_OK │ MB_ICONWARNING); 

本例中的name和age都是字段名,读取的字段值分别保存在sName和cAge变量内。例中的Fields是Recordset对象的容器, GetItem方法返回的是Field对象,而Value则是Field对象的一个属性(即该字段的值)。通过此例,应掌握操纵对象属性的方法。例如,要 获得Field 对象的Value属性的值可以直接用属性名Value来引用它(如上例),但也可以调用Get方法,例如:
CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem
(_variant_t("name"))->GetValue()); 
从此例还可以看到,判断是否到达记录集的末尾,使用记录集的adoEOF属性,其值若为真即到了结尾,反之则未到。判断是否到达记录集开头,则可用BOF属性。
另外,读取数据还有一个方法,就是定义一个绑定的类,然后通过绑定的变量得到字段值(详见后面的介绍)。
5、修改数据
方法一:
try{
m_pRecordset->MoveFirst(); 
while(m_pRecordset->adoEOF==VARIANT_FALSE) 

m_pRecordset->Fields->GetItem
(_variant_t("姓名"))->Value=_bstr_t("赵薇"); 
......
m_pRecordset->Update(); 
m_pRecordset->MoveNext(); 
}
}//try 
改变了Value属性的值,即改变了字段的值。
方法二:
m_pRecordset->Fields->GetItem
(_variant_t("姓名"))->PutValue(_bstr_t("赵薇")); 
方法三:就是用定义绑定类的方法(详见后面的介绍)。
6、添加记录
新记录添加成功后,即自动成为当前记录。AddNew方法有两种形式,一个含有参数,而另一个则不带参数。
方法一(不带参数):
// Add new record into this table:
try{
if(!m_pRecordset->Supports(adAddNew)) return; 
m_pRecordset->AddNew(); 
m_pRecordset->Fields->GetItem
(_variant_t("姓名"))->Value=_bstr_t("赵薇"); 
m_pRecordset->Fields->GetItem
(_variant_t("性别"))->Value=_bstr_t("女"); 
m_pRecordset->Fields->GetItem
(_variant_t("age"))->Value=_variant_t((short)20); 
m_pRecordset->Fields->GetItem
(_variant_t("marry"))->Value=_bstr_t("未婚"); 
m_pRecordset->Update(); 
}//try
catch (_com_error &e)
{
::MessageBox(NULL, "又出毛病了。","提示",MB_OK │ MB_ICONWARNING); 
}
VC中的GetKeyState和GetAsyncKeyState的区别
VC中添加组合快捷键时,经常会用到函数GetKeyState或函数GetAsyncKeyState,但是这两个函数有什么区别呢?各自都该如何使用呢?从网上搜了一下,找到如下资料
……………………………………………………………………………………………………………………………………………………
使用::GetKeyState()返回一个short型的数,short型是16位有符号的数据类型,如果要查询的键被按下,返回值最高位被置1,则这个数表示负数,所以可以用<0或>0来判断。   
   0x8000是16进制数,用2进制表示为1000    0000    0000    0000,    &是按位与   
   同样,如果键被按下,返回值最高位为1,则1xxx    xxxx    xxxx    xxxx    &    1000    0000    0000    0000得到的结果为1,否则为0,同样可以判断最高位的值。   
   需要说明的是,::GetKeyState()只能在键盘消息处理程序中使用,因为它只有在线程从消息队列中读取键盘消息时才会报告被查询键的状态,如果需要在键盘消息处理程序以外查询按键状态,则需要使用::GetAsyncKeyState来代替
……………………………………………………………………………………………………………………………………………………
GetAsyncKeyState查询指定键的实时状态
      
使用后发现两者的区别(以组合键CTRL+A为例):
      if (nChar ==0x041)&& (GetKeyState(VK_CONTROL)&0x8000)   //ctrl+A
     {
                //执行相应的操作
      }
      的效果是按下CTRL和A,实现指定的操作;(只有先按下CTRL然后按A或者同时按下二者,才能执行指定的操作)
     而如果用 
     if (nChar ==0x041)&& GetAsyncKeyState(VK_CONTROL))   //ctrl+A
     {
                //执行相应的操作
      }
    得到的效果将是:按下CTRL,然后按下A,可以执行指定的操作,但是与上述的区别在于:
    按下CTRL后隔了一段时间(可能是几秒或更长时间),然后再回过来按A键也会执行指定的操作(这样不是期望的效果)。
 
    以上只是发现的一个区别,可能这两个函数还有其他的区别,但是还未遇到,因此在此也无法列出。以后发现了再加上吧!
    MFC还有很多东西需要学习和理解,好好努力吧!为自己加油!^_^
VC中将SWF文件作为资源加载到工程中播放
步骤:
1.添加新资源到工程中:右击资源视图中的.rc,选择添加资源,然后选择自定义,弹出新建自定义资源对话框,在资源类型编辑框 中填入“SWF”一定要带引号,然后点击确定;或者在添加资源对话框中选择导入,在弹出的导入对话框中的文件类型中选择“所有文件(*.*)”否则将不会出现要添加的新资源类型,选择要添加的.swf文件后,弹出新建自定义资源类型对话框,按照上面所 说的同样的办法,即可完成新类型资源的添加;
2.程序中加载资源:首先根据资源ID加载资源,然后根据资源创建临时SWF文件,以后就对该临时SWF文件进行操作;
 CString type=L"swf";
 HRSRC res=FindResource(NULL,MAKEINTRESOURCE(IDR_SWF1),type);
 HGLOBAL gl=LoadResource(NULL, res);
 LPVOID lp=LockResource(gl);
 CString tempfile=L"temp.swf";
 HANDLE fp=CreateFile(tempfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 DWORD a;
 if (!WriteFile(fp,lp,SizeofResource(NULL,res),&a,NULL))
   {
    MessageBox(L"write file failed!");
    return FALSE;
   }
   CloseHandle(fp);
   FreeResource(gl);
   m_flash.Create(NULL, WS_CHILD | WS_VISIBLE, CRect(0,0, 500,290), this, 100);
   //获取文件的当前路径
    TCHAR strCurDrt[500];
    int nLen = ::GetCurrentDirectory(500,strCurDrt);
    if( strCurDrt[nLen]!='\\' )
    {
        strCurDrt[nLen++] = '\\';
        strCurDrt[nLen] = '\0';
    }
    CString strFileName = strCurDrt;
   strFileName +=tempfile;
   m_flash.LoadMovie(0,strFileName);
//注意,LoadMovie的第二个参数必须是绝对路径,即包含当前目录所在的路径和文件名,否则将无法正常加载
   m_flash.Play();
3.删除临时文件
    由于临时文件Temp.swf是在程序运行过程中从应用程序的资源中提取出来的,因此在程序退出之前需要将其删除。一般是在消息WM_DESTORY的响应函数里通过DeleteFile()函数来加以实现的。  
VS2005中出现的warning C4819问题的解决方案
      摘自: http://supersoftmm3d.blogspot.com/2008/09/vcwarning-c4819.html
      中文VC8的程序员可能会常常看见这个warning:warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失.这个警告没有什么坏影响,但会影响心情:) 所以还是要治理一下:哪个文件出现这个警告错误,打开它, 用VS2005的查找替换功能,打开允许正则表达式选项,选择当前窗口,查找替换 \n 为 \n , 然后,这个世界就清净了。原因: 查找的 \n 是跨平台的回车,替换的 \n 却是当前代码页的回车了。
     我试过了,该方法可用,问题解决。^_^
9:44 |  添加评论 |  固定链接 |  写入日志 |  VC学习
1月16日
使位图背景透明的程序代码
VC中有时需要将一幅位图的背景设置为透明。MFC中有TransparentBlt函数可以实现这一功能,实现起来也比较简单,但是该函数存在一个问题,那就是系统的问题。经实践发现,在Vista ,2003系统下都可以对位图实现背景透明,并对位图进行正确缩放,但是,在XP系统下(单显示器XP系统下好像可以正常缩放)却不能正常缩放,只是从原始位图中截取指定区域大小的一块进行显示而并不是缩放。为此,在《MFC Windows 程序设计》一书中找到了另一个功能和TransparentBlt类似的用户自定义函数MakeTransparent(函数名是我自己定义的,书上是DrawTransparent)。该函数可以实现TransparentBlt函数的功能,同时能解决TransparentBlt函数存在的问题,在Vista,2003,多显示器的XP系统下都能使位图背景透明,同时正确缩放。(当然,可能该函数也存在某些不足与局限性,但是目前我还没有遇到。^_^).为便于以后查阅,放置于此。
 
/*参数说明:
 *bitmap:为要处理的位图的指针,
 *rect:为指定的要显示位图的区域
 *color:为指定为透明的颜色,即位图的背景颜色
 *pDC:当然就是最终显示位图的设备上下文了,也可以是与显示位图的DC兼容的DC
 */
void MakeTransparent(CBitmap* bitmap,CRect rect,COLORREF color,CDC* pDC)
{
    CSize dispRes;
    dispRes.cx = rect.Width();
    dispRes.cy = rect.Height();
    BITMAP bmp;
    bitmap->GetBitmap(&bmp);
    CPoint size(dispRes.cx,dispRes.cy);
    pDC->DPtoLP(&size);
    CPoint org(rect.left,rect.top);
    pDC->DPtoLP(&org);
    //创建一个内存DC,并将位图选入其中
    CDC dcImage;
    CDC Imagedc;
    Imagedc.CreateCompatibleDC(pDC);
    dcImage.CreateCompatibleDC(pDC);
    CBitmap* oldBmp=Imagedc.SelectObject(bitmap);
    CBitmap dcbitmap;
    dcbitmap.CreateCompatibleBitmap(&Imagedc,size.x,size.y);
    dcImage.SelectObject(&dcbitmap);
    //dcImage.SetStretchBltMode(HALFTONE); //!!!!!!!!!!!
    dcImage.SetStretchBltMode(COLORONCOLOR);  //!!这一句是我自己添加上去的,若不添加此句,将会出现8或6像素的位图显示时为黑团
    dcImage.StretchBlt(0,0,size.x,size.y,&Imagedc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    dcImage.SetMapMode(pDC->GetMapMode());
    //创建第二个内存DC,并在其中创建一幅AND 掩模
    CDC dcAnd;
    dcAnd.CreateCompatibleDC(pDC);
    dcAnd.SetMapMode(pDC->GetMapMode());
    CBitmap bitmapAnd;
    bitmapAnd.CreateBitmap(size.x,size.y,1,1,NULL);//创建单色位图,作为“与”掩码
    CBitmap* oldBitmapAnd=dcAnd.SelectObject(&bitmapAnd);
    dcImage.SetBkColor(color);//****************
    dcAnd.BitBlt(0,0,size.x,size.y,&dcImage,0,0,SRCCOPY);
    //创建第三个内存DC,在其中创建一幅XOR掩模
    CDC dcXor;
    dcXor.CreateCompatibleDC(pDC);
    dcXor.SetMapMode(pDC->GetMapMode());
    //创建一个和原始位图匹配的位图
    CBitmap bitmapxor;
    bitmapxor.CreateCompatibleBitmap(&dcImage,size.x,size.y);
    CBitmap* oldBitmapxor=dcXor.SelectObject(&bitmapxor);
    //创建“异或”掩码
    dcXor.BitBlt(0,0,size.x,size.y,&dcImage,0,0,SRCCOPY);
    dcXor.BitBlt(0,0,size.x,size.y,&dcAnd,0,0,0x220326);//光栅操作0x220326表示 dst =(NOT src) AND dst
    //将目的矩形中的像素拷贝到一个临时内存DC中
    CDC dcTemp;
    dcTemp.CreateCompatibleDC(pDC);
    dcTemp.SetMapMode(pDC->GetMapMode());
    //创建一个大小和颜色属性都和初始位图匹配的位图,并将其选入临时DC中
    CBitmap bitmaptemp;
    BOOL re = bitmaptemp.CreateCompatibleBitmap(&dcImage,size.x,size.y );
    CBitmap* oldtempbitmap=dcTemp.SelectObject(&bitmaptemp);
    dcTemp.BitBlt(0,0,size.x,size.y,pDC,org.x,org.y,SRCCOPY);
    //在临时内存DC中,通过使用AND 和XOR掩模生成最终图像
    dcTemp.BitBlt(0,0,size.x,size.y,&dcAnd,0,0,SRCAND);
    dcTemp.BitBlt(0,0,size.x,size.y,&dcXor,0,0,SRCINVERT);
    
    //将最终图像贴到屏幕上
    pDC->BitBlt(org.x,org.y,size.x,size.y,&dcTemp,0,0,SRCCOPY);
    //释放位图
    dcTemp.SelectObject(oldtempbitmap);
    dcXor.SelectObject(oldBitmapxor);
    dcAnd.SelectObject(oldBitmapAnd);
    dcImage.SelectObject(oldBmp);     
    dcbitmap.DeleteObject();
    bitmapAnd.DeleteObject();
    bitmapxor.DeleteObject();
    bitmaptemp.DeleteObject();
    dcTemp.DeleteDC();
    dcXor.DeleteDC();
    dcAnd.DeleteDC();
    dcImage.DeleteDC();
    Imagedc.DeleteDC();
}
 
      本来位图背景透明的代码是去年年底就应该好好消化吸收的,可是当时真的是看了很多遍都没有彻底理解,只好将其放置到这里。今天在研究DIB位图时,突然想起DDB位图背景透明的问题,于是再次回头来看这些代码,对其似乎明白了一些。所以在原来的基础上再添加上这次的理解。
      由于0x220326表示dst = (NOT src)AND dst,因此,根据理解,以上函数的基本思想可以用以下式子来简化:(!I&I)XOR(I&P),其中I表示原始位图,P表示屏幕DC位图,!表示取非操作(NOT),&表示AND操作,(!I&I)就相当于光栅操作0x220326,XOR表示异或操作(SRCINVERT)。这样便于理解也便于看。
     希望我这次是真的理解了位图背景透明的原理了,^_^! 当然如果理解不当的话,还恳请高手指教!
VC资源分配、释放表
自己写的一个VC程序,运行过程中发现存在资源泄漏的问题,在网上搜了一下,找到下面的资料,感觉十分有用,于是放到这里。
VC资源分配、释放表

资源                            分配函数                            清除函数                     需要手动清除?

  ======================================================================
  

Accelerators                 LoadAccelerators                 N/A                             No
   
Atoms                          GlobalAddAtom                    GlobalFreeAtom            Yes
   
Bitmaps                        CreateBitmap                       DeleteObject                 Yes *vc小知识2 - wishiduhao - wishiduhao的博客

               CreateBitmapIndirect            DeleteObject                 Yes *
              CreateCompatibleBitmap       DeleteObject                 Yes *
               CreateDIBitmap                    DeleteObject                 Yes *
              CreateDiscardableBitmap       DeleteObject                 Yes *
                  LoadBitmap                         DeleteObject                 Yes

Brushes                        CreateBrushIndirect              DeleteObject                 Yes
                CreateDIBPatternBrush         DeleteObject                 Yes
                CreateHatchBrush                 DeleteObject                 Yes
                CreatePatternBrush               DeleteObject                 Yes
                 CreateSolidBrush                  DeleteObject                 Yes

Carets                          CreateCaret                          DestroyCaret                No #

 

Clipboard                      OpenClipboard                     CloseClipboard              Yes
  

Comms Ports                  OpenComm                         CloseComm                  Yes
  

Cursor                         CreateCursor                       DestroyCursor                     Yes
                 LoadCursor                         N/A                                     No
  

DC                              CreateDC                                   DeleteDC                      Yes
              CreateCompatibleDC                   DeleteDC                      Yes @
                       GetDC                                ReleaseDC                    Yes
                      GetWindowDC                     ReleaseDC                    Yes
                      BeginPaint                           EndPaint                       Yes
  

DialogBox                     CreateDialog                        DestroyWindow            No
                CreateDialogIndirect             DestroyWindow            No
               CreateDialogIndirectParam    DestroyWindow            No
                CreateDialogParam               DestroyWindow            No
  

File                              OpenFile                              _lclose                         No
  

Fonts                           CreateFont                           DeleteObject                 Yes
              CreateFontIndirect                DeleteObject                 Yes
               AddFontResource                 RemoveFontResource    Yes
  

GDIStockObj               GetStockObject                    N/A                             No &
  

Hook                            SetWindowsHook                 UnhookWindowsHook   Yes
  

IC                                CreateIC                              DeleteDC                      Yes
  

Icon                             CreateIcon                           DestroyIcon                 Yes
                 LoadIcon                             N/A                             No
  

Library                         LoadLibrary                         FreeLibrary                   Yes
  

Memory                       AllocDStoCSAlias                 FreeSelector                 Yes
               AllocSelector                       FreeSelector                 Yes
              GlobalAlloc                          GlobalFree                    No
                GlobalDOSAlloc                   GlobalDOSFr                No
                      GlobalFix                      GlobalUnfix                  No
                GlobalLock                          GlobalUnlock                No
               GlobalPageLock                   GlobalPageUnlock         No
              GlobalRealloc                       GlobalFree                    No
              GlobalWire                           GlobalUnwire                No
                LocalAlloc                           LocalFree                     No
                LocalLock                           LocalUnlock                 No
               LocalRealloc                        LocalFree                     No
  

Menu                           CreateMenu                         DestroyMenu                No %
               CreatePopupMenu                DestroyMenu                No %
               LoadMenu                           DestroyMenu                No %
               LoadMenuIndirect                DestroyMenu                No %
               GetSystemMenu                   N/A                             No
  

MetaFile                       CreateMetaFile                     DeleteMetaFile              Yes
  

Palette                          CreatePalette                        DeleteObject                 Yes
  

Pen                              CreatePen                            DeleteObject                 Yes
               CreatePenIndirect                 DeleteObject                 Yes
   

Regions                        CreateEllipticRgn                  DeleteObject                 Yes
                CreateEllipticRgnIndirect       DeleteObject                 Yes
                CreatePolygonRgn                DeleteObject                 Yes
                CreatePolyPolygonRgn          DeleteObject                 Yes
                CreateRectRgn                     DeleteObject                 Yes
                CreateRectRgnIndirect          DeleteObject                 Yes
                CreateRoundRectRgn            DeleteObject                 Yes
  

Resource                      AllocResource                      FreeResource                No
                 FindResource                       N/A                             No
                 LoadResource                      FreeResource                No
                 LockResource                      UnlockResource            No
  

Sound                          OpenSound                          CloseSound                  Yes
  

String                           LoadString                           N/A                             No
  

Thunk                          MakeProcInstance                FreeProcInstance          No
  

Timer                           SetTimer                             KillTimer                      No
  

Window                       CreateWindow                     DestroyWindow            No
               CreateWindowEx                  DestroyWindow            No  

*     位图资源在释放的时候必须从选中它的DC中脱离。
%    当菜单失去焦点和窗口不再关联或者应用程序结束的时候占用资源必须被释放。
@    DC被释放前必须和它关联(选中)的位图取消联系
#     如果脱字符指定了位图,位图必须被释放
&    对DeleteObject的调用不会销毁常规的StockObject(系统内定资源)


MATLAB7.0安装问题
     由于课题是用MATLAB 做的,要得到实验结果必须得安装MATLAB才行。以前在实验室时用的那个是师姐传给我的安装软件,安装很简单,直接点击安装程序即可运行使用,所以以为所有的MATLAB安装都是这么简单,于是对其也没有深入研究过。可是现在换了个机器,换了个系统(以前是XP系统,现在用的是VISTA系统),费了很大劲总算从网上下到了一个可以安装的程序,可结果安装是成功了,点击快捷方式运行却是一打开就自动关闭了。网上搜了一下,终于找到了解决方法。以下贴上解决方法,以作备忘。
MATLAB7.0安装完启动后自动关闭怎么办  因为MATLAB需要用到处理器的数学运算部分,故需要设置一下BLAS(Basic Linear Algebra Subroutines,就是"基础线性几何子程序"的意思)环境变量.首先请确认你的MATLAB的文件夹中有如下文件:atlas_Athlon.dll(AMD系列的请用这个),atlas_P4.dll(P4的用这个),atlas_PIII.dll(P3的用这个),atlas_PII.dll(P2的用这个),这些是对应处理器的数值运算优化文件 
            然后请按如下步骤进行: 
    1、右击我的电脑,选择属性. 
    2、在"高级"选项卡中点击"环境变量" 
    3、在系统变量下面添加如下内容(按"新建"): 
例如: 
       变量名:BLAS_VERSION 
       变量值:E:\Matlab7\bin\win32\atlas_Athlon.dll 
       然后运行你的MATLAB吧!  vc小知识2 - wishiduhao - wishiduhao的博客 
         
     VS2005 断点失效解决办法
    最近使用VS2005时,连续两次遇到设置的断点变得无效,提示“源代码与原始版本不同”,无法命中当前断点,程序也无法跟踪进去,在GOOGLE上搜了一下,总算找到了解决办法。试了试,问题得到了解决。以下是搜集到的相关网站,放在这里收藏:
http://msdn.microsoft.com/zh-cn/library/h6aesyw2(vs.80).aspx
http://qjgl.spaces.live.com/Blog/cns!30809769A632ADA2!119.entry
http://guangqili.spaces.live.com/blog/cns!388692DFE118F6D6!217.entry
VS2005下使用VC,部分断点无效,显示『当前不会命中断点。还没有为该文档加载任何符号』。
试过以下一些方法:
1、无效断点所在的项目和启动项目的设置:项目->属性->配置属性->C/C++->常规->调试信息格式,这里不能为『禁用』;
2、项目->属性->配置属性->链接器->调试->生成调试信息,这里设为『是』;
3、C/C++->优化->优化选择『禁用』;
4、删除解决方案下的.ncb文件;
5、工具->选项->调试->『要求源文件与原始版本完成匹配』去掉勾;
6、最后在上述设置的情况下,重新编译整个解决方案;
7、回过头来,发现原来是一段不会被执行到的代码……
看来,除了VS本身会有bug,自己的代码还是要多检查一下。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值