常常 看到對(duì)MAKEINTRESOURCE的疑問,認(rèn)為怎么能把一個(gè)整數(shù)轉(zhuǎn)化一個(gè)指向字符串的指針?提示下面是這個(gè)宏的定義。
#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
為什么能把一個(gè)一個(gè)ID號(hào)轉(zhuǎn)化一個(gè)字符串指針,理論是不成立的,因?yàn)槿绻麑⑵滢D(zhuǎn)化,將會(huì)是系統(tǒng)不允許的一內(nèi)存空間。
實(shí)際上這個(gè)宏是配合CString 一起來用的。如果單獨(dú)用這個(gè)宏來輸出字符串,比如AfxMessageBox(MAKEINTRESOURCEA(ID))根本不會(huì)是你所想要的字符串輸出。
無論是CString 的構(gòu)造函數(shù)還是賦值運(yùn)算符都會(huì)對(duì)這個(gè)輸入的地址值做一個(gè)處理。
就是調(diào)用CheckImplicitLoad來判斷是否是字符串指針還是資源ID.CheckImplicitLoad的源代碼如下。
bool CheckImplicitLoad( __in_opt const void* pv )
{
bool bRet = false;
if( (pv != NULL) && IS_INTRESOURCE( pv ) )
{
UINT nID = LOWORD( reinterpret_cast< DWORD_PTR >( pv ) );
if( !LoadString( nID ) )
{
ATLTRACE( atlTraceString, 2, _T( "Warning: implicit LoadString(%u) failed\n" ), nID );
}
bRet = true;
}
return( bRet );
}
其中宏IS_INTRESOURCE 的定義是#define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0)
也就是說判斷pv的值是否小于0x10000,如果小于這個(gè)值,證明是一個(gè)資源ID,則將指針強(qiáng)制轉(zhuǎn)換為資源ID,并從資源中加載字符串;如果不是,則認(rèn)為是一個(gè)字符串指針。
我想 MAKEINTRESOURCE 的作用在于與CString的參數(shù)類型兼容。如果是資源ID作一次轉(zhuǎn)化內(nèi)部還是會(huì)將其轉(zhuǎn)化回來。
結(jié)論,MAKEINTRESOURCE 一定要和CString類結(jié)合使用才有意義。