• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 在VC中透明浮動按鍵的實現

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    有一種按鍵,看起來是一幅完整的圖片,當鼠標移到按鍵區域時,圖片的一部分凸現,形成一個按鍵,當鼠標移走時又恢復原來狀態。 最近,看了一些關于浮動按鍵的代碼,其原理大致上跟CBitmapButton差不多,用數幅位圖代表按鍵的各個狀態,響應鼠標的各種消息來
        有一種按鍵,看起來是一幅完整的圖片,當鼠標移到按鍵區域時,圖片的一部分凸現,形成一個按鍵,當鼠標移走時又恢復原來狀態。

         最近,看了一些關于浮動按鍵的代碼,其原理大致上跟CBitmapButton差不多,用數幅位圖代表按鍵的各個狀態,響應鼠標的各種消息來設置按鍵的狀態,實現按鍵的浮動顯示,但是這樣的按鍵卻不能和周圍的背景混和成一幅圖片。

         為了實現“透明”按鍵,可以簡單地做個試驗:先在對話框中加入一個BUTTON,通過屬性框選“Owner Draw”風格,再加入一個PICTURE,并加入圖片,將BUTTON移到PICTURE上。運行結果發現,按鍵沒有顯示出來,但在按鍵區域按下鼠標時,該按鍵仍然能發出WM_COMMAND消息,這樣一個純透明的按鍵建立了。顯然,這個按鍵是毫無使用意義的,因為用戶不知道按鍵的位置,必須讓用戶容易覺察到按鍵的位置,可以把這個按鍵改造一下:

         (首先從CButton派生出一個新類CDrawButton)

         ·把按鍵的標題顯示出來

         這個實現起來比較簡單,我們可以重載CButton類的成員函數DrawItem(),

    void CDrawButton::DrawItem
    (LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    CDC dc;
    CRect rect=lpDrawItemStruct- >rcItem;//得到按鍵區域
    CString sCaption;
    dc.Attach(lpDrawItemStruct- >hDC); //得到設備環境CDC
    VERIFY(lpDrawItemStruct- >CtlType==ODT_BUTTON);
    GetWindowText(sCaption);//得到按鍵的標題
    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是成員變量,它保存了對話框的字體指針,為了按鍵的標題風格與對話框的字體風格一致,在初始化時調用對話框的成員函數GetFont()即可得到指向對話框字體的CFont類指針。

         ·使按鍵浮動顯示

        要通過自繪來表示按鍵的各種狀態,可填寫DRAWITEMSTRUCT來通知DrawItem()函數需要做什么,我們先了解一下DRAWITEMSTRUCT:

    typedef struct tagDRAWITEMSTRUCT{
        UINT CtlType; // 控件類型
        UINT CtlID;// 控件的ID號
        UNIT itemID;//菜單項的索引
        UINT itemAction;// 繪圖操作
        UINT itemState; // 狀態
        HWND hwndItem; // 控件的窗口句柄
        HDC hDC; // 相關的設備環境
        RECT rcItem;//控件的范圍
        DWORD itemData;//指定與菜單項相聯系的應用程序定義的32位值
    }DRAWITEMSTRUCT;

        利用這個結構先做一個按鍵狀態設置函數:
    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));
    }

        這樣,我們可以響應鼠標的各種消息來設置按鍵的各種狀態:
    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是個UINT類型的成員變量,它可以有三種自定義狀態:
    BTN_NORMAL    正常狀態
    BTN_UP        鼠標移入按鍵區域或釋放鼠標
    BTN_DOWN    按下鼠標
    (可以再加一種DISABLE狀態)

        當在按鍵區域釋放鼠標時,必須發送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);
    }

        接著就是繪制按鍵的各種狀態:由于按鍵必須“透明”,所以在按下和釋放時只在按鍵區域的四周加上一個3D邊框就行了。而在正常狀態下,則必須去掉邊框恢復背景。但如何恢復背景圖象呢?我是這樣做的:在按鍵初始化時,先把被按鍵覆蓋了的區域保存在一個CBitmap類中,以后需要重繪按鍵時就把這個CBitmap畫在按鍵上就行了。
    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);
    //得到繪制的設備環境CDC
        VERIFY(lpDrawItemStruct- >CtlType==ODT_BUTTON);

        if (lpDrawItemStruct- >itemAction & ODA_DRAWENTIRE){
            //重繪控件(正常狀態)
            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();
            }
            //顯示按鍵標題
            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)){
    //按下鼠標
    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)){
    //釋放鼠標或鼠標進入按鍵區域
    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();
    }

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

        CRect rect;
        GetWindowRect(&rect);
        pParent- >ScreenToClient(&rect);//獲得按鍵區域
        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();//獲得窗口或對話框的字體

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

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

        而使這個類和對話框上的按鍵產生聯系還必須調用一下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;
    }


        這個類還必須具有三個成員變量:
        CFont* m_pFont;
        CBitmap* m_pBitmap;
        UINT mBtnStats;

    在構造函數中初始化這些變量
        m_pBitmap=0;
        m_pFont=0;
        //賦予0是可以的
        mBtnStats=BTN_NORMAL;

    在折構函數中拆除位圖
        if(m_pBitmap!=0) delete m_pBitmap;

        這樣,一個透明的浮動式按鍵類就做好了,具體實現方法以下:
        1.接管對話框的BUTTON,首先在對話框上畫一個BUTTON,再加一個PICTURE圖片,BUTTON的風格必須加入OWNER DRAW及去掉VISIBLE,把BUTTON移到PICTURE上適當的位置,在對話框類加入CDrawButton類成員m_myButton,由于按鍵初始化時必須保存對話框的圖象,而對話框在運行InitDialog()或第一次運行OnPaint()時對話框的控件還沒有真正顯示出來,我們只好在OnMouseMove()中進行初始化:

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

        2.動態建立CDrawButton,在對話框類或CxxxView類加入CDrawButton類成員m_myButton,可以在對話框的InitDialog()或CxxxView類的InitialUpdate()中加入:m_myButton.Create()函數,必須包含BS_OWNERDRAW而不能有WS_VISIBLE風格,然后在OnMouseMove()或OnDraw()中進行初始化:m_myButton.LoadBack(this);注意應加在OnDraw()的最后。

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

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

        ·當鼠標移到按鍵區域時,改變鼠標

        這個很容易實現,不在這里多說了。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>