ImageButton

出自ProgWiki

跳轉到: 導航, 搜尋

目錄

用途

(改透過元件 IPicture 來載入圖檔,故可支援較多種的圖檔格式。)

原始程式

ImageButton.h

#pragma once
 
//-----------------------------------------------------------------------------
//class CImageButton 編譯相關開關
 
//#define CImageButton_UseCOM		1
#define CImageButton_UseFile		1
//#define CImageButton_UseResource	1
 
 
//-----------------------------------------------------------------------------
//class CImageButton
//	使用 IPicture 對圖檔解碼
//		支援圖檔格式
//			JPG(jpeg), GIF, BMP (bitmap), WMF (metafile), ICO (icon) 
//-----------------------------------------------------------------------------
 
 
//-----------------------------------------------------------------------------
//	路徑合併用 ( PathAppend 與 PathCombine )
//-----------------------------------------------------------------------------
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
 
inline void	PathAppend(CString& strPath, LPCTSTR lpszMore)
{
	//TODO: PathAppend(CString& strPath, LPCTSTR lpszMore)
 
	::PathAppend(	strPath.GetBuffer(MAX_PATH),
			lpszMore);
	strPath.ReleaseBuffer();
}
 
inline void PathCombine(CString& strDest, LPCTSTR lpszDir, LPCTSTR lpszFile)
{
	//TODO: PathCombine(CString& strDest, LPCTSTR lpszDir, LPCTSTR lpszFile)
 
	::PathCombine(	strDest.GetBuffer(MAX_PATH),
			lpszDir,
			lpszFile);
	strDest.ReleaseBuffer();
}
 
 
//-----------------------------------------------------------------------------
// CImageButton
//	圖形化按鈕類別, 繼承自 MFC 的 CBitmapButton
//
//	類別繼承樹
//		CObject +
//			+	CCmdTarget	+
//						+	CWnd	+
//								+	CButton	+
//										+	CBitmapButton	+
//													+	CImageButton
//-----------------------------------------------------------------------------
 
//class CBitmapButton
#include <afxctl.h>
 
 
class CImageButton : public CBitmapButton
{
	DECLARE_DYNAMIC(CImageButton)
 
public:
	CImageButton();
	virtual ~CImageButton();
 
protected:
	DECLARE_MESSAGE_MAP()
 
	BOOL	m_bTracking;
	virtual void PreSubclassWindow();
 
public:
	//滑鼠移入事件
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	//滑鼠移出事件
	afx_msg LRESULT OnMouseLeave(WPARAM, LPARAM);
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseCOM
#ifdef CImageButton_UseCOM
	public:
		//COM初始化
		static void InitRunTimeEnvironment(void);
		//COM釋放
		static void ReleaseRunTimeEnvironment(void);
#endif
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseResource
#ifdef CImageButton_UseResource
	protected:
		//For Resource
		static	HINSTANCE	m_hInstance;
		static	LPCSTR		m_lpszType;
 
		HRESULT GetImageFromResource(LPCTSTR lpszFilename, IPicture** ppPicture);
		HRESULT GetImageToBitmapFromResource(CBitmap& bmp, LPCTSTR lpszFilename);
 
	public:
 
		//設定Resource來源預設
		static void SetImageResource(HINSTANCE hInstance, LPCSTR lpszType);
		// 從Resource裡載入圖檔
		HRESULT LoadImagesFromResource(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel = NULL, LPCTSTR lpszImageFileFocus = NULL, LPCTSTR lpszImageFileDisabled = NULL);
 
#endif
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseFile
#ifdef CImageButton_UseFile
 
	protected:
		//For檔案
		static	CString		m_strImagePath;
 
		HRESULT GetImageFromFile(LPCTSTR lpszFilename, IPicture** ppPicture);
		HRESULT GetImageToBitmapFromFile(CBitmap& bmp, LPCTSTR lpszFilename);
 
	public:
 
		//設定檔案來源預設路徑
		static void SetImagePath(LPCTSTR lpszImagePath);
		// 從檔案載入圖檔
		HRESULT LoadImagesFromFile(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel = NULL, LPCTSTR lpszImageFileFocus = NULL, LPCTSTR lpszImageFileDisabled = NULL);
 
#endif
};

ImageButton.cpp

// ImageButton.cpp : 實作檔
//
 
#include "stdafx.h"
#include "ImageButton.h"
 
 
// CImageButton
 
IMPLEMENT_DYNAMIC(CImageButton, CBitmapButton)
 
 
//建構
CImageButton::CImageButton()
	: m_bTracking(FALSE)
{
	//TODO: CImageButton()
}
 
//解構
CImageButton::~CImageButton()
{
	//TODO: ~CImageButton()
}
 
 
//視窗訊息對應函式映射表
BEGIN_MESSAGE_MAP(CImageButton, CBitmapButton)
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()
 
 
 
 
void CImageButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: OnMouseMove(UINT nFlags, CPoint point)
 
	//TRACE("\nOnMouseMove ( %d, %d )", point.x, point.y );
 
	CBitmapButton::OnMouseMove(nFlags, point);
 
	if (this->GetFocus() != this)
	{
		this->SetFocus();
		TRACE("\nOnMouseMove ( %d, %d )", point.x, point.y );
 
		if (m_bTracking == FALSE) 
		{
			TRACKMOUSEEVENT t = 
			{
				sizeof(TRACKMOUSEEVENT),
				TME_LEAVE,
				this->GetSafeHwnd(),
				0
			};
			if (::_TrackMouseEvent(&t))
			{
				TRACE("\n* Mouse Enter");
 
				m_bTracking = TRUE;
 
				//按鈕重繪
				Invalidate();
			}
		}
	}
}
 
LRESULT CImageButton::OnMouseLeave(WPARAM, LPARAM)
{
	//TODO: OnMouseLeave(WPARAM, LPARAM)
 
	TRACE("\nOnMouseLeave");
 
	if (m_bTracking == TRUE)
	{
		TRACKMOUSEEVENT t = 
		{
			sizeof(TRACKMOUSEEVENT),
			TME_CANCEL,
			this->GetSafeHwnd(),
			0
		};
		if (::_TrackMouseEvent(&t))
		{
			TRACE("\n* Mouse Leave");
 
			m_bTracking = FALSE;
		}
	}
 
#if 0
	//單一層視窗用
	POINT pt;
	GetCursorPos(&pt);
 
	HWND hWnd = ::WindowFromPoint(pt);
	::SetFocus(hWnd);
#else
	//多層視窗用
	::SetFocus(::AfxGetApp()->GetMainWnd()->GetSafeHwnd());
#endif
 
	//按鈕重繪
	Invalidate();
 
	return S_OK;
}
 
 
void CImageButton::PreSubclassWindow()
{
	// TODO: PreSubclassWindow()
 
	CBitmapButton::PreSubclassWindow();
 
	ModifyStyle(0, BS_OWNERDRAW);
}
 
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseCOM
#ifdef CImageButton_UseCOM
 
//初始化COM
void CImageButton::InitRunTimeEnvironment(void)
{
	//TODO: InitRunTimeEnvironment(void)
 
	CoInitialize(NULL);
}
 
//釋放COM
void CImageButton::ReleaseRunTimeEnvironment(void)
{
	//TODO: ReleaseRunTimeEnvironment(void)
 
	CoUninitialize();
}
 
#endif
 
 
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseFile
#ifdef CImageButton_UseFile
 
 
CString		CImageButton::m_strImagePath = _T("");
 
 
//設定檔案來源預設路徑
void CImageButton::SetImagePath(LPCTSTR lpszImagePath)
{
	//TODO: SetImagePath(LPCTSTR lpszImagePath)
 
	TRACE("\n*設定圖檔預設路徑: %s\n", m_strImagePath);
	m_strImagePath = lpszImagePath;
}
 
//載入圖檔到 IPicture
HRESULT CImageButton::GetImageFromFile(LPCTSTR lpszFilename, IPicture** ppPicture)
{
	//TODO: GetImageFromFile(LPCTSTR pstrFilename, IPicture** ppPicture)
 
	if (*ppPicture)
		*ppPicture = NULL;
 
	if (lpszFilename == NULL)
		return E_NOINTERFACE;
 
	IPicture *pPic; 
	CComPtr<IStream> pStm = NULL; 
 
	BOOL bResult; 
 
	HANDLE	hFile		= INVALID_HANDLE_VALUE; 
	DWORD	dwFileSize	= 0,
		dwByteRead	= 0; 
	HGLOBAL hGlobal		= NULL; 
	LPVOID	pvData		= NULL; 
 
	try 
	{
		hFile = CreateFile(	lpszFilename,
					GENERIC_READ, 
					FILE_SHARE_READ,
					NULL,
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					NULL); 
 
		if (hFile == INVALID_HANDLE_VALUE) 
			return E_NOINTERFACE; 
 
		dwFileSize = GetFileSize(hFile, NULL);
 
		if (dwFileSize == 0xFFFFFFFF) 
			throw S_FALSE;
 
		hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); 
 
		if (hGlobal == NULL) 
			throw S_FALSE;
 
		if ((pvData = GlobalLock(hGlobal)) == NULL)
			throw S_FALSE;
 
		ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);
 
		if (CloseHandle(hFile) != NULL)
			hFile = INVALID_HANDLE_VALUE;
 
		GlobalUnlock(hGlobal); 
 
		CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 
 
		bResult = OleLoadPicture(	pStm,
						dwFileSize,
						TRUE,
						IID_IPicture,
						(LPVOID*)&pPic); 
 
		if (FAILED(bResult)) 
			throw S_FALSE;
 
		*ppPicture = pPic;	
	}
	catch(HRESULT)
	{
		if (hGlobal)
		{
			if (pvData)
				GlobalUnlock(hGlobal); 
			GlobalFree(hGlobal);
		}
 
		if (hFile != INVALID_HANDLE_VALUE)
			CloseHandle(hFile);
 
		return E_NOINTERFACE;
	}
 
 
	return S_OK;
}
 
HRESULT CImageButton::GetImageToBitmapFromFile(CBitmap& bmp, LPCTSTR lpszFilename)
{
	//TODO: GetImageToBitmapFromFile(CBitmap& bmp, LPCTSTR lpszFilename)
 
	if (lpszFilename == NULL)
		return S_FALSE;
 
	CString		strImageFile;
	strImageFile = lpszFilename;
	if (strImageFile.Find(_T(':')) == -1)
	{
		if (!m_strImagePath.IsEmpty())
			PathCombine(strImageFile, m_strImagePath, lpszFilename);
	}
 
	CPictureHolder	PictureHolder;
 
	HRESULT		hr		 = S_FALSE;
	IPicture*	pPicture = NULL;
	hr = this->GetImageFromFile(strImageFile, &pPicture);
 
	if (SUCCEEDED(hr))
	{
		OLE_XSIZE_HIMETRIC nWidth;
		OLE_YSIZE_HIMETRIC nHeight;
		pPicture->get_Width(&nWidth);
		pPicture->get_Height(&nHeight);
 
		nWidth	= (int)((float)nWidth / 26.46f);
		nHeight	= (int)((float)nHeight / 26.46f);
 
		CRect rcBounds(0, 0, nWidth, nHeight);
 
		CClientDC dc0( CWnd::GetDesktopWindow());
		CDC dc;
		dc.CreateCompatibleDC( &dc0 );
		bmp.CreateCompatibleBitmap( &dc0, nWidth, nHeight );
		CBitmap* pBmpOld = (CBitmap*) dc.SelectObject(bmp); 
 
		PictureHolder.m_pPict = pPicture;
		PictureHolder.Render(&dc, rcBounds, rcBounds);
		PictureHolder.m_pPict = NULL;
		pPicture->Release();
 
		//dc.SelectObject(pBmpOld);
 
		return S_OK;
	}
 
	return S_FALSE;
}
 
 
// 從檔案載入圖檔
HRESULT CImageButton::LoadImagesFromFile(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel, LPCTSTR lpszImageFileFocus, LPCTSTR lpszImageFileDisabled)
{
	//TODO: LoadImagesFromFile(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel, LPCTSTR lpszImageFileFocus, LPCTSTR lpszImageFileDisabled)
 
	m_bitmap.DeleteObject();
	m_bitmapSel.DeleteObject();
	m_bitmapFocus.DeleteObject();
	m_bitmapDisabled.DeleteObject();
 
	HRESULT		hr = S_OK;
 
	//圖檔載入
	if (lpszImageFile)
	{
		hr = GetImageToBitmapFromFile(m_bitmap, lpszImageFile);
 
		if (hr != S_OK)
		{
			TRACE("\n*無法載入圖檔: %s\n按鈕顯示自動進入純文字模式\n", lpszImageFile);
			ModifyStyle( BS_OWNERDRAW, 0);
			return S_FALSE;
		}
	}
 
	if (lpszImageFileSel)
	{
		hr = GetImageToBitmapFromFile(m_bitmapSel, lpszImageFileSel);
	}
 
	if (lpszImageFileFocus)
	{
		hr = GetImageToBitmapFromFile(m_bitmapFocus, lpszImageFileFocus);
	}
 
	if (lpszImageFileDisabled)
	{
		hr = GetImageToBitmapFromFile(m_bitmapDisabled, lpszImageFileDisabled);
	}
 
	//按鈕自動縮放到圖檔的Size
	this->SizeToContent();
 
	return S_OK;
}
 
#endif
 
 
//-----------------------------------------------------------------------------
//TODO: #ifdef CImageButton_UseResource
#ifdef CImageButton_UseResource
 
 
 
HINSTANCE	CImageButton::m_hInstance	 = NULL;
LPCSTR		CImageButton::m_lpszType	 = RT_HTML;
 
 
void CImageButton::SetImageResource(HINSTANCE hInstance, LPCSTR lpszType)
{
	//TODO:  SetImageResource(HINSTANCE hInstance, LPCSTR lpszType)
 
	m_hInstance = hInstance;
	m_lpszType	= lpszType;
}
 
//載入圖檔到 IPicture
HRESULT CImageButton::GetImageFromResource(LPCTSTR lpszFilename, IPicture** ppPicture)
{
	//TODO: GetImageFromResource(LPCTSTR pstrFilename, IPicture** ppPicture)
 
	if (*ppPicture)
		*ppPicture = NULL;
 
	if (lpszFilename == NULL)
		return E_NOINTERFACE;
 
	IPicture *pPic; 
	CComPtr<IStream> pStm = NULL; 
 
	BOOL bResult; 
 
	HRSRC	hResInfo	= NULL;
	HGLOBAL hRes		= NULL;
	char*	lpRes		= NULL;
 
	DWORD	dwFileSize	= 0;
	HGLOBAL hGlobal		= NULL; 
	LPVOID	pvData		= NULL; 
 
	try 
	{
		hResInfo = FindResource(m_hInstance, lpszFilename, m_lpszType);
		if (hResInfo == NULL) 
			throw S_FALSE;
 
		dwFileSize = SizeofResource( m_hInstance, hResInfo ); 
		if (dwFileSize == 0) 
			throw S_FALSE;
 
		hRes = LoadResource(m_hInstance, hResInfo );
		if (hRes == NULL) 
			throw S_FALSE;
 
		hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); 
		if (hGlobal == NULL) 
			throw S_FALSE;
 
		if ((pvData = GlobalLock(hGlobal)) == NULL)
			throw S_FALSE;
 
		lpRes = (char*)LockResource(hRes);
		if (lpRes)
		{
			CopyMemory(pvData, lpRes, dwFileSize);
			UnlockResource(hRes);
			lpRes = NULL;
		}
 
		if (FreeResource(hRes) == NULL)
			hRes = NULL;
 
		GlobalUnlock(hGlobal); 
 
		CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 
 
		bResult = OleLoadPicture(	pStm,
						dwFileSize,
						TRUE,
						IID_IPicture,
						(LPVOID*)&pPic); 
 
		if (FAILED(bResult)) 
			throw S_FALSE;
 
		*ppPicture = pPic;	
	}
	catch(HRESULT)
	{
		if (hGlobal)
		{
			if (pvData)
				GlobalUnlock(hGlobal); 
			GlobalFree(hGlobal);
		}
 
		if (hRes)
		{
			if (lpRes)
				UnlockResource(hRes);  
			FreeResource(hRes);
		}
 
		return E_NOINTERFACE;
	}
 
 
	return S_OK;
}
 
HRESULT CImageButton::GetImageToBitmapFromResource(CBitmap& bmp, LPCTSTR lpszFilename)
{
	//TODO: GetImageToBitmapFromFile(CBitmap& bmp, LPCTSTR lpszFilename)
 
	if (lpszFilename == NULL)
		return S_FALSE;
 
 
	CPictureHolder	PictureHolder;
 
	HRESULT		hr		 = S_FALSE;
	IPicture*	pPicture = NULL;
	hr = this->GetImageFromResource(lpszFilename, &pPicture);
 
	if (SUCCEEDED(hr))
	{
		OLE_XSIZE_HIMETRIC nWidth;
		OLE_YSIZE_HIMETRIC nHeight;
		pPicture->get_Width(&nWidth);
		pPicture->get_Height(&nHeight);
 
		nWidth	= (int)((float)nWidth / 26.46f);
		nHeight	= (int)((float)nHeight / 26.46f);
 
		CRect rcBounds(0, 0, nWidth, nHeight);
 
		CClientDC dc0( CWnd::GetDesktopWindow());
		CDC dc;
		dc.CreateCompatibleDC( &dc0 );
		bmp.CreateCompatibleBitmap( &dc0, nWidth, nHeight );
		CBitmap* pBmpOld = (CBitmap*) dc.SelectObject(bmp); 
 
		PictureHolder.m_pPict = pPicture;
		PictureHolder.Render(&dc, rcBounds, rcBounds);
		PictureHolder.m_pPict = NULL;
		pPicture->Release();
 
		//dc.SelectObject(pBmpOld);
 
		return S_OK;
	}
 
	return S_FALSE;
}
 
 
 
// 從Resource裡載入圖檔
HRESULT CImageButton::LoadImagesFromResource(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel, LPCTSTR lpszImageFileFocus, LPCTSTR lpszImageFileDisabled)
{
	//TODO: LoadImagesFromResource(LPCTSTR lpszImageFile, LPCTSTR lpszImageFileSel, LPCTSTR lpszImageFileFocus, LPCTSTR lpszImageFileDisabled)
 
	m_bitmap.DeleteObject();
	m_bitmapSel.DeleteObject();
	m_bitmapFocus.DeleteObject();
	m_bitmapDisabled.DeleteObject();
 
	HRESULT		hr = S_OK;
 
	//圖檔載入
	if (lpszImageFile)
	{
		hr = GetImageToBitmapFromResource(m_bitmap, lpszImageFile);
 
		if (hr != S_OK)
		{
			TRACE("\n*無法載入圖檔: %s\n按鈕顯示自動進入純文字模式\n", lpszImageFile);
			ModifyStyle( BS_OWNERDRAW, 0);
			return S_FALSE;
		}
	}
 
	if (lpszImageFileSel)
	{
		hr = GetImageToBitmapFromResource(m_bitmapSel, lpszImageFileSel);
	}
 
	if (lpszImageFileFocus)
	{
		hr = GetImageToBitmapFromResource(m_bitmapFocus, lpszImageFileFocus);
	}
 
	if (lpszImageFileDisabled)
	{
		hr = GetImageToBitmapFromResource(m_bitmapDisabled, lpszImageFileDisabled);
	}
 
	//按鈕自動縮放到圖檔的Size
	this->SizeToContent();
 
	return S_OK;
}
#endif
個人工具
名字空間
變換
動作
導航
分類
其他
技術類News或部落格
工具箱