人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當(dāng)前位置:蘿卜系統(tǒng)下載站 > 技術(shù)開(kāi)發(fā)教程 > 詳細(xì)頁(yè)面

在VC中透明浮動(dòng)按鍵的完成

在VC中透明浮動(dòng)按鍵的完成

更新時(shí)間:2022-09-23 文章作者:未知 信息來(lái)源:網(wǎng)絡(luò) 閱讀次數(shù):

    有一種按鍵,看起來(lái)是一幅完整的圖片,當(dāng)鼠標(biāo)移到按鍵區(qū)域時(shí),圖片的一部分凸現(xiàn),形成一個(gè)按鍵,當(dāng)鼠標(biāo)移走時(shí)又恢復(fù)原來(lái)狀態(tài)。

     最近,看了一些關(guān)于浮動(dòng)按鍵的代碼,其原理大致上跟CBitmapButton差不多,用數(shù)幅位圖代表按鍵的各個(gè)狀態(tài),響應(yīng)鼠標(biāo)的各種消息來(lái)設(shè)置按鍵的狀態(tài),實(shí)現(xiàn)按鍵的浮動(dòng)顯示,但是這樣的按鍵卻不能和周?chē)谋尘盎旌统梢环鶊D片。

     為了實(shí)現(xiàn)“透明”按鍵,可以簡(jiǎn)單地做個(gè)試驗(yàn):先在對(duì)話(huà)框中加入一個(gè)BUTTON,通過(guò)屬性框選“Owner Draw”風(fēng)格,再加入一個(gè)PICTURE,并加入圖片,將BUTTON移到PICTURE上。運(yùn)行結(jié)果發(fā)現(xiàn),按鍵沒(méi)有顯示出來(lái),但在按鍵區(qū)域按下鼠標(biāo)時(shí),該按鍵仍然能發(fā)出WM_COMMAND消息,這樣一個(gè)純透明的按鍵建立了。顯然,這個(gè)按鍵是毫無(wú)使用意義的,因?yàn)橛脩?hù)不知道按鍵的位置,必須讓用戶(hù)容易覺(jué)察到按鍵的位置,可以把這個(gè)按鍵改造一下:

     (首先從CButton派生出一個(gè)新類(lèi)CDrawButton)

     ·把按鍵的標(biāo)題顯示出來(lái)

     這個(gè)實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,我們可以重載CButton類(lèi)的成員函數(shù)DrawItem(),

void CDrawButton::DrawItem
(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
CRect rect=lpDrawItemStruct- >rcItem;//得到按鍵區(qū)域
CString sCaption;
dc.Attach(lpDrawItemStruct- >hDC); //得到設(shè)備環(huán)境CDC
VERIFY(lpDrawItemStruct- >CtlType==ODT_BUTTON);
GetWindowText(sCaption);//得到按鍵的標(biāo)題
dc.SetBkMode(TRANSPARENT);//透明顯示
CFont* m_pOldFont=dc.SelectObject(m_pFont);
dc.DrawText(sCaption,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
dc.SelectObject(m_pOldFont);
}

     其中的m_pFont是成員變量,它保存了對(duì)話(huà)框的字體指針,為了按鍵的標(biāo)題風(fēng)格與對(duì)話(huà)框的字體風(fēng)格一致,在初始化時(shí)調(diào)用對(duì)話(huà)框的成員函數(shù)GetFont()即可得到指向?qū)υ?huà)框字體的CFont類(lèi)指針。

     ·使按鍵浮動(dòng)顯示

    要通過(guò)自繪來(lái)表示按鍵的各種狀態(tài),可填寫(xiě)DRAWITEMSTRUCT來(lái)通知DrawItem()函數(shù)需要做什么,我們先了解一下DRAWITEMSTRUCT:

typedef struct tagDRAWITEMSTRUCT{
    UINT CtlType; // 控件類(lèi)型
    UINT CtlID;// 控件的ID號(hào)
    UNIT itemID;//菜單項(xiàng)的索引
    UINT itemAction;// 繪圖操作
    UINT itemState; // 狀態(tài)
    HWND hwndItem; // 控件的窗口句柄
    HDC hDC; // 相關(guān)的設(shè)備環(huán)境
    RECT rcItem;//控件的范圍
    DWORD itemData;//指定與菜單項(xiàng)相聯(lián)系的應(yīng)用程序定義的32位值
}DRAWITEMSTRUCT;

    利用這個(gè)結(jié)構(gòu)先做一個(gè)按鍵狀態(tài)設(shè)置函數(shù):
void CDrawButton::SetButtonMode(UINT action, UINT mode)
{
// TODO: Add your message handler code
here and/or call default
    DRAWITEMSTRUCT DIS;
    DIS.CtlType = ODT_BUTTON;
    DIS.CtlID = GetDlgCtrlID();
    DIS.itemAction = action;
    DIS.itemState = mode;
    DIS.hwndItem = GetSafeHwnd();
    DIS.hDC = GetDC()- >GetSafeHdc();
    GetClientRect(&(DIS.rcItem));
    SendMessage(WM_DRAWITEM,(WPARAM)
GetSafeHwnd(),(LPARAM)&DIS);
    ReleaseDC(CDC::FromHandle(DIS.hDC));
}

    這樣,我們可以響應(yīng)鼠標(biāo)的各種消息來(lái)設(shè)置按鍵的各種狀態(tài):
void CDrawButton::OnMouseMove
(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code
here and/or call default
    CRect rect;
    GetClientRect(&rect);
    if(rect.PtInRect(point)){
        if (mBtnStats==BTN_NORMAL){
    SetButtonMode(ODA_SELECT, ODS_FOCUS);
            SetCapture();
        }
    }
    else{
//AutoLoad(GetDlgCtrlID(),GetParent());
SetButtonMode(ODA_DRAWENTIRE,ODS_DEFAULT);
        ReleaseCapture();
    }

    CButton::OnMouseMove(nFlags, point);
}

    這里,mBtnStats是個(gè)UINT類(lèi)型的成員變量,它可以有三種自定義狀態(tài):
BTN_NORMAL    正常狀態(tài)
BTN_UP        鼠標(biāo)移入按鍵區(qū)域或釋放鼠標(biāo)
BTN_DOWN    按下鼠標(biāo)
(可以再加一種DISABLE狀態(tài))

    當(dāng)在按鍵區(qū)域釋放鼠標(biāo)時(shí),必須發(fā)送WM_COMMAND消息:
void CDrawButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code
here and/or call default
    CRect rect;
    GetClientRect(&rect);
    if(rect.PtInRect(point)){
        if (mBtnStats==BTN_DOWN)
            GetParent()- >SendMessage(WM_COMMAND,
        MAKELPARAM(GetDlgCtrlID(),BN_CLICKED),
        (LPARAM)GetSafeHwnd());
        SetCapture();
    }
    else{
    SetButtonMode(ODA_DRAWENTIRE,ODS_DEFAULT);
        ReleaseCapture();
    }

    CButton::OnLButtonUp(nFlags, point);
}

    接著就是繪制按鍵的各種狀態(tài):由于按鍵必須“透明”,所以在按下和釋放時(shí)只在按鍵區(qū)域的四周加上一個(gè)3D邊框就行了。而在正常狀態(tài)下,則必須去掉邊框恢復(fù)背景。但如何恢復(fù)背景圖象呢?我是這樣做的:在按鍵初始化時(shí),先把被按鍵覆蓋了的區(qū)域保存在一個(gè)CBitmap類(lèi)中,以后需要重繪按鍵時(shí)就把這個(gè)CBitmap畫(huà)在按鍵上就行了。
void CDrawButton::DrawItem
(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // TODO: Add your code to draw the specified item
    CDC dc;
    CRect rect=lpDrawItemStruct- >rcItem;
    CString sCaption;
    dc.Attach(lpDrawItemStruct->hDC);
//得到繪制的設(shè)備環(huán)境CDC
    VERIFY(lpDrawItemStruct- >CtlType==ODT_BUTTON);

    if (lpDrawItemStruct- >itemAction & ODA_DRAWENTIRE){
        //重繪控件(正常狀態(tài))
        mBtnStats=BTN_NORMAL;
        if (m_pBitmap!=0){
            CDC memDC;
            memDC.CreateCompatibleDC(&dc);
            memDC.SelectObject(m_pBitmap);
    dc.BitBlt(0, 0, rect.Width(), rect.Height(),
                &memDC, 0, 0, SRCCOPY);
            memDC.DeleteDC();
        }
        //顯示按鍵標(biāo)題
        GetWindowText(sCaption);
        dc.SetBkMode(TRANSPARENT);
        if (m_pFont!=0){
        CFont* m_pOldFont=dc.SelectObject(m_pFont);
        dc.DrawText(sCaption,&rect,
    DT_CENTER|DT_VCENTER|DT_SINGLELINE);
            dc.SelectObject(m_pOldFont);
        }
    }

if ((lpDrawItemStruct- >itemState & ODS_SELECTED) &&
(lpDrawItemStruct- >itemAction & ODA_SELECT)){
//按下鼠標(biāo)
mBtnStats=BTN_DOWN;
dc.Draw3dRect(&rect,RGB(128,128,128),RGB(192,192,192));
rect.top=rect.top+1;rect.bottom=rect.bottom-1;
rect.left=rect.left+1;rect.right=rect.right-1;
dc.Draw3dRect(&rect,RGB(0,0,0),RGB(255,255,255));
    }

if(!(lpDrawItemStruct- >itemState & ODS_SELECTED) &&
(lpDrawItemStruct- >itemAction & ODA_SELECT)){
//釋放鼠標(biāo)或鼠標(biāo)進(jìn)入按鍵區(qū)域
mBtnStats=BTN_UP;
dc.Draw3dRect(&rect,RGB(255,255,255),RGB(0,0,0));
rect.top=rect.top+1;rect.bottom=rect.bottom-1;
rect.left=rect.left+1;rect.right=rect.right-1;
dc.Draw3dRect(&rect,RGB(192,192,192),RGB(128,128,128));
    }

    dc.Detach();
}

    接著就必須一些初始化工作,其中最關(guān)鍵就是把被按鍵覆蓋了的區(qū)域保存進(jìn)CBitmap類(lèi)中,我們知道CDC::StretchBlt()函數(shù)可以把位圖的指定區(qū)域從一個(gè)設(shè)備拷貝到另一個(gè)設(shè)備中,這樣可以很方便地把窗口或?qū)υ?huà)框的某個(gè)區(qū)域保存,條件是獲得其DC:
void CDrawButton::LoadBack(CWnd *pParent)
{
    ASSERT(GetStyle() & BS_OWNERDRAW);
    if (m_pBitmap!=0) return;

    CRect rect;
    GetWindowRect(&rect);
    pParent- >ScreenToClient(&rect);//獲得按鍵區(qū)域
    CPaintDC dc(pParent);
    if (m_pBitmap==0) m_pBitmap=new CBitmap;//初始化位圖
    m_pBitmap- >CreateCompatibleBitmap
(&dc,rect.Width(),rect.Height());
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    memDC.SelectObject(m_pBitmap);
memDC.StretchBlt(0, 0, rect.Width(),rect.Height(), &dc,
    rect.left, rect.top,
rect.Width(),rect.Height(), SRCCOPY);//保存
    memDC.DeleteDC();
m_pFont=pParent- >GetFont();//獲得窗口或?qū)υ?huà)框的字體

    ModifyStyle(0,WS_VISIBLE);//顯示按鍵

    SetBitmapMode(ODA_DRAWENTIRE,0);//繪制按鍵
}

    而使這個(gè)類(lèi)和對(duì)話(huà)框上的按鍵產(chǎn)生聯(lián)系還必須調(diào)用一下SubclassDlgItem():
BOOL CDrawButton::AutoLoad(UINT nID, CWnd *pParent)
{
// first attach the CDrawButton to the dialog control

    if (m_pBitmap!=0) return FALSE;

    if (!SubclassDlgItem(nID, pParent)) return FALSE;

    LoadBack(pParent);

    return TRUE;
}


    這個(gè)類(lèi)還必須具有三個(gè)成員變量:
    CFont* m_pFont;
    CBitmap* m_pBitmap;
    UINT mBtnStats;

在構(gòu)造函數(shù)中初始化這些變量
    m_pBitmap=0;
    m_pFont=0;
    //賦予0是可以的
    mBtnStats=BTN_NORMAL;

在折構(gòu)函數(shù)中拆除位圖
    if(m_pBitmap!=0) delete m_pBitmap;

    這樣,一個(gè)透明的浮動(dòng)式按鍵類(lèi)就做好了,具體實(shí)現(xiàn)方法以下:
    1.接管對(duì)話(huà)框的BUTTON,首先在對(duì)話(huà)框上畫(huà)一個(gè)BUTTON,再加一個(gè)PICTURE圖片,BUTTON的風(fēng)格必須加入OWNER DRAW及去掉VISIBLE,把BUTTON移到PICTURE上適當(dāng)?shù)奈恢茫趯?duì)話(huà)框類(lèi)加入CDrawButton類(lèi)成員m_myButton,由于按鍵初始化時(shí)必須保存對(duì)話(huà)框的圖象,而對(duì)話(huà)框在運(yùn)行InitDialog()或第一次運(yùn)行OnPaint()時(shí)對(duì)話(huà)框的控件還沒(méi)有真正顯示出來(lái),我們只好在OnMouseMove()中進(jìn)行初始化:

m_myButton.AutoLoad(IDC_BUTTON1,this);
AutoLoad()只運(yùn)行一次。

    2.動(dòng)態(tài)建立CDrawButton,在對(duì)話(huà)框類(lèi)或CxxxView類(lèi)加入CDrawButton類(lèi)成員m_myButton,可以在對(duì)話(huà)框的InitDialog()或CxxxView類(lèi)的InitialUpdate()中加入:m_myButton.Create()函數(shù),必須包含BS_OWNERDRAW而不能有WS_VISIBLE風(fēng)格,然后在OnMouseMove()或OnDraw()中進(jìn)行初始化:m_myButton.LoadBack(this);注意應(yīng)加在OnDraw()的最后。

    同樣地,LoadBack()只運(yùn)行一次。

    (如果按鍵比背景的圖片遲建立而具有可見(jiàn)(Visible)屬性,則會(huì)把圖片抹掉,所以必須去掉VISIBLE屬性或不能加入WS_VISIBLE風(fēng)格)

    ·當(dāng)鼠標(biāo)移到按鍵區(qū)域時(shí),改變鼠標(biāo)

    這個(gè)很容易實(shí)現(xiàn),不在這里多說(shuō)了。

溫馨提示:喜歡本站的話(huà),請(qǐng)收藏一下本站!

本類(lèi)教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 胶南市| 阳曲县| 阿拉善左旗| 平泉县| 大英县| 华坪县| 贵溪市| 保康县| 宝清县| 襄垣县| 波密县| 古浪县| 蓬莱市| 时尚| 周宁县| 阿坝| 岱山县| 平南县| 铁岭县| 炎陵县| 云龙县| 屏东市| 长岛县| 依兰县| 安阳县| 武定县| 新津县| 叙永县| 安庆市| 穆棱市| 永济市| 凉城县| 临潭县| 肃北| 衡阳市| 灵石县| 定边县| 旺苍县| 山阴县| 武汉市| 蒙自县|