亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MFC實(shí)現(xiàn)漂亮界面之美化按鈕

 更新時(shí)間:2019年02月20日 14:48:53   投稿:lijiao  
這篇文章主要為大家詳細(xì)介紹了MFC實(shí)現(xiàn)漂亮界面之美化按鈕,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

上次我們學(xué)習(xí)了如何美化對(duì)話框的界面,這次我們?yōu)樯洗蔚膶?duì)話框添加兩個(gè)按鈕,一個(gè)是關(guān)閉按鈕,另一個(gè)是最小化按鈕,好,現(xiàn)在我們先看一下效果:

是不是很難看,因?yàn)槲覀兊膶?duì)話框美化了,所以我們的按鈕也要美化,因?yàn)椴捎觅N圖的方式來美化,所以,我先給出這兩個(gè)按鈕的PNG格式的圖片,該圖片支持透明色,具體如下:

關(guān)閉按鈕效果圖:

最小化按鈕效果圖:

這兩張效果圖是我自己從網(wǎng)上找的,可能不是很合適,但是用來教學(xué),完全沒有問題,它們的尺寸都是108*21,每張圖片都有四個(gè)小圖片,第一張和第四張小圖片都是透明的,所以看不見效果,我們使用這兩張圖片來完成按鈕的美化,每張圖片從左向右有四張小圖片,我們只用前三張,分別對(duì)應(yīng)默認(rèn)狀態(tài),焦點(diǎn)狀態(tài),按下狀態(tài)。

下面,我們來說一下如何美化按鈕?

第1步,我們先在對(duì)話框上放置兩個(gè)按鈕,一個(gè)是關(guān)閉按鈕,另一個(gè)是最小化按鈕,它們對(duì)應(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)整按鈕在對(duì)話框上的位置,其中的參數(shù)代表該按鈕在父窗口的左上角X坐標(biāo),Y坐標(biāo),寬度,高度,最后一個(gè)參數(shù)是為PNG格式圖片準(zhǔn)備的,如果是PNG帶透明色的圖片,需要對(duì)它進(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)的背景圖片,它們對(duì)應(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)樗峭该鞯?,并且我們采用的是雙緩沖,所以,為了避免最終透明色變成黑色,我們先在內(nèi)存DC上貼上按鈕在父窗口位置的背景圖,這樣可以解決透明色變成黑色的問題,如果你采用GDI+,就不用這么做,但是我們采用的是GDI。

第7步,用CMyButton替代對(duì)話框頭文件中的CButton。

第8步,在對(duì)話框的InitDialog中,對(duì)兩個(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步,編譯程序,最終效果圖如下:

今天,我們已經(jīng)為它添加了最小化,關(guān)閉按鈕,下次,我們?yōu)槠涮砑泳庉嬁颍?/p>

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語(yǔ)言可變參數(shù)函數(shù)詳解示例

    C語(yǔ)言可變參數(shù)函數(shù)詳解示例

    一般我們編程的時(shí)候,函數(shù)中形式參數(shù)的數(shù)目通常是確定的,在調(diào)用時(shí)要依次給出與形式參數(shù)對(duì)應(yīng)的實(shí)際參數(shù)。但在某些情況下我們希望函數(shù)的參數(shù)個(gè)數(shù)可以根據(jù)需要確定,因此c語(yǔ)言引入可變參數(shù)函數(shù)。典型的可變參數(shù)函數(shù)的例子有printf()、scanf()等,下面我就開始講解
    2013-11-11
  • C語(yǔ)言操作符超詳細(xì)講解上篇

    C語(yǔ)言操作符超詳細(xì)講解上篇

    C?語(yǔ)言提供了豐富的操作符,有:算術(shù)操作符,移位操作符,位操作符,賦值操作符,單目操作符,關(guān)系操作符,邏輯操作符,條件操作符等。因?yàn)槠^大將分兩篇講解,讓我們通讀本篇來詳細(xì)了解吧
    2022-04-04
  • opencv 做人臉識(shí)別 opencv 人臉匹配分析

    opencv 做人臉識(shí)別 opencv 人臉匹配分析

    opencv 人臉識(shí)別通過級(jí)聯(lián)分類器對(duì)特征的分級(jí)篩選來確定是否是人臉,每個(gè)節(jié)點(diǎn)的正確識(shí)別率很高,但正確拒絕率很低,任一節(jié)點(diǎn)判斷沒有人臉特征則結(jié)束運(yùn)算,宣布不是人臉
    2012-11-11
  • window調(diào)用api列出當(dāng)前所有進(jìn)程示例

    window調(diào)用api列出當(dāng)前所有進(jìn)程示例

    這篇文章主要介紹了window調(diào)用api列出當(dāng)前所有進(jìn)程示例,需要的朋友可以參考下
    2014-04-04
  • C++ 虛函數(shù)專題

    C++ 虛函數(shù)專題

    這篇文章主要介紹了C++中虛函數(shù)的知識(shí)點(diǎn),文中配合代碼講解非常細(xì)致,供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • C++詳細(xì)分析線程間的同步通信

    C++詳細(xì)分析線程間的同步通信

    線程間不通信的話,每個(gè)線程受CPU的調(diào)度,沒有任何執(zhí)行上的順序可言,線程1和線程2是根據(jù)CPU調(diào)度算法來的,兩個(gè)線程都有可能先運(yùn)行,是不確定的,線程間的運(yùn)行順序是不確定的,所以多線程程序出問題,難以復(fù)現(xiàn),本章我們就來了解線程間的同步通信
    2022-05-05
  • 隨機(jī)加密程序的實(shí)現(xiàn)方法

    隨機(jī)加密程序的實(shí)現(xiàn)方法

    下面實(shí)例是對(duì)隨機(jī)加密程序的實(shí)現(xiàn)方法。需要的朋友參考下
    2013-05-05
  • c++ map,mutimap刪除問題分析

    c++ map,mutimap刪除問題分析

    本文詳細(xì)介紹c++ map,mutimap刪除操作時(shí)的一些問題,提供了解決方法,需要的朋友可以參考下
    2012-11-11
  • C語(yǔ)言宏定義#define的使用

    C語(yǔ)言宏定義#define的使用

    本文主要介紹了C語(yǔ)言宏定義#define的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C#中委托的基本用法總結(jié)

    C#中委托的基本用法總結(jié)

    以下是對(duì)C#中委托的基本用法進(jìn)行了詳細(xì)的總結(jié)分析,需要的朋友可以過來參考下。希望對(duì)大家有所幫助
    2013-09-09

最新評(píng)論