CBitmapButton類使用注意事項(主要是AutoLoad)
1、MFC有一個位圖按鈕類,即為CBitmapButton,能夠實現簡單的按鈕貼圖美化;但是長久沒有使用,今天就遇到一些問題:主要就是CBitmapButton::AutoLoad這個函式的使用,總是出錯,無法正確的載入圖片;現在將需要注意的問題貼出來,以作備份。
2、首先,說明以下不用AutoLoad的初始化方法,我在VS2010下測試成功,完全可以用類嚮導新增一個CBitmapButton型的控制元件變數(即在DoDataExchange關聯控制元件與變數)而不用手動呼叫SubclassDlgItem函式。只需要將預先匯入的點陣圖載入到按鈕類變數中就行了,具體如下:
(1)在對話方塊上放置一個按鈕,修改其自繪(Owner Draw)屬性
(2)利用類嚮導為該按鈕關聯一個控制元件變數m_ctlBtn;
(3)在按鈕控制元件所在的對話方塊類的OnInitDialog函式中新增載入圖片的程式碼:
m_ctlBtn.LoadBitmaps(IDB_UP, IDB_DOWN, IDB_FOCUS, IDB_DISABLE);
m_ctlBtn.SizeToContent();// 根據載入的圖片,調整按鈕大小
(4)關於LoadBitmaps函式,只有第一個引數(即按鈕正常狀態下的點陣圖資源ID)是必須的,其它引數可以不設:
BOOL LoadBitmaps( UINT nIDBitmapResource, UINT nIDBitmapResourceSel(5)OK,這樣就行了= 0, UINT nIDBitmapResourceFocus = 0, UINT nIDBitmapResourceDisabled = 0 );
3、現在在說用AutoLoad函式載入圖片,以及相應的注意點:
(1)關於AutoLoad函式,可以先看一下它的實現程式碼:
(2)可以看到,在AutoLoad函式中先呼叫SubclassDlgItem關聯控制元件,所以我們就不能使用類嚮導關聯控制元件了,具體來說就是在對話方塊類的DoDataExchange函式中的DDX_Control(... ...)會與此處的SubclassDlgItem衝突,如果一定要用類嚮導,只要將響應的DDX_Control語句刪除就行了;// Autoload will load the bitmap resources based on the text of // the button // Using suffices "U", "D", "F" and "X" for up/down/focus/disabled BOOL CBitmapButton::AutoLoad(UINT nID, CWnd* pParent) { // first attach the CBitmapButton to the dialog control if (!SubclassDlgItem(nID, pParent)) return FALSE; CString buttonName; GetWindowText(buttonName); ASSERT(!buttonName.IsEmpty()); // must provide a title LoadBitmaps(buttonName + _T("U"), buttonName + _T("D"), buttonName + _T("F"), buttonName + _T("X")); // we need at least the primary if (m_bitmap.m_hObject == NULL) return FALSE; // size to content SizeToContent(); return TRUE; }
(3)接著繼續看AutoLoad的實現程式碼,也就是獲取按鈕文字(Caption),然後呼叫LoadBitmaps函式載入圖片;
即LoadBitmaps的引數是根據按鈕文字加上一個字母來確定的;
(4)按鈕的文字,即為屬性視窗中的Caption內容;按照這樣說來,是不是隻要將資源對話方塊中相應點陣圖的ID改為Caption中的內容加上一個字母就行了呢?答案是不行的。很多人都會犯這個錯誤,我一開始也犯了這個錯誤,糾結了好一會。
(5)原因是AutoLoad函式中呼叫的LoadBitmaps函式並不是前面提到的那個以點陣圖ID為引數的函式,仔細想一想,Caption中設定的是一個字串,然後在這個字串後面加一個字母,依然是一個字串;而控制元件的ID其實只是一個整數。顯然AutoLoad中的LoadBitmaps有一個過載函式:
BOOLLoadBitmaps(LPCTSTR lpszBitmapResource,LPCTSTR lpszBitmapResourceSel =NULL,LPCTSTR lpszBitmapResourceFocus =NULL,LPCTSTR lpszBitmapResourceDisabled =NULL);
(6)接下來看一下這個函式的實現:
// LoadBitmaps will load in one, two, three or all four bitmaps
// returns TRUE if all specified images are loaded
BOOL CBitmapButton::LoadBitmaps(LPCTSTR lpszBitmapResource,
LPCTSTR lpszBitmapResourceSel, LPCTSTR lpszBitmapResourceFocus,
LPCTSTR lpszBitmapResourceDisabled)
{
// delete old bitmaps (if present)
m_bitmap.DeleteObject();
m_bitmapSel.DeleteObject();
m_bitmapFocus.DeleteObject();
m_bitmapDisabled.DeleteObject();
if (!m_bitmap.LoadBitmap(lpszBitmapResource))
{
TRACE(traceAppMsg, 0, "Failed to load bitmap for normal image.\n");
return FALSE; // need this one image
}
BOOL bAllLoaded = TRUE;
if (lpszBitmapResourceSel != NULL)
{
if (!m_bitmapSel.LoadBitmap(lpszBitmapResourceSel))
{
TRACE(traceAppMsg, 0, "Failed to load bitmap for selected image.\n");
bAllLoaded = FALSE;
}
}
if (lpszBitmapResourceFocus != NULL)
{
if (!m_bitmapFocus.LoadBitmap(lpszBitmapResourceFocus))
bAllLoaded = FALSE;
}
if (lpszBitmapResourceDisabled != NULL)
{
if (!m_bitmapDisabled.LoadBitmap(lpszBitmapResourceDisabled))
bAllLoaded = FALSE;
}
return bAllLoaded;
}
(7)可以看到最終呼叫的是CBitmap類的成員函式LoadBitmap載入圖片的,但是CBitmap類下的該函式也有兩個過載:
BOOL LoadBitmap ( LPCTSTR lpszResourceName ); BOOL LoadBitmap ( UINT nIDResource );
(8)到此問題是清楚了,但是關於以LPCTSTR 型資料為引數LoadBitmap函式實際上引數並不是實際的檔案路徑,許多人可能都看到過,說CBitmap::LoadBitmap不能直接載入硬碟上的檔案,譬如這樣是不行的(雖然程式碼並不報錯):
CBitmap oBitmap;oBitmap.LoadBitmap(_T("D://test.bmp"));
(9)實際上這裡的引數依然是類似ID號的一種資源序號,只不過以字串的形式來表示,但是卻又不是簡單的從ID號轉化而來的,因為本文已經扯得比較遠,而且這個問題事實上還有許多內容,本文就不再深入下去了;下面迴歸主題,述說如何使用AutoLoad載入圖片。
4、使用AutoLoad載入圖片的步驟:
(1)同樣,在對話方塊上新增一個按鈕,更改其自繪屬性;
(2)手動新增一個CBitmapButton型的成員變數m_bmpBtn;
(3)關鍵步驟:點陣圖資源、按鈕ID 和 按鈕Caption的命名,命名規則如下:
按鈕ID:IDC_BTN_TEST_
按鈕Caption:BTN_TETST_
點陣圖ID(注意,包含分號):"TEST_U"、"TEST_D"、"TEST_F"、"TEST_X"
5、注意點:
(1)按鈕Caption是根據按鈕ID設定的:
a、若按鈕ID中有字元”_“,則以按鈕ID中第一個”_“字元後面的所有字串為按鈕Caption;
b、若按鈕ID中無字元”_“,則以ID名為按鈕Caption。
eg1:若按鈕ID為:IDC_BUTTON_UP 則按鈕Caption為:BUTTON_UP
eg2:若按鈕ID為:IDC_BTN_DOWN則按鈕Caption為:BTN_DOWN
eg3:若按鈕ID為:BTN_FOCUS則按鈕Caption為:FOCUS
eg4:若按鈕ID為:DISABLE則按鈕Caption為:DISABLE
(2)點陣圖資源ID是根據按鈕Caption設定的:
a、根據點陣圖所表示的按鈕狀態:UP、DOWN、FOCUS和DISABLE,分別在按鈕Caption後面加上一個大寫字母U或D或F或X;
b、然後用雙引號將這串字元引起來;
eg1:若按鈕Caption為:BUTTON_UP
則按鈕點陣圖資源ID為:"BUTTON_UPU"、"BUTTON_UPD"、"BUTTON_UPF"、"BUTTON_UPX"
eg2:若按鈕Caption為:BTN_DOWN
則按鈕點陣圖資源ID為:"BTN_DOWNU"、"BTN_DOWND"、"BTN_DOWNF"、"BTN_DOWNX"
eg3:若按鈕Caption為:FOCUS
則按鈕點陣圖資源ID為:"FOCUSU"、"FOCUSD"、"FOCUSF"、"FOCUSX"