• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            yehao's Blog

            圖形界面上的任意形狀圖形按鈕

          1. DemoButton.rar - 430.97 KB(已被下載145次)
          2. 摘要

            隨著計算機(jī)的發(fā)展和普及,人們對于軟件的界面美觀性要求越來越高。MFC提供了很多標(biāo)準(zhǔn)控件,比如按鈕控件,按鈕在MFC編程中有著較高的使用頻率。本文將介紹如何實(shí)現(xiàn)在有背景圖片的情況下,任意形狀按鈕的自繪方法。本文使用基于對話框工程程序進(jìn)行演示。

            關(guān)鍵字: VC++ 按鈕 自繪 任意形狀 圖形

            實(shí)現(xiàn)原理

            我們知道windows窗口默認(rèn)都是矩形,要實(shí)現(xiàn)任意形狀的窗口就需要自繪。為此從CBUTTON派生一個按鈕類CControlButton,重載DrawItem消息處理進(jìn)行自繪。圖片的背景是矩形的,假如我們的按鈕圖片是圓形的,當(dāng)把圖片繪制上去之后,我們發(fā)現(xiàn)多出了背景部分。如何消除背景呢?

            為了解決這個問題,我們可以用BitBlt 中的MERGEPAINT和SRCAND的方式進(jìn)行繪制。 MERGEPAINT是把圖形反色后再同貼圖目的地進(jìn)行OR操作,而SRCAND是把圖形和貼圖目的地進(jìn)行AND操作。在計算機(jī)中,使用的是數(shù)字圖像處理,每一種顏色都是由RGB表示的,RGB是指紅、綠、藍(lán)三原色,只要有這3種顏色和對應(yīng)的顏色強(qiáng)度就可以合成各種顏色了。比如,黑色的RGB值為(0,0,0),白色的RGB值為(255,255,255),括號內(nèi)對應(yīng)的是紅綠藍(lán)3種顏色的強(qiáng)度。在數(shù)字圖像處理中可以實(shí)現(xiàn)OR、AND等邏輯運(yùn)算。任何顏色同白色進(jìn)行OR運(yùn)算結(jié)果都為白色,進(jìn)行AND運(yùn)算結(jié)果都是該顏色本身;任何顏色跟黑色進(jìn)行OR運(yùn)算結(jié)果都為該顏色本身;進(jìn)行AND運(yùn)算結(jié)果都是黑色。為此,我們準(zhǔn)備兩張圖片,如下圖所示:

            左面圖片的背景為白色,右面是將左面中需要顯示部分填充黑色而得。實(shí)現(xiàn)去除背景貼圖關(guān)鍵代碼如下:

            if (IsMask==TRUE) //值為真則去除圖片背景
            {
                   CDC MaskDC;
                   MaskDC.CreateCompatibleDC(pDC);
                   if (IsBackBmp==TRUE)//使用和主窗口相同的背景圖片
                   {
                          CBitmap *pOldBmp;
                          CDC BackDC;
                          BackDC.CreateCompatibleDC(pDC);
                          pOldBmp = MaskDC.SelectObject(&m_MaskBitmap);
                          BackDC.SelectObject(&m_BackBitmap);
                          pDC->BitBlt(0,0,rect.Width(),rect.Height(),&BackDC,BackRect.left,BackRect.top,SRCCOPY);
                   }
            
                   pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MaskDC,0,0,MERGEPAINT);
                   pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCAND);
                   ReleaseDC(&MaskDC);
                   }
            
                   else
                   {
                          pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
                   }
            
            

            MaskDC是圖2的DC,MemDC為圖1的DC。效果如下圖所示:

            可能這時你就納悶了,為什么背景色還是白色呢,是不是代碼沒有去掉圖片的背景色呢?答案是貼圖的時候已經(jīng)去掉了背景色。請看分析

            按鈕是一個子窗口,默認(rèn)情況下主窗口和按鈕子窗口背景都是白色,但是往往我們需要在主窗口上繪制一張圖片,這樣窗口看起來就比較美觀。這樣子做之后,按鈕子窗口和主窗口的背景就不一樣了。在進(jìn)行按鈕自繪的時候,那就是把按鈕背景作為目的地進(jìn)行OR、AND運(yùn)算,因為按鈕背景就是白色的,所以效果看起來也就是白色的。

            要解決這個問題也很簡單,我們獲取按鈕所在主窗口中的矩形區(qū)域,把這個區(qū)域的主窗口背景繪制到按鈕中,再進(jìn)行繪制按鈕圖片的操作就可以了。

            通過這樣做之后,效果如下圖:

            為此,我們已經(jīng)得到一個圖片按鈕了。但僅僅這樣還不行,這按鈕的響應(yīng)區(qū)域還是矩形區(qū)域,也就是說除了按鈕圖片之外的區(qū)域也響應(yīng)鼠標(biāo)點(diǎn)擊。那我們就需要構(gòu)造一個按鈕圖片區(qū)域,使用庫函數(shù)SetWindowRgn就可以確定響應(yīng)區(qū)域了。SetWindowRgn有個參數(shù)為HRGN類型,因此我們需要獲得一個HRGN。

            Jean-Edouard Lachand-Robert 寫了一個 BitmapToRegion 函數(shù),函數(shù)的功能為把一張位圖根據(jù)一種顏色轉(zhuǎn)化為一個區(qū)域,這個我們就可以得到一個HRGN。有關(guān)BitmapToRegion詳情請看代碼說明。我們用圖2中的黑色區(qū)域去轉(zhuǎn)化成區(qū)域,為此我們就得了一個圖片按鈕的響應(yīng)區(qū)域了。

            另外,CControlButton類還提供了通常的四態(tài)按鈕的支持,即鼠標(biāo)劃過、點(diǎn)擊、正常、獲得焦點(diǎn)四種情況對應(yīng)加載四張不同的位圖。

            成員函數(shù)介紹

            void CControlButton::SetMaskBitmapId(int mask, bool action)

            • 功能:設(shè)置圖2資源圖片
            • 返回值:無
            • 參數(shù):mask ,圖2的資源ID
              action,值為TRUE則有效,F(xiàn)ALSE為無效

            void CControlButton::SetBackBmp(int nBgdBmpId,CRect rect)

            • 功能:設(shè)置按鈕背景圖片
            • 返回值:無
            • 參數(shù):nBgdBmpId ,主窗口背景圖片資源ID
              rect , 按鈕在主窗口中的客戶區(qū)矩形, 使用GetWindowRect, ScreenToClient這兩個函數(shù)即可以輕松獲得。

            void CControlButton::SetRgnMask(int nMaskBmpId, bool nAction)

            • 功能:設(shè)置有效區(qū)域函數(shù):
            • 返回值:無
            • 參數(shù):nMaskBmpId ,圖2的資源ID
              nAction ,值為TRUE則設(shè)置有效,F(xiàn)ALSE則無效,通過這樣可以使用或禁止構(gòu)造響應(yīng)區(qū)域

            void CControlButton::SetBitmapId(int nOver,int nNormal,int nPressed,int nFocus)

            • 功能:設(shè)置按鈕動態(tài)加載的四幅圖片 :
            • 返回值:無
            • 參數(shù):nOver,鼠標(biāo)劃過對應(yīng)按鈕圖片資源ID。
              nNormal ,正常狀態(tài)下 對應(yīng)按鈕圖片資源ID
              nPressed ,按下按鈕對應(yīng)圖片資源ID
              nFocus ,獲得焦點(diǎn)情況下圖片資源ID

            使用說明

            CControlButton類從CButton類派生,使用時,只需在界面上放置一個按鈕控件,添加CControlButton類,關(guān)聯(lián)一個CControlButton的控件變量,然后進(jìn)行初始化即可:

            CRect btnRect; //定義按鈕矩形變量
            m_demoBtn.GetWindowRect(btnRect); //獲取按鈕窗口矩形區(qū)域
            ScreenToClient(btnRect); //轉(zhuǎn)換成客戶區(qū)域
            
            //設(shè)置按鈕的背景圖片,跟主窗口的背景圖片一樣
            m_demoBtn.SetBackBmp(IDB_BACKGROUND,btnRect);
            m_demoBtn.SetRgnMask(IDB_OKmask,TRUE);//設(shè)置響應(yīng)區(qū)域,TRUE設(shè)置構(gòu)造區(qū)域有效
            m_demoBtn.SetMaskBitmapId(IDB_OKmask,TRUE);   //設(shè)置掩碼圖片
            
            //設(shè)置按鈕的四種狀態(tài)圖
            m_demoBtn.SetBitmapId(IDB_btn_ok_b,IDB_btn_ok_a,IDB_btn_ok_c,IDB_btn_ok_a); 
            

            結(jié)束語

            本類是在我朋友hurryboylqs四態(tài)圖片按鈕類的基礎(chǔ)上完成,衷心感謝hurryboylqs的幫助,希望本文對大家有一點(diǎn)點(diǎn)幫助。本人深知本類還有一些不足之處,如若大家對本類有修改完善,也請連修改說明給我發(fā)送一份,萬分感謝!

            posted on 2011-07-12 17:49 厚積薄發(fā) 閱讀(842) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程

            導(dǎo)航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計

            常用鏈接

            留言簿

            隨筆分類

            文章分類

            文章檔案

            搜索

            最新評論

            久久91精品国产91久久小草| 久久国产美女免费观看精品| 97视频久久久| 久久精品人人做人人爽97| 国产精品国色综合久久| 亚洲综合精品香蕉久久网97| 久久久WWW成人免费精品| 久久九九兔免费精品6| 一本大道加勒比久久综合| 亚洲国产成人久久笫一页| 久久电影网2021| 亚洲综合精品香蕉久久网| 国产亚州精品女人久久久久久 | 理论片午午伦夜理片久久 | 伊人色综合九久久天天蜜桃| 精品久久久久久无码专区不卡 | 国产成人精品久久一区二区三区av | 亚洲精品国产第一综合99久久| 99re这里只有精品热久久| 久久精品国产AV一区二区三区| 狠狠人妻久久久久久综合蜜桃| 91精品国产乱码久久久久久| 99蜜桃臀久久久欧美精品网站| 久久天天躁狠狠躁夜夜2020老熟妇| 69国产成人综合久久精品| 国内精品九九久久精品| 久久久久这里只有精品| 国产精品成人无码久久久久久| 国产Av激情久久无码天堂| 日韩精品久久久肉伦网站| 亚洲国产美女精品久久久久∴| 国产69精品久久久久APP下载 | 国产精品美女久久久久久2018| 国产69精品久久久久观看软件| 一级a性色生活片久久无少妇一级婬片免费放 | 久久精品国产亚洲精品2020| 亚洲伊人久久大香线蕉综合图片| 久久综合鬼色88久久精品综合自在自线噜噜 | 久久精品夜色噜噜亚洲A∨| 国产精品一区二区久久精品无码| 国产午夜电影久久|