??xml version="1.0" encoding="utf-8" standalone="yes"?>
刚接触VC~程的朋友往往对许多数据类型的转换感到qh不解Q本文将介绍一些常用数据类型的使用?/p>
我们先定义一些常见类型变量借以说明 int i = 100; 一、其它数据类型{换ؓ字符?/p>
_bstr_t变量 二、字W串转换为其它数据类?br>strcpy(temp,"123"); 短整?int) CComBSTR变量 _bstr_t变量 四、BSTR、_bstr_t与CComBSTR CComBSTR与_bstr_t对大量的操作W进行了重蝲Q可以直接进?,!=,=={操作,所以用非常方ѝ?br>特别是_bstr_t,大家使用它?/p>
对于不马上赋值的VARIANTQ最好先用Void VariantInit(VARIANTARG FAR* pvarg);q行初始?其本质是vt讄为VT_EMPTY,下表我们列Dvt与常用数据的对应关系: Byte bVal; // VT_UI1. ҎProgID得到CLSID ҎCLSID得到ProgID 七、ANSI与Unicode ANSI转换到Unicode Ҏ息的处理中我们经帔R要将WPARAM或LPARAM{?2位数据(DWORD)分解成两?6位数据(WORD),例如Q?br>LPARAM lParam; MFC应用E序中指针的使用
long l = 2001;
float f=300.2;
double d=12345.119;
char username[]="E佩?;
char temp[200];
char *buf;
CString str;
_variant_t v1;
_bstr_t v2;
短整?int)
itoa(i,temp,10);///i转换为字W串攑օtemp?最后一个数字表C十q制
itoa(i,temp,2); ///按二q制方式转换
长整?long)
ltoa(l,temp,10);
点?float,double)
用fcvt可以完成转换,q是MSDN中的例子:
int decimal, sign;
char *buffer;
double source = 3.1415926535;
buffer = _fcvt( source, 7, &decimal, &sign );
q行l果:source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0
decimal表示数点的位置,sign表示W号:0为正敎ͼ1?
CString变量
str = "2008北京奥运";
buf = (LPSTR)(LPCTSTR)str;
BSTR变量
BSTR bstrValue = ::SysAllocString(L"E序?);
char * buf = _com_util::ConvertBSTRToString(bstrValue);
SysFreeString(bstrValue);
AfxMessageBox(buf);
delete(buf);
CComBSTR变量
CComBSTR bstrVar("test");
char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str);
AfxMessageBox(buf);
delete(buf);
_bstr_tcd是对BSTR的封装,因ؓ已经重蝲?操作W,所以很Ҏ使用
_bstr_t bstrVar("test");
const char *buf = bstrVar;///不要修改buf中的内容
AfxMessageBox(buf);
通用Ҏ(针对非COM数据cd)
用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);
i = atoi(temp);
长整?long)
l = atol(temp);
点(double)
d = atof(temp);
CString变量
CString name = temp;
BSTR变量
BSTR bstrValue = ::SysAllocString(L"E序?);
...///完成对bstrValue的?br>SysFreeString(bstrValue);
CComBSTRcd变量可以直接赋?br>CComBSTR bstrVar1("test");
CComBSTR bstrVar2(temp);
_bstr_tcd的变量可以直接赋?br>_bstr_t bstrVar1("test");
_bstr_t bstrVar2(temp);
三、其它数据类型{换到CString
使用CString的成员函数Format来{?例如:
整数(int)
str.Format("%d",i);
点?float)
str.Format("%f",i);
字符串指?char *){已l被CString构造函数支持的数据cd可以直接赋?br>str = username;
对于Format所不支持的数据cdQ可以通过上面所说的关于其它数据cd转化到char *的方法先转到char *Q然后赋值给CString变量?/p>
CComBSTR 是ATL对BSTR的封装,_bstr_t是C++对BSTR的封?BSTR?2位指?但ƈ不直接指向字串的~冲区?br>char *转换到BSTR可以q样:
BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上comutil.h和comsupp.lib
SysFreeString(bstrValue);
反之可以使用
char *p=_com_util::ConvertBSTRToString(b);
delete p;
具体可以参考一Q二D落里的具体说明?/p>
五、VARIANT 、_variant_t ?COleVariant
VARIANT的结构可以参考头文gVC98\Include\OAIDL.H中关于结构体tagVARIANT的定义?br>对于VARIANT变量的赋|首先lvt成员赋|指明数据cdQ再对联合结构中相同数据cd的变量赋|举个例子Q?br>VARIANT va;
int a=2001;
va.vt=VT_I4;///指明整型数据
va.lVal=a; ///赋?/p>
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.
DECIMAL FAR* pdecVal // VT_BYREF|VT_DECIMAL.
IUnknown FAR* punkVal; // VT_UNKNOWN.
IDispatch FAR* pdispVal; // VT_DISPATCH.
SAFEARRAY FAR* parray; // VT_ARRAY|*.
Byte 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; // Generic ByRef.
char cVal; // VT_I1.
unsigned short uiVal; // VT_UI2.
unsigned long ulVal; // VT_UI4.
int intVal; // VT_INT.
unsigned int uintVal; // VT_UINT.
char FAR * pcVal; // VT_BYREF|VT_I1.
unsigned short FAR * puiVal; // VT_BYREF|VT_UI2.
unsigned long FAR * pulVal; // VT_BYREF|VT_UI4.
int FAR * pintVal; // VT_BYREF|VT_INT.
unsigned int FAR * puintVal; //VT_BYREF|VT_UINT.
_variant_t是VARIANT的封装类Q其赋值可以用强制类型{换,其构造函C自动处理q些数据cd?br>使用旉加上#include <comdef.h>
例如Q?br>long l=222;
ing i=100;
_variant_t lVal(l);
lVal = (long)i;
COleVariant的用与_variant_t的方法基本一P请参考如下例子:
COleVariant v3 = "字符?, v4 = (long)1999;
CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;
六、其它一些COM数据cd
HRESULT CLSIDFromProgID( LPCOLESTR lpszProgID,LPCLSID pclsid);
CLSID clsid;
CLSIDFromProgID( L"MAPI.Folder",&clsid);
WINOLEAPI ProgIDFromCLSID( REFCLSID clsid,LPOLESTR * lplpszProgID);
例如我们已经定义?CLSID_IApplication,下面的代码得到ProgID
LPOLESTR pProgID = 0;
ProgIDFromCLSID( CLSID_IApplication,&pProgID);
...///可以使用pProgID
CoTaskMemFree(pProgID);//不要忘记释放
UnicodeUCؓ宽字W型字串,COM里用的都是Unicode字符丌Ӏ?/p>
(1)通过Lq个宏来实现Q例? CLSIDFromProgID( L"MAPI.Folder",&clsid);
(2)通过MultiByteToWideChar函数实现转换,例如:
char *szProgID = "MAPI.Folder";
WCHAR szWideProgID[128];
CLSID clsid;
long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));
szWideProgID[lLen] = '\0';
(3)通过A2W宏来实现,例如:
USES_CONVERSION;
CLSIDFromProgID( A2W(szProgID),&clsid);
Unicode转换到ANSI
(1)使用WideCharToMultiByte,例如:
// 假设已经有了一个Unicode ?wszSomeString...
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
(2)使用W2A宏来实现,例如:
USES_CONVERSION;
pTemp=W2A(wszSomeString);
八、其?/p>
WORD loValue = LOWORD(lParam);///取低16?br>WORD hiValue = HIWORD(lParam);///取高16?/p>
对于16位的数据(WORD)我们可以用同LҎ分解成高低两?位数?BYTE),例如:
WORD wValue;
BYTE loValue = LOBYTE(wValue);///取低8?br>BYTE hiValue = HIBYTE(wValue);///取高8?/p>
两个16位数据(WORDQ合?2位数?DWORD,LRESULT,LPARAM,或WPARAM)
LONG MAKELONG( WORD wLow, WORD wHigh );
WPARAM MAKEWPARAM( WORD wLow, WORD wHigh );
LPARAM MAKELPARAM( WORD wLow, WORD wHigh );
LRESULT MAKELRESULT( WORD wLow, WORD wHigh );
两个8位的数据(BYTE)合成16位的数据(WORD)
WORD MAKEWORD( BYTE bLow, BYTE bHigh );
从R(red),G(green),B(blue)三色得到COLORREFcd的颜色?br>COLORREF RGB( BYTE byRed,BYTE byGreen,BYTE byBlue );
例如COLORREF bkcolor = RGB(0x22,0x98,0x34);
从COLORREFcd的颜色值得到RGB三个颜色?br>BYTE Red = GetRValue(bkcolor); ///得到U颜?br>BYTE Green = GetGValue(bkcolor); ///得到lK?br>BYTE Blue = GetBValue(bkcolor); ///得到兰颜?/p>
九、注意事?br>假如需要用到ConvertBSTRToString此类函数,需要加上头文gcomutil.h,q在setting中加入comsupp.lib或者直接加?pragma comment( lib, "comsupp.lib" )
2) 在App中获得MainFrame指针
3) 在View中获得MainFrame指针
4) 获得ViewQ已建立Q指?/u>
5) 获得当前文档指针
6) 获得状态栏与工h指针
7) 获得状态栏与工h变量
8) 在Mainframe获得菜单指针
9) 在Q何类中获得应用程序类
10) 从文档类取得视图cȝ指针(1)
11) 在App中获得文档模板指?/u>
12) 从文档模板获得文档类指针
13) 在文档类中获得文档模板指?/u>
14) 从文档类取得视图cȝ指针(2)
15) 从一个视囄取得另一视图cȝ指针
VC中编E对于刚刚开始学习的同学Q最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决?br>下面文字主要是个人在~程中指针用的一些体会,说的不当的地方请指正?br>一般我们用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架Q无论是多文档还是单文档Q都存在指针获取和操作问题?br>下面q节内容主要是一般的框架Q然后再讲多U程中的指针使用。用到的类需要包含响应的头文件。首先一般获得本c?视,文档Q对话框都支?实例指针thisQ用this的目的,主要可以通过cM的函数向其他cL者函C发指针,以便于在非本cM操作和用本cM的功能?br> 1Q?在View中获得Doc指针
CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文档?/pre>
2) 在App中获得MainFrame指针
CWinApp 中的 m_pMainWnd变量是MainFrame的指?br>也可以:
CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
3) 在View中获得MainFrame指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
4) 获得ViewQ已建立Q指?
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
CyouView *pView=(CyouView *)pMain->GetActiveView();
5) 获得当前文档指针
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
6) 获得状态栏与工h指针
CStatusBar * pStatusBarQ?CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
7) 如果框架中加入工h和状态栏变量q可以这?
(CMainFrame *)GetParent()->m_wndToolBar;
(CMainFrame *)GetParent()->m_wndStatusBar;
8) 在Mainframe获得菜单指针
CMenu *pMenu=m_pMainWnd->GetMenu();
9) 在Q何类中获得应用程序类
用MFC全局函数AfxGetApp()获得?br> 10) 从文档类取得视图cȝ指针
我是?a target=_blank>http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,从文档获得视囄指针目的一般ؓ了控制同一文档的多个视囄定位问题Q我的体会特别是文字处理CEditView当生多个视囄Ӟq个功能是非帔R要的?
CDocumentcL供了两个函数用于视图cȝ定位Q?br>GetFirstViewPosition()和GetNextView()
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
注意QGetNextView()括号中的参数用的是引用方式,因此执行后值可能改变?br>GetFirstViewPosition()用于q回W一个视图位|(q回的ƈ非视囄指针Q而是一个POSITIONcd|QGetNextView()有两个功能:q回下一个视囄的指针以及用引用调用的方式来改变传入的POSITIONcd参数的倹{很明显Q在TestE序中,只有一个视囄Q因此只需这两个函数调用一ơ即可得到CTestView的指针如下(需定义一个POSITIONl构变量来辅助操作)Q?
CTestView* pTestView;
POSITION pos=GetFirstViewPosition();
pTestView=GetNextView(pos);
q样Q便可到了CTestViewcȝ指针pTestView.执行完几句后Q变量pos=NULL,因ؓ没有下一个视囄Q自然也没有下一个视囄的POSITION.但是q几条语句太单,不具有太强的通用性和安全特征Q当象前面说的那P当要在多个视图ؓ中返回某个指定类的指针时Q我们需要遍历所有视囄Q直到找到指定类为止。判断一个类指针指向的是否某个类的实例时Q可用IsKindOf()成员函数时行查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
卛_查pView所指是否是CTestViewcR?br>
有了以上基础Q我们已l可以从文档cd得Q何类的指针。ؓ了方便,我们其作ؓ一个文档类的成员函敎ͼ它有一个参敎ͼ表示要获得哪个类的指针。实现如下:
CView* CTestDoc::GetView(CRuntimeClass* pClass)
{
CView* pView;
POSITION pos=GetFirstViewPosition();
while(pos!=NULL){
pView=GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com");
return NULL;
}
return pView;
}
其中用了两次视图cȝ成员函数IsKindOf()来判断,是因为退出while循环有三U可能:
1.pos为NULLQ即已经不存在下一个视囄供操作;
2.pView已符合要求?br>
1?同是满。这是因为GetNextView()的功能是当前视图指针改变成一个视囄位置同时q回当前视图指针Q因此pos是pView的下一个视囄的POSITION,完全有可能既是pos==NULL又是pViewW合需要。当所需的视图是最后一个视图是最后一个视囄时就如引。因此需采用两次判断?br>使用该函数应遵@如下格式Q以取得CTestView指针ZQ:
CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
RUNTIME_CLASS是一个宏Q可以简单地理解它的作用Q将cȝ名字转化为CRuntimeClass为指针?br>至于强制cd转换也是Z安全Ҏ考虑的,因ؓ从同一个基cM间的指针cd是互相兼容的。这U强制类型{换也许ƈ不必要,但能避免一些可能出现的ȝ?br>
3.从一个视囄取得另一视图cȝ指针 l合1?Q很Ҏ得出视图cM间互相获得指针的ҎQ就是用文档cM中{Q先?的方法得到文档类的指针,再用2的方法,以文档类的视囑֮位函数取得另一个视囄。同P可以实现成一个函敎ͼ
Q假设要从CTestAView中取得指向其它视囄的指针)
CView* CTestAView::GetView(CRuntimeClass* pClass)
{
CTestDoc* pDoc=(CTestDoc*)GetDocument();
CView* pView;
POSITION pos=pDoc->GetFirstViewPosition();
while(pos!=NULL){
pView=pDoc->GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.");
return NULL;
}
return pView;
}
q个函数?中的GetView()相比Q一是多了第一句以取得文档cL针,二是在GetFirstViewPosition()和GetNextView()前加上了文档cL针,以表C它们是文档cL员函数?br>有了此函敎ͼ当要从CTestAView中取得CTestBView的指针时Q只需如下Q?
CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));
11Q对于单文档中也可以加入多个文档模板Q但是一般的开发就使用MDI方式开发多文档模板Q其Ҏ与上q视囄获取Ҏ很接q,q里E做解释Q如果不清楚Q请查阅MSDNQ(以下四个内容Q?1?2?3?4Q来源:http://sanjianxia.myrice.com/vc/vc45.htmQ?br>
可以用CWinApp::GetFirstDocTemplatePostion获得应用E序注册的第一个文档模板的位置Q?br>利用该值来调用CWinApp::GetNextDocTemplate函数Q获得第一个CDocTemplate对象指针?
POSITION GetFirstDocTemplate( ) const;
CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;
W二个函数返回由pos 标识的文档模ѝPOSITION是MFC定义的一个用于P代或对象指针索的倹{通过q两个函敎ͼ应用E序可以遍历整个文档模板列表。如果被索的文档模板是模板列表中的最后一个,则pos参数被置为NULL?br> 12Q一个文档模板可以有多个文档Q每个文档模杉K保留q维护了一个所有对应文档的指针列表?
用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一个文档的位置Qƈ用POSITIONg为CDocTemplate::GetNextDoc的参数来重复遍历与模板相关的文档列表。函数原形ؓQ?
viaual POSITION GetFirstDocPosition( ) const = 0;
visual CDocument *GetNextDoc(POSITION & rPos) const = 0;
如果列表为空Q则rPos被置为NULL. 13Q在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针。函数原形如下:
CDocTemplate * GetDocTemplate ( ) const;
如果该文档不属于文档模板理Q则q回gؓNULL? 14)一个文档可以有多个视。每一个文档都保留q维护一个所有相兌的列表。CDocument::AddView一个视q接到文档上Q将该视加入到文档相联系的视的列表中Qƈ视的文档指针指向该文档。当有File/New、File/Open、Windows/New或Window/Split的命令而将一个新创徏的视的对象连接到文档上时Q?MFC会自动调用该函数Q框枉过文档/视的l构文档和视联pv来。当ӞE序员也可以Ҏ自己的需要调用该函数?
Virtual POSITION GetFirstViewPosition( ) const;
Virtual CView * GetNextView( POSITION &rPosition) cosnt;
应用E序可以调用CDocument::GetFirstViewPositionq回与调用文档相联系的视的列表中的第一个视的位|,q调用CDocument::GetNextViewq回指定位置的视QƈrPositon的值置为列表中下一个视的POSITION倹{如果找到的视ؓ列表中的最后一个视Q则rPosition|ؓNULL. 15)从一个视囄取得另一视图cȝ指针
q个应用在多视的应用E序中很多见Q一般如果自己在ȝ序或者主框架中做好变量记P也可以获得,q有比较通用的就是用文档cM中{Q以文档cȝ视图遍历定位Q取得另一个视囄。这个功能从本文W?0中可以得到?br>
q些资料大部分都是从|上和MSDN中获得的Q写q个文档是Z让大家不用再LQ列出标题,可操作性更强?br>
{
CDC maskDC, ImageDC;
maskDC.CreateCompatibleDC(pDestDC);
ImageDC.CreateCompatibleDC(pDestDC);
CBitmap maskBMP;
maskBMP.CreateBitmap(nWidth, nHeight, 1, 1, NULL);//创徏单色掩码位图
CBitmap *pOldBMP = ImageDC.SelectObject(pBitmap);
CBitmap *maskOldBMP = maskDC.SelectObject(&maskBMP);
ImageDC.SetBkColor(clr);// 讄透明?br> maskDC.BitBlt(0, 0, nWidth, nHeight, &ImageDC, nXsrc, nYsrc, SRCCOPY);
//讄背景色ؓ黑色Q前景色为白Ԍ掩码位图与原位囄"?
ImageDC.SetBkColor(RGB(0, 0, 0));
ImageDC.SetTextColor(RGB(255, 255, 255));
ImageDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, nXsrc, nYsrc, SRCAND);
//讄背景色ؓ白色Q前景色为黑Ԍ掩码位图与背景q行“?#8221;q算
pDestDC->SetBkColor(RGB(255, 255, 255));
pDestDC->SetTextColor(RGB(0, 0, 0));
pDestDC->BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, nXsrc, nYsrc, SRCAND);
// "?q算,生成最l效?br> pDestDC->BitBlt(nXDest, nYDest, nWidth, nHeight, &ImageDC, nXsrc, nYsrc, SRCPAINT);
if (pOldBMP) ImageDC.SelectObject(pOldBMP);
ImageDC.DeleteDC();
if (maskOldBMP) maskDC.SelectObject(maskOldBMP);
maskDC.DeleteDC();
if (maskBMP.m_hObject) maskBMP.DeleteObject();
}
BOOL TransparentBlt( HDC hdcDest, // 目标DC int nXOriginDest, // 目标X偏移 int nYOriginDest, // 目标Y偏移 int nWidthDest, // 目标宽度 int hHeightDest, // 目标高度 HDC hdcSrc, // 源DC int nXOriginSrc, // 源XL int nYOriginSrc, // 源YL int nWidthSrc, // 源宽? int nHeightSrc, // 源高? UINT crTransparent // 透明?COLORREFcd );使用CZ:
CBitmap FootballBMP; FootballBMP.LoadBitmap(IDB_FOOTBALLBMP); CDC ImageDC; ImageDC.CreateCompatibleDC(pDC); CBitmap *pOldImageBMP = ImageDC.SelectObject(&FootballBMP); TransparentBlt(pDC->m_hDC, 0, 0, 218, 199, ImageDC.m_hDC, 0, 0, 218, 199, RGB(0,0,0xff)); ImageDC.SelectObject(pOldImageBMP);二、实现TransparentBlt函数
HBITMAP hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 建立单色位图 SetBkColor(hImageDC, RGB(0,0,0xff)); // 讄背景色ؓ蓝色 BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY); // 拯到hMaskDCq样球位图中蓝色区域在掩码位图中成了白Ԍ其它区域为黑Ԍ此时hMaskBMP 如下?
SetBkColor(hImageDC, RGB(0,0,0)); SetTextColor(hImageDC, RGB(255,255,255)); BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);q样Q掩码位图中背景Ԍ黑色Q的区域在hImageBMP中被保留Q前景色Q白Ԍ的部分变为黑艌Ӏ?此时hImageBMP 如下?
SetBkColor(hdcDest,RGB(255,255,255)); SetTextColor(hdcDest,RGB(0,0,0)); BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);掩码中白色区域(数据??#8220;?#8221;l果不变Q背景保持不变Q黑色区域变成黑Ԍ此时背景昄如下:
BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);q样将球l制到背景上了?br>
void TransparentBlt2( HDC hdcDest, // 目标DC int nXOriginDest, // 目标X偏移 int nYOriginDest, // 目标Y偏移 int nWidthDest, // 目标宽度 int nHeightDest, // 目标高度 HDC hdcSrc, // 源DC int nXOriginSrc, // 源XL int nYOriginSrc, // 源YL int nWidthSrc, // 源宽? int nHeightSrc, // 源高? UINT crTransparent // 透明?COLORREFcd ) { HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); // 创徏兼容位图 HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 创徏单色掩码位图 HDC hImageDC = CreateCompatibleDC(hdcDest); HDC hMaskDC = CreateCompatibleDC(hdcDest); hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP); hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP); // 源DC中的位图拯C时DC? if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc) BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY); else StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY); // 讄透明? SetBkColor(hImageDC, crTransparent); // 生成透明区域为白Ԍ其它区域为黑色的掩码位图 BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY); // 生成透明区域为黑Ԍ其它区域保持不变的位? SetBkColor(hImageDC, RGB(0,0,0)); SetTextColor(hImageDC, RGB(255,255,255)); BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND); // 透明部分保持屏幕不变Q其它部分变成黑? SetBkColor(hdcDest,RGB(255,255,255)); SetTextColor(hdcDest,RGB(0,0,0)); BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND); // "?q算,生成最l效? BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT); // 清理、恢? SelectObject(hImageDC, hOldImageBMP); DeleteDC(hImageDC); SelectObject(hMaskDC, hOldMaskBMP); DeleteDC(hMaskDC); DeleteObject(hImageBMP); DeleteObject(hMaskBMP); }2.3 TransparentBlt的另外一个版?TransparentBltU
bool TransparentBltU( HDC dcDest, // handle to Dest DC int nXOriginDest, // x-coord of destination upper-left corner int nYOriginDest, // y-coord of destination upper-left corner int nWidthDest, // width of destination rectangle int nHeightDest, // height of destination rectangle HDC dcSrc, // handle to source DC int nXOriginSrc, // x-coord of source upper-left corner int nYOriginSrc, // y-coord of source upper-left corner int nWidthSrc, // width of source rectangle int nHeightSrc, // height of source rectangle UINT crTransparent // color to make transparent ) { if (nWidthDest < 1) return false; if (nWidthSrc < 1) return false; if (nHeightDest < 1) return false; if (nHeightSrc < 1) return false; HDC dc = CreateCompatibleDC(NULL); HBITMAP bitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc, BITSPIXEL), NULL); if (bitmap == NULL) { DeleteDC(dc); return false; } HBITMAP oldBitmap = (HBITMAP)SelectObject(dc, bitmap); if (!BitBlt(dc, 0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY)) { SelectObject(dc, oldBitmap); DeleteObject(bitmap); DeleteDC(dc); return false; } HDC maskDC = CreateCompatibleDC(NULL); HBITMAP maskBitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL); if (maskBitmap == NULL) { SelectObject(dc, oldBitmap); DeleteObject(bitmap); DeleteDC(dc); DeleteDC(maskDC); return false; } HBITMAP oldMask = (HBITMAP)SelectObject(maskDC, maskBitmap); SetBkColor(maskDC, RGB(0,0,0)); SetTextColor(maskDC, RGB(255,255,255)); if (!BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS)) { SelectObject(maskDC, oldMask); DeleteObject(maskBitmap); DeleteDC(maskDC); SelectObject(dc, oldBitmap); DeleteObject(bitmap); DeleteDC(dc); return false; } SetBkColor(dc, crTransparent); BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT); SetBkColor(dc, RGB(0,0,0)); SetTextColor(dc, RGB(255,255,255)); BitBlt(dc, 0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND); HDC newMaskDC = CreateCompatibleDC(NULL); HBITMAP newMask; newMask = CreateBitmap(nWidthDest, nHeightDest, 1, GetDeviceCaps(newMaskDC, BITSPIXEL), NULL); if (newMask == NULL) { SelectObject(dc, oldBitmap); DeleteDC(dc); SelectObject(maskDC, oldMask); DeleteDC(maskDC); DeleteDC(newMaskDC); DeleteObject(bitmap); DeleteObject(maskBitmap); return false; } SetStretchBltMode(newMaskDC, COLORONCOLOR); HBITMAP oldNewMask = (HBITMAP) SelectObject(newMaskDC, newMask); StretchBlt(newMaskDC, 0, 0, nWidthDest, nHeightDest, maskDC, 0, 0, nWidthSrc, nHeightSrc, SRCCOPY); SelectObject(maskDC, oldMask); DeleteDC(maskDC); DeleteObject(maskBitmap); HDC newImageDC = CreateCompatibleDC(NULL); HBITMAP newImage = CreateBitmap(nWidthDest, nHeightDest, 1, GetDeviceCaps(newMaskDC, BITSPIXEL), NULL); if (newImage == NULL) { SelectObject(dc, oldBitmap); DeleteDC(dc); DeleteDC(newMaskDC); DeleteObject(bitmap); return false; } HBITMAP oldNewImage = (HBITMAP)SelectObject(newImageDC, newImage); StretchBlt(newImageDC, 0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc, nHeightSrc, SRCCOPY); SelectObject(dc, oldBitmap); DeleteDC(dc); DeleteObject(bitmap); BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, newMaskDC, 0, 0, SRCAND); BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, newImageDC, 0, 0, SRCPAINT); SelectObject(newImageDC, oldNewImage); DeleteDC(newImageDC); SelectObject(newMaskDC, oldNewMask); DeleteDC(newMaskDC); DeleteObject(newImage); DeleteObject(newMask); return true; }
首先Q创建对话框资源Q在对话框资源编辑器内生成一?/span>Dialog资源Qƈ其风格Q?/span>StyleQ属性必设|ؓChildQ不能设|ؓOverlapped?/span>PopupQ否则运行肯定出错;至于边界属性则随用戯己喜Ƣ,一般都是选择None。其余属性也随用户选择Q一般没有特D要求还是选择默认的好?/span>
其次Q创建基?/span>CDialog的派生类Q打开ClassWizardQؓ以上创徏的资源添加一个以CDialog为基cȝzc(因ؓClassWizard没有?/span>CDialogBar列在基类目录清单中,所以用户只能先?/span>CDialogcL生)?/span>
再次Q修Ҏ生类?/span>CDialogBar为基c:通常需要手工修改几处代码,在本例中zcMCDataStatus命名。(注:以后讲解中凡是手工改动都是以灰背景显C)
1?/span> 在头文g中修改承关p?/span>
?/span>class CDataStatus : public CDialog 改ؓclass CDataStatus : public CDialogBar
2?/span> 在代码文件中修该构造函数承关p?/span>
?/span>CDataStatus::CDataStatus(CWnd* pParent /*=NULL*/)
: CDialog(CDataStatus::IDD, pParent)
{
//{{AFX_DATA_INIT(CDataStatus)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
改ؓ
CDataStatus::CDataStatus(CWnd* pParent /*=NULL*/)
{
//{{AFX_DATA_INIT(CDataStatus)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
3?/span> ?/span>DDXl定函数中的l承关系L
卛_void CDataStatus::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCurrentCheckDlg)
………..
//}}AFX_DATA_MAP
}
改ؓ
void CDataStatus::DoDataExchange(CDataExchange* pDX)
{
//{{AFX_DATA_MAP(CCurrentCheckDlg)
………….
//}}AFX_DATA_MAP
}
4?/span> 重新初始化函敎ͼq个相当重要Q如果不q么做的话,DDX函数形同虚设Q当然用L工具条如果没有用?/span>DDX的话当然可以不加q段代码Q:
首先?/span>ClassWizard?/span>MessageMap中对消息?/span>CDataStatuscȝWM_INITDIALOG消息d处理函数默认名ؓOnInitDialog?/span>
其次手工修改代码如下Q?/span>
1?/span> d消息映射函数。由于对话框形式的初始化函数消息q未加蝲到消息映内Qؓ此我们需要手工添加,要不然代码无法拦截该工具条的初始化消息,形式如下Q?/span>
?/span>BEGIN_MESSAGE_MAP(CDataStatus, CDialogBar)
//{{AFX_MSG_MAP(CDataStatus)
.......
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
改ؓQ?/span>
BEGIN_MESSAGE_MAP(CDataStatus, CDialogBar)
//{{AFX_MSG_MAP(CDataStatus)
.......
ON_MESSAGE(WM_INITDIALOG,OnInitDialog)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
2?/span> 修改OnInitDialog函数Q此函数q未传递参敎ͼ但是在这里我们需要让它传递参敎ͼ代码如下修改Q当然头文g中,对声明也要做修改Q在q里׃作赘qCQ?/span>
?/span>BOOL CDataStatus::OnInitDialog()
{
CDialogBar::OnInitDialog();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
改ؓQ?/span>
BOOL CDataStatus::OnInitDialog(UINT wParam,LONG lParam)
{
//CDialogBar::OnInitDialog();
// TODO: Add extra initialization here
BOOL bRet = HandleInitDialog(wParam,lParam);
if (!UpdateData(FALSE))
{
TRACE("InitCDataStatus FailedQ?/span>");
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
二?/span>在框架类中实现该zcȝ对象?/span>
首先Q在框架cȝ头文件内声明实例对象Q本例实例化Q?/span>CDataStatus m_wndDataStatus;当然头文件中不可避免要包含新zcȝ头文件?/span>
其次Q在框架cȝOnCreate函数内创建对象ƈ对象绑定对话框资源。Ş式与创徏ToolBar原理一P本例实例如下Q?/span>
if (!m_wndDataStatus.Create(this,IDD_DATASTATUS,WS_VISIBLE|WS_CHILD
|CBRS_SIZE_DYNAMIC|CBRS_BOTTOM,IDD_DATASTATUS))
{
TRACE0("Failed to create CDataStatus bar!");
return -1;
}
再次Q最为关键的一点就是重写框架类?/span>OnCmdMsg虚函数。如果不重写该函敎ͼ那么不光DDX功能无法实现Q连最基本?/span>OnCommand事g都无法实现。而且q得手工d代码QŞ式如下:
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
改ؓQ?/span>
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
if (m_wndDataStatus.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))
return TRUE;
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
三?/span>?/span>CReBar上添加该实例化对?/span>
其实q一步倒是相当单,只是自己以前没用q这个类Q所以在q里也顺便用了一下?/span>
首先Q在框架cȝ头文件中?/span>CRebar声明一个对象,?/span>CReBar m_wndReBar;
其次Q在框架cȝ代码文g中的OnCreat函数体内Q生成对象,代码如下Q?/span>
if (!m_wndReBar.Create(this,RBS_BANDBORDERS,WS_CHILD |
WS_VISIBLE| CBRS_BOTTOM|WS_CLIPSIBLINGS|WS_CLIPCHILDREN))
{
TRACE0("Failed to create Rebar \n");
return -1;
}
再次Q就是将所要添加的toolbar以及新生成的CDataStatus对象m_wndDataStatus加进Rebar的对?/span>m_wndReBar中,代码如下Q?/span>
m_wndReBar.AddBar(&m_wndDataStatus,NULL,NULL,
RBBS_GRIPPERALWAYS|RBBS_FIXEDBMP);