近日用VC寫一個GDI相關的程式時,一不小心栽了跟頭,害得我浪費了整整一天的時間來debug!!
跟頭1:COLORREF的high-order byte
我在處理圖片的透明色是,用到了如下代碼:
COLORREF color1 = ....;
COLORREF color2 = ....;
if (color1 = = color2)
{
......
}
可是很奇怪的是,兩種顏色明明是一樣的,可if的判斷條件就是不滿足!!!最後發現是COLORREF的high-order byte 的問題. 我們知道RGB三色共佔用了3個位元組,剩餘的1個位元組對顏色來說是無效的,但對 "==" 比較來說就有效了!!原來我的color1和color2的high-order byte不相同!!其實,按照MSDN的說法,這個Byte必須為0的,不過好像不為0也不影響GDI的繪圖,就是比較時出問題.
於是我寫了一個宏,NO_HIGH_BYTE_COLOR
#define NO_HIGH_BYTE_COLOR(clr) ((clr)&0x00FFFFFF) //取出沒有high-order byte 的COLORREF值(置high-order byte為0)
然後把判斷處該為:
if (NO_HIGH_BYTE_COLOR(color1) = = NO_HIGH_BYTE_COLOR(color2))
{
......
}
以防萬一.
跟頭2:{}和局部變數
這個就比較弱智了.呵呵,純粹是自己粗心
我寫的一個畫字串的函數(DrawText API的擴充,可以指定字型,背景顏色等,但是測試發現有連續運行幾百次後出現字型錯誤和花屏(win98下如此.但奇怪的是GID資源泄漏在XP下似乎沒有影響,容錯性好???......),根據經驗,很明顯就是資源泄漏了.經過排除,最後鎖定了下面這個成員函數,但怎麼看都看不出問題,最後還是同事"一語驚醒夢中人",幫我找出了錯誤.呵呵,錯在哪裡?自己看代碼吧.注意紅色部分......
class CCanvas : public CDC
......
int CCanvas::DrawString(const CString &str, LPRECT lpRect, UINT uFormat, HFONT hFont, COLORREF clrText, BOOL blTrans, COLORREF clrBk)
{
int nOldBk = SetBkMode(blTrans ? TRANSPARENT : OPAQUE);
int nOldBkColor = SetBkColor(clrBk);
COLORREF clrOldTextColor = SetTextColor(clrText);
HFONT hOldFont = NULL;
if (hFont)
{
HFONT hOldFont = (HFONT)SelectObject(hFont);
}
int nResult = DrawText(str,lpRect, uFormat);
//Set Back
if (hFont)
{
SelectObject(hOldFont);
}
SetTextColor(clrOldTextColor);
SetBkColor(nOldBkColor);
SetBkMode(nOldBk);
return nResult;
}
函數中任何地方都可以聲明變數是C++的一個特性,確實很方便,但有時也會帶來隱患,當然,前提是你足夠粗心:)我個人認為,這樣的情況(內層範圍的變數和外層範圍的變數重名)編譯器是應該來個warning的,不知道這個是不是違背了"C的精神"所以才沒有做....呵呵,不僅懷念起Pascal的var了......