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

制作彈出式菜單按鈕

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


一、新建一個以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 閱讀(964) 評論(0)  編輯 收藏 引用


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


導航

<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

統計

常用鏈接

留言簿(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>
            亚洲手机在线| 欧美jizzhd精品欧美巨大免费| 亚洲美女在线国产| 亚洲成色www8888| 国产一区二区三区自拍| 久久亚洲综合色一区二区三区| 亚洲视频一区在线观看| 日韩视频在线一区二区| 99精品热6080yy久久| 久久精品国产综合| 亚洲一区二区三区三| 欧美成人精品在线视频| 久久久亚洲影院你懂的| 国产精品黄色| 久久不见久久见免费视频1| 久久中文精品| 国产视频一区免费看| 亚洲另类在线视频| 亚洲黄色天堂| 欧美不卡在线视频| 日韩亚洲欧美精品| 亚洲视频在线播放| 国产精品日韩精品| 国产精一区二区三区| 1769国产精品| 亚洲在线成人| 最新亚洲视频| 性欧美1819sex性高清| 欧美激情欧美狂野欧美精品| 国产视频不卡| 亚洲视频网在线直播| 六十路精品视频| 亚洲专区一区| 欧美吻胸吃奶大尺度电影| 一区二区在线不卡| 久久久亚洲高清| 欧美一区二区视频在线观看| 亚洲一区二区欧美| 亚洲国产精品一区| 欧美在线看片| 国产欧美在线| 久久久噜噜噜| 久久综合国产精品| 亚洲人久久久| 日韩一区二区精品葵司在线| 蜜桃av一区二区在线观看| 亚洲第一精品在线| 欧美成人精品一区二区| 欧美.日韩.国产.一区.二区| 亚洲国产精品一区制服丝袜| 久久精品人人爽| 久久久久9999亚洲精品| 亚洲区在线播放| 一个色综合导航| 国产欧美精品久久| 欧美激情国产日韩| 国产精品成人一区二区| 久久亚洲图片| 国产精品高潮呻吟久久| 男女av一区三区二区色多| 欧美日本在线一区| 久久综合中文字幕| 欧美视频在线观看免费网址| 久久国产精品色婷婷| 你懂的一区二区| 欧美成人免费一级人片100| 欧美日韩综合一区| 噜噜噜在线观看免费视频日韩| 欧美日韩精品免费观看视一区二区 | 亚洲日本在线视频观看| 亚洲毛片在线观看.| 国产性做久久久久久| 夜夜嗨av一区二区三区四季av | 国产精品99久久久久久久女警| 午夜精品99久久免费| 在线一区免费观看| 欧美日韩xxxxx| 亚洲激情校园春色| 亚洲人体偷拍| 欧美日韩国语| 99在线|亚洲一区二区| 亚洲免费成人av电影| 模特精品在线| 亚洲另类在线视频| 亚洲综合首页| 国产一区二区精品久久99| 欧美在线播放| 欧美国产在线电影| 一区二区三区蜜桃网| 欧美午夜视频在线观看| 这里只有精品在线播放| 欧美专区在线| 日韩视频在线播放| 国产精品视频网| 狂野欧美一区| 亚洲欧美日韩国产综合在线| 久久国产精品99精品国产| 在线成人h网| 欧美日韩国产精品| 久久xxxx| 欧美亚洲日本网站| 亚洲精品精选| 国产精品日韩在线| 久久裸体视频| 性色av一区二区三区在线观看| 欧美激情bt| 欧美91视频| 久久久国产一区二区| 亚洲综合精品四区| 亚洲美女av网站| 亚洲人精品午夜| 亚洲国产欧美久久| 国产一区视频观看| 国产丝袜一区二区| 国产精品一区二区黑丝| 欧美日韩中文字幕日韩欧美| 久久一区二区精品| 女同一区二区| 噜噜噜91成人网| 欧美r片在线| 国产精品激情电影| 欧美性感一类影片在线播放| 欧美另类人妖| 国产精品一区二区在线| 国产欧美精品国产国产专区| 欧美少妇一区| 一区二区视频免费在线观看| 激情一区二区三区| 一区二区三区蜜桃网| 亚洲午夜精品国产| 性欧美videos另类喷潮| 久久女同精品一区二区| 欧美激情久久久久久| 中文av一区二区| 久久视频在线看| 欧美精品一区二区视频| 国产精品v亚洲精品v日韩精品| 国产一区二区高清| 夜夜嗨av一区二区三区网站四季av | 西西人体一区二区| 男女精品视频| 一区二区三区日韩| 久久精品亚洲精品| 国产精品美女在线| 亚洲天堂av在线免费观看| 蜜桃av一区二区| 久久精品一区二区三区不卡牛牛| 欧美精品999| 在线看国产一区| 欧美在线看片| 亚洲欧美变态国产另类| 欧美午夜在线一二页| 一区二区不卡在线视频 午夜欧美不卡'| 亚洲综合精品一区二区| 宅男噜噜噜66一区二区| 欧美激情视频在线免费观看 欧美视频免费一 | 国产午夜精品一区二区三区欧美 | 国产精品久久97| 一区二区av在线| 日韩视频免费| 欧美丝袜一区二区| 欧美亚洲专区| 久久精品国产免费看久久精品| 国产欧美一区二区三区在线老狼 | 野花国产精品入口| 黄色一区二区三区| 欧美一区激情| 国产在线拍偷自揄拍精品| 亚洲国产精品久久精品怡红院| 久久综合九色综合欧美狠狠| 亚洲日本电影在线| 久久亚洲不卡| 亚洲第一视频网站| 亚洲黄色大片| 欧美日韩国产一区二区| 最近中文字幕mv在线一区二区三区四区| 国产亚洲在线| 久久午夜av| 99热精品在线| 香蕉久久一区二区不卡无毒影院| 欧美视频一二三区| 性xx色xx综合久久久xx| 老妇喷水一区二区三区| 亚洲欧洲日本一区二区三区| 欧美激情综合| 亚洲欧美激情诱惑| 欧美成人首页| 亚洲尤物精选| 亚洲国产精彩中文乱码av在线播放| 欧美黑人国产人伦爽爽爽| 亚洲精品中文字幕在线| 亚洲在线1234| 亚洲精品视频在线| 国产视频一区三区| 欧美日韩亚洲一区二区三区在线观看| 在线亚洲国产精品网站| 亚洲高清毛片| 免费高清在线视频一区·| 亚洲欧美影音先锋| 亚洲精品裸体|