這篇文章將為大家詳細(xì)講解有關(guān)MFC如何實(shí)現(xiàn)漂亮界面之美化按鈕,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括福鼎網(wǎng)站建設(shè)、福鼎網(wǎng)站制作、福鼎網(wǎng)頁制作以及福鼎網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,福鼎網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到福鼎省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
效果:
是不是很難看,因?yàn)槲覀兊膶υ捒蛎阑耍晕覀兊陌粹o也要美化,因?yàn)椴捎觅N圖的方式來美化,所以,我先給出這兩個(gè)按鈕的PNG格式的圖片,該圖片支持透明色,具體如下:
關(guān)閉按鈕效果圖:
最小化按鈕效果圖:
這兩張效果圖是我自己從網(wǎng)上找的,可能不是很合適,但是用來教學(xué),完全沒有問題,它們的尺寸都是108*21,每張圖片都有四個(gè)小圖片,第一張和第四張小圖片都是透明的,所以看不見效果,我們使用這兩張圖片來完成按鈕的美化,每張圖片從左向右有四張小圖片,我們只用前三張,分別對應(yīng)默認(rèn)狀態(tài),焦點(diǎn)狀態(tài),按下狀態(tài)。
下面,我們來說一下如何美化按鈕?
第1步,我們先在對話框上放置兩個(gè)按鈕,一個(gè)是關(guān)閉按鈕,另一個(gè)是最小化按鈕,它們對應(yīng)的ID分別是IDC_BUTTON_CLOSE和IDC_BUTTON_MIN,然后將我們的按鈕設(shè)置為自繪制模式,方法如下:
選擇按鈕,右鍵屬性,在屬性列表中找到Owner Draw選項(xiàng),將其設(shè)置為True,效果圖如下:
再為它們添加兩個(gè)成員變量,具體如下:
CButton m_btnClose; CButton m_btnMin;
第2步,我們新建一個(gè)類,繼承自CButton,我們?nèi)∶麨镃MyButton,為其添加3個(gè)成員變量,分別如下:
//按鈕背景圖像 CImage m_imgButton; //按鈕png路徑,包括焦點(diǎn),正常,按下3個(gè)狀態(tài) CString m_strImgPath; //父窗口背景圖片背景路徑,透明png需要使用 CString m_strImgParentPath;
第3步,我們?yōu)镃MyButton添加3個(gè)成員函數(shù),分別如下:
//設(shè)置按鈕背景圖片路徑,父窗口背景圖片路徑 void SetImagePath(CString strImgPath, CString strParentImgPath); //初始化按鈕,主要是調(diào)整按鈕的位置,處理透明色 bool InitMyButton(int nX/*左上角X坐標(biāo)*/, int nY/*左上角Y坐標(biāo)*/,int nW/*圖像寬*/, int nH/*圖像高*/, bool bIsPng/*是否是PNG圖片*/); //自繪制函數(shù) void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
CMyButton的聲明最終如下:
class CMyButton : public CButton { DECLARE_DYNAMIC(CMyButton) public: CMyButton(); virtual ~CMyButton(); //按鈕背景圖像 CImage m_imgButton; //按鈕png路徑,包括焦點(diǎn),正常,按下3個(gè)狀態(tài) CString m_strImgPath; //父窗口背景圖片背景路徑,透明png需要使用 CString m_strImgParentPath; //設(shè)置按鈕背景圖片路徑,父窗口背景圖片路徑 void SetImagePath(CString strImgPath, CString strParentImgPath); //初始化按鈕,主要是調(diào)整按鈕的位置,處理透明色 bool InitMyButton(int nX/*左上角X坐標(biāo)*/, int nY/*左上角Y坐標(biāo)*/,int nW/*圖像寬*/, int nH/*圖像高*/, bool bIsPng/*是否是PNG圖片*/); //自繪制函數(shù) void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); protected: DECLARE_MESSAGE_MAP() };
第4步,我們實(shí)現(xiàn)SetImagePath函數(shù),它的功能是為按鈕背景圖片和父窗口背景圖片成員函數(shù)初始化,具體如下:
void CMyButton::SetImagePath(CString strImgPath, CString strParentImgPath) { m_strImgPath = strImgPath; m_strImgParentPath = strParentImgPath; }
第5步,我們實(shí)現(xiàn)InitMyButton函數(shù),它的功能是調(diào)整按鈕在對話框上的位置,其中的參數(shù)代表該按鈕在父窗口的左上角X坐標(biāo),Y坐標(biāo),寬度,高度,最后一個(gè)參數(shù)是為PNG格式圖片準(zhǔn)備的,如果是PNG帶透明色的圖片,需要對它進(jìn)行特殊處理,具體定義如下:
bool CMyButton::InitMyButton(int nX, int nY, int nW, int nH, bool bIsPng) { HRESULT hr = 0; if (m_strImgPath.IsEmpty()) return false; hr = m_imgButton.Load(m_strImgPath); if (FAILED(hr)) return false; if (bIsPng) { if (m_imgButton.GetBPP() == 32) { int i = 0; int j = 0; for (i = 0; i < m_imgButton.GetWidth(); i++) { for (j = 0; j < m_imgButton.GetHeight(); j++) { byte * pbyte = (byte *)m_imgButton.GetPixelAddress(i, j); pbyte[0] = pbyte[0] * pbyte[3] / 255; pbyte[1] = pbyte[1] * pbyte[3] / 255; pbyte[2] = pbyte[2] * pbyte[3] / 255; } } } } MoveWindow(nX,nY,nW,nH); return true; }
其中MoveWindow函數(shù)是用來調(diào)整按鈕位置的函數(shù),其中的參數(shù)分別代表其在父窗口的左上角X坐標(biāo),左上角Y坐標(biāo),寬度,高度。
第6步,我們實(shí)現(xiàn)DrawItem函數(shù),它是美化Button的核心函數(shù),當(dāng)我們將Button設(shè)置為自繪制后,每次按鈕需要刷新,重新繪制的時(shí)候,MFC框架會(huì)調(diào)用它的DrawItem函數(shù),在這個(gè)函數(shù)中,我們可以根據(jù)按鈕當(dāng)前的狀態(tài)為其貼上相應(yīng)的背景圖。當(dāng)我們按鈕按鈕的時(shí)候,為其貼上被按下的背景圖;當(dāng)我們的按鈕獲取焦點(diǎn)的時(shí)候,為其貼上獲取焦點(diǎn)的背景圖;當(dāng)我們的按鈕沒有焦點(diǎn),我們?yōu)槠滟N上默認(rèn)的背景圖片,它們對應(yīng)的位置前面已經(jīng)說過。為了避免閃爍,我們采用雙緩沖的方式,具體代碼如下:
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { if (!lpDrawItemStruct) return; HDC hMemDC; HBITMAP bmpMem; HGDIOBJ hOldObj; bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top); if (!bmpMem) return; hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC); if (!hMemDC) { if (bmpMem) { ::DeleteObject(bmpMem); bmpMem = NULL; } return; } hOldObj = ::SelectObject(hMemDC, bmpMem); RECT rectTmp = { 0 }; rectTmp = lpDrawItemStruct->rcItem; MapWindowPoints(GetParent(), &rectTmp); int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left; int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top; if (lpDrawItemStruct->itemState & ODS_SELECTED) { //按鈕被選擇 m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, nW*2, 0, SRCCOPY); } else if (lpDrawItemStruct->itemState & ODS_FOCUS) { //焦點(diǎn)狀態(tài) m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, nW, 0, SRCCOPY); } else { //默認(rèn)狀態(tài) CImage imgParent; imgParent.Load(m_strImgParentPath); imgParent.Draw(hMemDC, 0, 0, nW, nH, rectTmp.left, rectTmp.top, nW, nH); m_imgButton.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH); imgParent.Destroy(); } ::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldObj); if (bmpMem) { ::DeleteObject(bmpMem); bmpMem = NULL; } if (hMemDC) { ::DeleteDC(hMemDC); hMemDC = NULL; } return; }
這里我們重點(diǎn)說一下默認(rèn)狀態(tài)的背景圖,因?yàn)樗峭该鞯模⑶椅覀儾捎玫氖请p緩沖,所以,為了避免最終透明色變成黑色,我們先在內(nèi)存DC上貼上按鈕在父窗口位置的背景圖,這樣可以解決透明色變成黑色的問題,如果你采用GDI+,就不用這么做,但是我們采用的是GDI。
第7步,用CMyButton替代對話框頭文件中的CButton。
第8步,在對話框的InitDialog中,對兩個(gè)按鈕進(jìn)行初始化,具體如下:
m_btnMin.SetImagePath(_T("./res/btn_min.png"), _T("./res/Background.png")); m_btnMin.InitMyButton(516, 8, 27, 21, true); m_btnClose.SetImagePath(_T("./res/btn_close.png"),_T("./res/Background.png")); m_btnClose.InitMyButton(545,8,27,21,true);
第9步,編譯程序,最終效果圖如下:
關(guān)于“MFC如何實(shí)現(xiàn)漂亮界面之美化按鈕”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。