CBitmapButton類使用注意事項(主要是AutoLoad)

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;
}


(2)可以看到,在AutoLoad函數中先調用SubclassDlgItem關聯控件,所以我們就不能使用類嚮導關聯控件了,具體來說就是在對話框類的DoDataExchange函數中的DDX_Control(... ...)會與此處的SubclassDlgItem衝突,如果一定要用類嚮導,只要將響應的DDX_Control語句刪除就行了;

(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"






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章