• <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>

            制作彈出式菜單按鈕

            下面,我們看一下它的制作過程:


            一、新建一個以CButton類為基類的新類
            單擊“Insert”→“New Class”,建立一個新類。基類設置為CButton,新類起名為CMenuButton
            二、利用自繪方法繪制按鈕
            主體區顯示按鈕文本,選擇區畫一個小箭頭
            CMenuButton類中用ClassWizard添加函數:PreSubclassWindow()DrawItem()
            PreSubclassWindow()
            函數在建立按鈕時執行,可用于做一些準備工作。在這里我給按鈕添加自繪屬性:


            void CMenuButton::PreSubclassWindow() 
            {
                ModifyStyle( 0, BS_OWNERDRAW );    
            //設置按鈕屬性為自繪式
                
                CButton::PreSubclassWindow();
            }

            DrawItem()函數用于繪制按鈕,左邊繪制按鈕文字,作為主體區,右邊繪制一個小箭頭,作為選擇區。實際應用中,可根據具體需要繪制想要的形狀和內容。


            void CMenuButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
            {
                CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
                m_ButRect = lpDrawItemStruct->rcItem;    
            //獲取按鈕尺寸
                int nSavedDC = pDC->SaveDC();
                VERIFY( pDC );

                DrawButton(pDC);    
            //繪制按鈕

                pDC->RestoreDC( nSavedDC );
            }

            其中m_ButRect都是CRect型對象,在頭文件中進行定義。DrawButton()為繪制按鈕的函數,把它定義在外邊的目的是方便用戶修改,如果你想改變按鈕形狀,只需修改DrawButton()函數即可。


            void CMenuButton::DrawButton(CDC *pDC)
            {
                m_LRect.SetRect( m_ButRect.left, m_ButRect.top,
                    m_ButRect.right-21, m_ButRect.bottom );  
            //按鈕主體區尺寸
                m_RRect.SetRect( m_ButRect.right-20, m_ButRect.top,
                    m_ButRect.right, m_ButRect.bottom );    
            //按鈕選擇區尺寸

                CPen Pen;
                Pen.CreatePen(PS_SOLID, 1, RGB(192,192,192) );
                pDC->SelectObject( &Pen );

                pDC->FillSolidRect( m_ButRect, m_BackColor );  
            //畫背景
                switch( m_State )    
            //不同狀態畫不同邊框
                {
                case 0:        
            //正常按鈕
                    pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
                    pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
                    break;
                case 1:        
            //鼠標進入時的按鈕
                    pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
                    pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
                    pDC->MoveTo( m_ButRect.TopLeft() );
                    pDC->LineTo( m_ButRect.right, m_ButRect.top );
                    break;
                case 2:        
            //單擊按鈕主體區時的按鈕
                    pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
                    break;
                case 3:        
            //單擊按鈕選擇區時的按鈕
                    pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
                    break;
                }

                POINT    m_pt[3], m_ptCentre;        
            //箭頭坐標(三個頂點)
                m_ptCentre = m_RRect.CenterPoint();  
            //選擇區中點位置
                m_pt[0].x = m_ptCentre.x-3;        
            //計算箭頭坐標
                m_pt[0].y = m_ptCentre.y-2;
                m_pt[1].x = m_ptCentre.x+4;
                m_pt[1].y = m_ptCentre.y-2;
                m_pt[2].x = m_ptCentre.x;
                m_pt[2].y = m_ptCentre.y+2;

                pDC->SelectStockObject( BLACK_BRUSH );  
            //定義畫刷(黑色)
                CRgn rgn;
                rgn.CreatePolygonRgn( m_pt, 3, ALTERNATE );
                pDC->PaintRgn( &rgn );            
            //畫選擇區箭頭

                pDC->SetTextColor( m_ForeColor ); 
            //畫主體區文字
                pDC->SetBkMode( TRANSPARENT );
                pDC->DrawText( m_strText, &m_LRect, DT_SINGLELINE | DT_CENTER
                    | DT_VCENTER | DT_END_ELLIPSIS);
            }

            m_State是個標志,=0表示正常按鈕;=1表示鼠標進入按鈕,繪制暗線邊框;=2表示在按鈕主體區按下鼠標左鍵;=3表示在按鈕選擇區按下鼠標左鍵。

            m_State的不同取值下,繪制不同的按鈕邊框,可以增加按鈕的動態效果。

            三、添加鼠標響應函數

            CMenuButton類中用ClassWizard添加函數:OnMouseMove()OnLButtonDown()OnLButtonUp()
            OnMouseMove()
            函數用于響應鼠標移動消息,當鼠標進入按鈕時,設置相應標志,并重繪按鈕邊框,當鼠標離開按鈕時,清除標志,恢復原邊框。


            void CMenuButton::OnMouseMove(UINT nFlags, CPoint point) 
            {
                if( !b_InFlag || GetCapture()!=this )    
            //鼠標進入按鈕
                {
                    b_InFlag = true;    
            //設置進入標志
                    SetCapture();       
            //捕獲鼠標
                    m_State = 1;        
            //置按鈕狀態(1-當前按鈕)
                    if( b_ClickFlag )   
            //檢測單擊選擇區標志
                    {
                        m_Menu.Detach();    
            //清除打開的菜單
                        m_Menu.DestroyMenu();
                        b_ClickFlag = false;
                    }
                    Invalidate();       
            //重繪按鈕
                }
                else
                {
                    if ( !m_ButRect.PtInRect(point) )    
            //鼠標離開按鈕
                    {
                        b_InFlag = false;    
            //清除進入標志
                        ReleaseCapture();    
            //釋放鼠標捕獲
                        b_ClickBut = false;  
            //清除單擊標志
                        m_State = 0;         
            //置按鈕狀態(0-正常按鈕)
                        if( b_ClickFlag )    
            //檢測單擊選擇區標志
                        {
                            m_Menu.Detach();    
            //清除打開的菜單
                            m_Menu.DestroyMenu();
                            b_ClickFlag = false;
                        }
                        Invalidate();        
            //重繪按鈕
                    }
                }
                
                CButton::OnMouseMove(nFlags, point);
            }

            b_InFlag是個BOOL型量,鼠標進入時設置,離開時清除,目的是防止鼠標在按鈕上移動時重復刷新按鈕,以避免閃爍。
            b_ClickFlag
            是單擊按鈕選擇區標志,當它為true時,表示彈出菜單已打開,為false時表示菜單未彈出。當菜單已經彈出,而鼠標又移回按鈕單擊時,應清除菜單。
            b_ClickBut
            是單擊按鈕主體區標志。
            OnLButtonDown()
            函數響應按鈕單擊消息,當單擊的是按鈕主體區時,設置b_ClickBut標志;當單擊的是按鈕選擇區時,要根據單擊次數,決定是否彈出菜單。


            void CMenuButton::OnLButtonDown(UINT nFlags, CPoint point) 
            {
                if( m_LRect.PtInRect(point) )    
            //單擊按鈕主體區
                {
                    m_State = 2;        
            //置按鈕狀態(2-正常按鈕)
                    b_ClickBut = true;  
            //設置單擊按鈕標志
                    Invalidate();       
            //重繪按鈕
                }
                else if( m_RRect.PtInRect(point) && m_MenuID )  
            //單擊選擇區
                {
                    m_State = 3;
                    b_ClickBut = false;    
            //清除單擊按鈕標志
                    Invalidate();          
            //重繪按鈕
                    b_ClickFlag = !b_ClickFlag;    
            //單擊選擇區標志
                    if( b_ClickFlag )    
            //一次單擊,彈出菜單
                    {
                        CRect rect = m_RRect;
                        ClientToScreen(rect);    
            //轉換為屏幕坐標
                        point = rect.BottomRight();
                        point.x -= rect.Width(); 
            //設置彈出菜單的位置

                        VERIFY(m_Menu.LoadMenu(m_MenuID));  
            //裝入菜單資源

                        CMenu* pPopup = m_Menu.GetSubMenu(0);
                        ASSERT(pPopup != NULL);
                        CWnd* pWndPopupOwner = this;

                        while (pWndPopupOwner->GetStyle() & WS_CHILD)
                            pWndPopupOwner = pWndPopupOwner->GetParent();

                        pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
                            point.x, point.y, pWndPopupOwner);  
            //彈出菜單
                    }
                    else        
            //再次單擊,清除菜單
                    {
                        m_Menu.Detach();
                        m_Menu.DestroyMenu();
                    }
                }
                
                CButton::OnLButtonDown(nFlags, point);
            }

            當單擊按鈕選擇區時,在選擇區的左下角彈出菜單,函數中的point是鼠標的屏幕坐標,求菜單位置時也使用屏幕坐標。
            m_MenuID
            是與按鈕關聯的彈出菜單的ID,它在創建按鈕時進行設置。
            OnLButtonUp()
            函數響應按鈕彈起消息,這是只要恢復按鈕正常狀態即可,以產生單擊動畫效果。


            void CMenuButton::OnLButtonUp(UINT nFlags, CPoint point) 
            {
                m_State = 0;    
            //恢復為正常按鈕
                Invalidate();   
            //重繪按鈕
                
                CButton::OnLButtonUp(nFlags, point);
            }

            四、自定義接口函數

            提供用戶使用按鈕的接口。


            //設置關聯菜單ID
            void CMenuButton::SetMenuID(int nID)
            {
                m_MenuID = nID;
            }

            //設置按鈕文本
            void CMenuButton::SetText(CString str)
            {
                m_strText = str;
            }

            //設置文本顏色
            void CMenuButton::SetForeColor(COLORREF color)
            {
                m_ForeColor = color;
                Invalidate();
            }

            //設置背景顏色
            void CMenuButton::SetBkColor(COLORREF color)
            {
                m_BackColor = color;
                Invalidate();
            }

            //是否單擊主按鈕區
            BOOL CMenuButton::isClick()
            {
                return b_ClickBut;
            }

            由于這種按鈕分為兩個區域,使用時要根據單擊區域決定要做的工作,所以設置了isClick()接口函數。

            五、變量的初始化

            CMenuButton類的頭文件中,定義有以下變量和函數:


            MenuButton.h

            private:
                int         m_State;        
            //按鈕狀態
                BOOL        b_InFlag;       
            //鼠標進入標志
                BOOL        b_ClickFlag;    
            //單擊選擇區
                BOOL        b_ClickBut;     
            //單擊主體區
                CString     m_strText;      
            //按鈕文字
                COLORREF    m_ForeColor;    
            //文本顏色
                COLORREF    m_BackColor;    
            //背景色
                CRect       m_ButRect;      
            //按鈕尺寸
                CRect       m_LRect;        
            //按鈕左部尺寸
                CRect       m_RRect;        
            //按鈕右部尺寸
                CMenu       m_Menu;         
            //彈出菜單
                int         m_MenuID;       
            //菜單ID

                void DrawButton(CDC *pDC);    
            //繪制按鈕

            public:
                CMenuButton();        
            //構造函數
                void SetMenuID(int nID);        
            //設置關聯菜單ID
                void SetForeColor(COLORREF color);   
            //設置文本顏色
                void SetBkColor(COLORREF color);     
            //設置背景顏色
                void SetText(CString str); 
            //設置按鈕文本
                BOOL isClick();            
            //是否單擊主按鈕區

            各變量的初始化在構造函數中進行:


            CMenuButton::CMenuButton()
            {
                m_MenuID = 0;        
            //菜單ID
                b_InFlag = false;    
            //進入標志
                m_State = 0;         
            //初始狀態
                b_ClickFlag = false; 
            //單擊選擇區標志
                b_ClickBut = false;  
            //單擊主體區標志
                m_strText = _T("");  
            //按鈕文本
                m_ForeColor = RGB(0,0,0);    
            //文字顏色
                m_BackColor = GetSysColor( COLOR_3DFACE );  
            //背景色
            }

            這樣,帶菜單的按鈕類就做好了,用它定義的按鈕實例可以連接一個彈出式按鈕,下面我們就看看怎樣定義按鈕實例。

            六、生成按鈕實例

            1、在對話框中放置按鈕,把它的大小調整合適;

            2、用ClassWizard為按鈕添加變量,把變量的類型設置為CMenuButton
            3
            、定義按鈕的關聯菜單
            關聯菜單就是普通的彈出式菜單,用VC的菜單編輯器生成即可。進入資源的“Menu”項,插入一個新的菜單,根據需要添加菜單項。
            4
            、設置按鈕

            在對話框的OnInitial()函數中初始化按鈕:


            按鈕變量.SetMenuID( 菜單ID );
            按鈕變量.SetText( 按鈕文本 );
            按鈕變量.SetBkColor( 按鈕背景色 );

            七、按鈕的響應

            對按鈕的響應包括單擊按鈕主體區的響應和單擊菜單項的響應兩部分。用ClassWizard添加按鈕的響應函數和各菜單項的響應函數。

            在按鈕的響應函數中要做如下工作:


            void CMBTestView::OnMenubutton1() 
            {
                if( m_MenuButton1.isClick() )
                {
                    
            //響應按鈕操作
                }
            }

            這里要求只有單擊按鈕的主體區時才進行響應。

            至于單擊菜單項的響應與普通菜單一樣,這里不再詳述。

            這個按鈕類還有幾點可考慮改進:

            ①增加無效狀態(變灰)按鈕;

            ②設置按鈕文字字體。

            posted on 2008-05-04 21:50 wrh 閱讀(952) 評論(0)  編輯 收藏 引用

            導航

            <2009年3月>
            22232425262728
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            統計

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            伊人久久精品影院| 久久99精品久久久久久野外 | 国产精品久久久久aaaa| 久久夜色tv网站| 久久天天躁狠狠躁夜夜不卡| 国产香蕉久久精品综合网| 久久99国产综合精品女同| 精品久久久久久久中文字幕| 久久久精品国产免大香伊| 99久久精品无码一区二区毛片| 2021国产精品午夜久久| 久久国产精品久久国产精品| 久久久久国产成人精品亚洲午夜| 久久久SS麻豆欧美国产日韩| 精品久久久久久综合日本| 久久婷婷色综合一区二区| 久久久久免费精品国产| 精产国品久久一二三产区区别| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 亚洲国产精品成人久久蜜臀| 亚洲午夜久久久影院| 日产久久强奸免费的看| 91精品国产高清久久久久久国产嫩草 | 久久人人爽人人人人片av| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久青青国产| 97超级碰碰碰碰久久久久| 久久久久99精品成人片欧美| 欧美国产成人久久精品| 亚洲国产成人久久一区WWW| 久久久综合香蕉尹人综合网| 久久青青草原精品影院| 久久精品国产福利国产秒| 久久国产热精品波多野结衣AV| 亚洲va久久久噜噜噜久久男同| 欧美一区二区久久精品| 久久久久亚洲av综合波多野结衣| 日韩十八禁一区二区久久| 国产精品久久久香蕉| 亚洲精品综合久久| 亚洲香蕉网久久综合影视|