青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

制作彈出式菜單按鈕

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


一、新建一個以CButton類為基類的新類
單擊“Insert”→“New Class”,建立一個新類?;愒O置為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 閱讀(964) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

統計

常用鏈接

留言簿(19)

隨筆檔案

文章檔案

收藏夾

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            日韩午夜精品| 欧美国产先锋| 久久久欧美精品sm网站| 欧美国产日韩一区二区三区| 亚洲在线视频免费观看| 欧美丰满少妇xxxbbb| 女主播福利一区| 国产美女精品一区二区三区| 日韩亚洲欧美成人一区| 欧美尤物一区| 久久婷婷久久一区二区三区| 亚洲大胆视频| 中文久久精品| 一区久久精品| 亚洲视频在线一区观看| 亚洲第一狼人社区| 亚洲无限乱码一二三四麻| 亚洲电影欧美电影有声小说| 中国成人在线视频| 亚洲精品护士| 欧美专区日韩专区| 一区二区三区免费看| 久久久久久久综合狠狠综合| 午夜在线不卡| 欧美久久久久久久久| 美腿丝袜亚洲色图| 国产精品久久久久一区二区三区 | 亚洲成人资源网| 国产精品久久久久aaaa九色| 欧美激情精品久久久久久久变态| 国产精品丝袜白浆摸在线| 亚洲国产第一| 激情综合自拍| 亚洲欧美国产va在线影院| 一本色道久久综合亚洲精品不 | 亚洲一区制服诱惑| 欧美国产日韩精品| 毛片av中文字幕一区二区| 国产精品一区二区黑丝| 一本色道久久综合精品竹菊| 日韩亚洲视频| 欧美阿v一级看视频| 欧美a级一区| 在线成人黄色| 久久久亚洲国产天美传媒修理工| 久久精品综合| 国产一区二区三区免费不卡| 亚洲一区网站| 午夜精品久久久久99热蜜桃导演| 国产精品国产三级国产| 亚洲午夜小视频| 亚洲免费在线观看视频| 欧美午夜www高清视频| 99re在线精品| 亚洲欧美综合| 国产精品一区二区三区四区| 亚洲欧美bt| 久久九九热re6这里有精品| 免费一级欧美片在线观看| 亚洲性图久久| 亚洲激情专区| 亚洲伦理在线观看| 激情偷拍久久| 91久久夜色精品国产九色| 亚洲黄色在线看| 欧美专区在线观看一区| 亚洲五月六月| 国产区精品视频| 午夜视频久久久| 久久久综合激的五月天| 136国产福利精品导航| 蜜桃久久av| 亚洲高清在线视频| 亚洲天堂免费观看| 国产欧美日韩另类视频免费观看| 欧美一区二区视频在线观看2020| 鲁大师影院一区二区三区| 亚洲人精品午夜| 国产精品v亚洲精品v日韩精品| 亚洲一区二区三区免费观看| 久久久99国产精品免费| 亚洲黄色尤物视频| 国产精品久久久亚洲一区 | 在线欧美三区| 欧美激情中文字幕一区二区 | 亚洲免费av片| 国产精品美女久久福利网站| 欧美在线观看视频一区二区| 免费在线看一区| 亚洲色图在线视频| 国产真实乱偷精品视频免| 欧美1区免费| 亚洲一区区二区| 亚洲国产精品第一区二区三区| 亚洲一区二区综合| 亚洲国产精品国自产拍av秋霞 | 亚洲国产精品一区制服丝袜| 午夜欧美电影在线观看| 亚洲精品国产日韩| 国内精品一区二区三区| 欧美色道久久88综合亚洲精品| 欧美在线观看一区二区| 亚洲精品国产系列| 久热精品在线视频| 亚洲欧美综合网| 亚洲二区精品| 国产日韩欧美中文| 欧美精品在线播放| 久久久久中文| 午夜在线视频观看日韩17c| 亚洲国产精品一区二区第四页av| 欧美专区日韩专区| 亚洲网站在线观看| 亚洲国产91| 精品福利免费观看| 国产欧美日韩另类视频免费观看| 欧美久久久久| 欧美激情一区二区在线 | 久久久久久午夜| 午夜精品久久久久久| 99re6这里只有精品| 亚洲国产精品一区二区www| 国产精品美女久久久| 亚洲激情视频在线| 亚洲高清久久网| 国产日韩欧美一区| 国产精品国产三级国产普通话三级| 欧美福利视频| 免费不卡在线观看av| 久久久久国产精品一区二区| 亚洲欧美综合另类中字| 一区二区三区精品久久久| 亚洲精品中文字| 亚洲精品乱码久久久久久蜜桃91 | 欧美日产国产成人免费图片| 美女精品在线观看| 久久性天堂网| 久久夜色精品国产亚洲aⅴ| 欧美一区精品| 欧美专区在线观看| 久久久久久久综合| 蜜臀av一级做a爰片久久| 久久精品女人的天堂av| 欧美在线视频观看免费网站| 欧美在线一二三区| 欧美在线免费| 久热精品在线视频| 国产精品露脸自拍| 欧美高潮视频| 亚洲美女电影在线| 久久都是精品| 午夜精品久久久| 欧美日韩情趣电影| 亚洲黄色天堂| 亚洲麻豆视频| 欧美凹凸一区二区三区视频| 牛牛国产精品| 亚洲成人在线视频网站| 欧美日韩一区二区三区免费看| 亚洲女人小视频在线观看| 亚洲一区视频| 性色av一区二区三区在线观看 | 午夜精品福利视频| 性欧美videos另类喷潮| 久久精彩视频| 久久免费视频在线观看| 欧美大片一区二区| 国产精品毛片在线| 国产一区二区三区视频在线观看| 在线观看视频一区二区| 亚洲免费播放| 欧美一区二区三区男人的天堂| 久久资源av| 亚洲毛片av在线| 午夜免费在线观看精品视频| 久久综合狠狠| 欧美亚州韩日在线看免费版国语版| 国产精品一区二区久久精品| 在线成人av.com| 亚洲一二区在线| 久久免费高清视频| 亚洲精品一区在线| 欧美自拍丝袜亚洲| 欧美国产在线视频| 国产精品有限公司| 亚洲欧洲日本一区二区三区| 亚洲女性裸体视频| 欧美18av| 亚洲一级网站| 欧美激情一区二区三区在线视频观看 | 亚洲色诱最新| 亚洲激情小视频| 亚洲伊人第一页| 欧美精品二区| 亚洲国产欧洲综合997久久| 亚洲伊人色欲综合网| 欧美在线观看天堂一区二区三区| 亚洲电影av在线| 一区二区成人精品 | 久热成人在线视频|