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

制作彈出式菜單按鈕

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


一、新建一個以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   管理


導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿(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>
            亚洲欧洲av一区二区三区久久| 黑人一区二区| 国产精品v日韩精品| 国产午夜精品全部视频播放 | 亚洲永久免费视频| 久久久青草青青国产亚洲免观| 亚洲经典视频在线观看| 玖玖视频精品| 国产精品视频一区二区高潮| 亚洲中无吗在线| 亚洲高清资源| 久久婷婷国产麻豆91天堂| 国产精品视频不卡| 午夜精品久久久久久久| 亚洲精品国久久99热| 欧美黄免费看| 妖精成人www高清在线观看| 91久久精品美女| 欧美日韩美女一区二区| 亚洲午夜未删减在线观看| 9l视频自拍蝌蚪9l视频成人| 欧美午夜精品久久久久免费视| 亚洲欧美日韩爽爽影院| 午夜精品婷婷| 在线精品观看| 亚洲国产天堂久久国产91| 欧美国产日韩二区| 在线综合亚洲欧美在线视频| 亚洲性图久久| 红杏aⅴ成人免费视频| 欧美国产精品| 欧美日韩一级黄| 欧美在线免费观看| 久久婷婷丁香| 一区二区三区|亚洲午夜| 亚洲专区免费| 亚洲电影在线| 亚洲精品视频一区二区三区| 国产精品一区二区在线观看不卡 | 欧美资源在线| 久久网站免费| 亚洲综合视频在线| 久久精品国产v日韩v亚洲| 亚洲精品乱码久久久久久久久 | 国产欧美视频一区二区三区| 麻豆精品一区二区综合av | 欧美一区二区精品在线| 久久美女性网| 中文av字幕一区| 久久久噜噜噜久久| 亚洲欧美文学| 免费久久99精品国产| 亚洲欧美日韩网| 欧美视频在线免费看| 久久九九精品| 国内精品久久久久国产盗摄免费观看完整版| 亚洲人妖在线| 亚洲主播在线播放| 国产在线乱码一区二区三区| 亚洲日本欧美| 亚洲欧美日韩在线一区| 亚洲国产精品成人一区二区| 在线观看三级视频欧美| 亚洲免费观看高清完整版在线观看熊| 国产精品久久久久久久久借妻 | 久久精品一二三| 欧美区二区三区| 蜜桃av一区二区三区| 国产精品蜜臀在线观看| 亚洲精品乱码久久久久久蜜桃91| 韩国精品在线观看| 中文av字幕一区| 日韩性生活视频| 久久久久99| 久久精品国产亚洲一区二区三区| 欧美性久久久| 一区二区欧美国产| 日韩一级二级三级| 久久精品动漫| 久久久久久久国产| 国产精自产拍久久久久久蜜| 一区二区免费在线视频| 99国产精品| 欧美激情在线免费观看| 亚洲福利国产| 亚洲高清视频中文字幕| 久久久999精品| 免费成人高清视频| 在线观看欧美黄色| 另类av导航| 亚洲成人在线视频网站| 亚洲国产精品欧美一二99| 久久综合久久久| 欧美电影打屁股sp| 亚洲精品婷婷| 欧美连裤袜在线视频| 亚洲日本电影| 亚洲女人小视频在线观看| 国产精品福利久久久| 亚洲一区二三| 久久久久一区二区三区| 在线日韩电影| 欧美精品在欧美一区二区少妇| 日韩天天综合| 久久精品盗摄| 亚洲国产精品福利| 欧美极品在线观看| 亚洲婷婷综合久久一本伊一区| 亚洲欧美综合v| 国产一区二区三区日韩| 久久色在线观看| 日韩视频一区二区三区在线播放| 午夜在线观看欧美| 美女精品在线观看| 久久久夜色精品亚洲| 欧美高清在线精品一区| 亚洲黄色一区二区三区| 欧美成人综合| 亚洲婷婷在线| 免费看黄裸体一级大秀欧美| 日韩天堂在线视频| 国产精品美女久久久久久2018| 午夜精品一区二区三区电影天堂| 久久男女视频| 日韩视频二区| 国产色婷婷国产综合在线理论片a| 久久免费视频这里只有精品| 亚洲看片一区| 久久视频在线视频| 一区二区免费在线视频| 国产一区二区三区高清在线观看| 女同性一区二区三区人了人一 | 亚洲视频axxx| 欧美电影免费| 久久国产88| 亚洲特黄一级片| 狠狠综合久久av一区二区老牛| 欧美国产精品劲爆| 欧美尤物一区| 99精品视频免费观看| 久热精品视频在线| 亚洲欧美另类在线观看| 亚洲区一区二| 狠狠网亚洲精品| 国产女人水真多18毛片18精品视频| 免费中文日韩| 久久精品主播| 亚洲在线免费| 一区二区激情小说| 亚洲狠狠丁香婷婷综合久久久| 久久精品成人| 欧美一级理论片| 亚洲伊人色欲综合网| 日韩视频在线免费观看| 在线激情影院一区| 红桃av永久久久| 国产亚洲欧美一区二区| 国产精品免费福利| 欧美午夜在线一二页| 欧美精品福利在线| 欧美ab在线视频| 美女黄网久久| 久久综合色播五月| 久久久久国产成人精品亚洲午夜| 亚洲欧美精品在线| 在线一区二区视频| 日韩亚洲精品电影| 日韩视频不卡中文| 艳女tv在线观看国产一区| 亚洲日本视频| 亚洲免费不卡| 一道本一区二区| 一区二区av| 亚洲一区二区在| 欧美亚洲一区二区三区| 亚洲欧美一区二区三区极速播放| 亚洲午夜国产一区99re久久 | 日韩亚洲精品在线| 99av国产精品欲麻豆| 亚洲理论电影网| 日韩一本二本av| 一区二区三区高清不卡| 在线亚洲国产精品网站| 亚洲午夜精品久久久久久浪潮| 午夜精彩国产免费不卡不顿大片| 国产午夜精品久久久久久免费视| 国产精品美女久久久久久久| 国产精品卡一卡二| 国产精品永久免费在线| 国产日韩精品视频一区二区三区| 国产精品夜夜夜| 国产亚洲欧美另类一区二区三区| 好看不卡的中文字幕| 亚洲激情视频网| 宅男噜噜噜66一区二区66| 亚洲欧美日韩国产中文在线| 久久se精品一区二区| 免费日韩av片| 夜夜嗨av一区二区三区网站四季av | 亚洲已满18点击进入久久|