VS2010中CMFCButton控件的使用 --1

控件按鈕應該是使用最頻繁的控件了。我感覺沒有之一。

但是MFC的常規按鈕限制很多,功能基本不能滿足要求。以前使用很廣的CButtonST類倒是個選擇,但那個好像是基於VC6.0弄的,不清楚在VS2010上使用情況怎麼樣。正好,VS2010提供了一個CMFCButton類,比Button做了很多強化。就選擇直接使用。

基本的用法和CButton是一樣的,只是要注意一點,不要在控件工具中拖MFC Button Control到對話框或者什麼其他地方,這裏在編譯的時候好像會出問題。要用Button Control,然後定義控件類型之後,手動去修改類。

在這裏使用CMFCButton主要是爲了實現加載圖片透明化。

CMFCButton的使用,這個例子裏面基本上都有展示。安裝了VS2010的可以在Microsoft Visual Studio 10.0\Samples\2052目錄下找到對應的源碼。當然裏面很多例子,要用的心思慢慢找。或者直接到  去下載也是可以的,我把這個工程摘出來了。

這裏我就細說下圖片透明化的問題。下面是加載圖片的細節,這裏可以看到,CMFCButton是可以直接加載png格式的圖片的,這點很重要,下面會講到。

m_Button.SetImage(IDB_BTN1_32, IDB_BTN1_HOT_32);

void CMFCButton::SetImage(UINT uiBmpResId, UINT uiBmpHotResId, UINT uiBmpDsblResID)
{
	SetImageInternal(uiBmpResId, uiBmpHotResId, FALSE /* Not checked */, uiBmpDsblResID);
}

void CMFCButton::SetImageInternal(UINT uiBmpResId, UINT uiBmpHotResId, BOOL bChecked, UINT uiBmpDsblResID)
{
	ClearImages(bChecked);

	if (uiBmpResId == 0)
	{
		return;
	}

	HBITMAP hbmp = ButtonLoadBitmap(uiBmpResId);
	HBITMAP hbmpHot = ButtonLoadBitmap(uiBmpHotResId);
	HBITMAP hbmpDisabled = ButtonLoadBitmap(uiBmpDsblResID);

	SetImageInternal(hbmp, TRUE /* AutoDestroy */, hbmpHot, FALSE, bChecked, hbmpDisabled);
}

static HBITMAP __stdcall ButtonLoadBitmap(UINT uiBmpResId)
{
	if (uiBmpResId == 0)
	{
		return NULL;
	}

	LPCTSTR lpszResourceName = MAKEINTRESOURCE(uiBmpResId);
	ENSURE(lpszResourceName != NULL);

	HBITMAP hbmp = NULL;

	// Try to load PNG image first:
	CPngImage pngImage;
	if (pngImage.Load(lpszResourceName))
	{
		hbmp = (HBITMAP) pngImage.Detach();
	}
	else
	{
		HINSTANCE hinstRes = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
		if (hinstRes == NULL)
		{
			return NULL;
		}

		UINT uiLoadImageFlags = LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS;

		hbmp = (HBITMAP) ::LoadImage(hinstRes, lpszResourceName, IMAGE_BITMAP, 0, 0, uiLoadImageFlags);
	}

	return hbmp;
}

實際上,你隨意加載圖片基本是沒辦法透明化的,那個白的或者黑的邊框很影響感官的。

void CMFCButton::SetImageInternal(HBITMAP hBitmapCold, BOOL bAutoDestroy, HBITMAP hBitmapHot, BOOL bMap3dColors, BOOL bChecked, HBITMAP hBitmapDisabled)
{
	ClearImages(bChecked);

	if (hBitmapCold == NULL)
	{
		return;
	}

	const int nCount = hBitmapDisabled == NULL ? 2 : 3;

	for (int i = 0; i < nCount; i++)
	{
		HBITMAP hBitmap = (i == 0) ? hBitmapCold :(i == 1) ? hBitmapHot : hBitmapDisabled;
		CMFCToolBarImages& image = bChecked ?((i == 0) ? m_ImageChecked :(i == 1) ? m_ImageCheckedHot : m_ImageCheckedDisabled) :
			((i == 0) ? m_Image :(i == 1) ? m_ImageHot : m_ImageDisabled);

		if (hBitmap == NULL)
		{
			break;
		}

		BITMAP bmp;
		::GetObject(hBitmap, sizeof(BITMAP), (LPVOID) &bmp);

		BOOL bMap3dColorsCurr = bMap3dColors ||(bmp.bmBitsPixel > 8 && bmp.bmBitsPixel < 32);
		BOOL bAlpha = !bMap3dColors && bmp.bmBitsPixel == 32 && CMFCToolBarImages::Is32BitTransparencySupported();

		if (i == 0)
		{
			m_sizeImage.cx = bmp.bmWidth;
			m_sizeImage.cy = bmp.bmHeight;
		}
		else
		{
			// Hot and cold bitmaps should have the same size!
			ASSERT(m_sizeImage.cx == bmp.bmWidth);
			ASSERT(m_sizeImage.cy == bmp.bmHeight);
		}

		if (bAlpha)
		{
			CMFCToolBarImages::PreMultiplyAlpha(hBitmap, TRUE);
		}

		image.SetImageSize(CSize(bmp.bmWidth, bmp.bmHeight));
		image.SetTransparentColor(bMap3dColorsCurr ? RGB(192, 192, 192) : bAlpha ?(COLORREF) -1 : afxGlobalData.clrBtnFace);
		image.AddImage(hBitmap, TRUE);
	}

	if (bAutoDestroy)
	{
		if (hBitmapHot != NULL)
		{
			::DeleteObject(hBitmapHot);
		}

		if (hBitmapCold != NULL)
		{
			::DeleteObject(hBitmapCold);
		}

		if (hBitmapDisabled != NULL)
		{
			::DeleteObject(hBitmapDisabled);
		}
	}
}

這段代碼裏面可以很清楚的看到那個關於透明化的處理,但是有個要求圖片必須是32位的需求。一般的BMP格式就是24位,是沒辦法滿足要求的,這裏既是png格式圖片施展地方了。因爲png格式好像默認就是32位的。

 

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