1、MFC有一個位圖按鈕類,即爲CBitmapButton,能夠實現簡單的按鈕貼圖美化;但是長久沒有使用,今天就遇到一些問題:主要就是CBitmapButton::AutoLoad這個函數的使用,總是出錯,無法正確的加載圖片;現在將需要注意的問題貼出來,以作備份。
2、首先,說明以下不用AutoLoad的初始化方法,我在VS2010下測試成功,完全可以用類嚮導添加一個CBitmapButton型的控件變量(即在DoDataExchange關聯控件與變量)而不用手動調用SubclassDlgItem函數。只需要將預先導入的位圖加載到按鈕類變量中就行了,具體如下:
(1)在對話框上放置一個按鈕,修改其自繪(Owner Draw)屬性爲TRUE;
(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 = 0, UINT nIDBitmapResourceFocus = 0, UINT nIDBitmapResourceDisabled = 0 );(5)OK,這樣就行了
3、現在在說用AutoLoad函數加載圖片,以及相應的注意點:
(1)關於AutoLoad函數,可以先看一下它的實現代碼:
// 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有一個重載函數:
BOOL LoadBitmaps( 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"