Open Cascade MFC應(yīng)用程序中使用AIS_RubberBand繪制矩形選擇框的問(wèn)題及處理方法


@版權(quán)聲明:本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載顿涣,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出,
本文鏈接http://www.reibang.com/p/1d566a1445bc
如有問(wèn)題酝豪, 可郵件(yumxuanyi@qq.com)咨詢涛碑。


關(guān)鍵字:OpenCascade、MFC孵淘、AIS_RubberBand

問(wèn)題描述

在使用MFC創(chuàng)建的Opeen Cascade項(xiàng)目中,可以使用AIS_RubberBand來(lái)創(chuàng)建選擇框蒲障。
現(xiàn)在需要達(dá)到如下效果:

  1. down-move-up模式:鼠標(biāo)左鍵按下 開(kāi)始繪制矩形框, 左鍵保持按下?tīng)顟B(tài)隨著鼠標(biāo)移動(dòng)不斷更新矩形框 瘫证,鼠標(biāo)左鍵彈起矩形框繪制結(jié)束揉阎。
  2. 單擊 - move - 單擊 模式:鼠標(biāo)左鍵單擊(連續(xù)的down -up)開(kāi)始繪制矩形框-隨著鼠標(biāo)移動(dòng)矩形框不斷更新-鼠標(biāo)左鍵再次單擊結(jié)束繪制
  3. 雙擊 - move - 雙擊 模式:同上單擊模式,只是單擊改雙擊背捌。

但在MFC中區(qū)分鼠標(biāo)單擊毙籽、雙擊、左鍵按下毡庆、左鍵抬起是比較困難的一件事坑赡。因?yàn)闊o(wú)論單擊還是雙擊始終會(huì)先觸發(fā)down 。

解決方法

不處理雙擊還是單擊,僅僅在buttonDown 和buttonUp中進(jìn)行判斷
因此將以上過(guò)程簡(jiǎn)化為:

  1. 僅僅在鼠標(biāo)左鍵按下LeftButton中決定是否開(kāi)始繪制矩形框或結(jié)束矩形框的繪制
  2. 在鼠標(biāo)左鍵抬起時(shí)么抗,判斷是否結(jié)束繪制毅否。
  3. 鼠標(biāo)移動(dòng)過(guò)程中 ,如果開(kāi)始繪制就不斷的更新矩形框乖坠。

通過(guò)以上處理搀突。我們將決定是否開(kāi)始繪制矩形框的條件完全放在LeftButtonDown中,這樣只用判斷鼠標(biāo)是否為down 還是up來(lái)終止和結(jié)束繪制。

需要定義的變量

  1. Handle(AIS_RubberBand) mySelectionRectangle;//選擇框?qū)ο?/li>
  2. Mouse_SelectionState mySelectionState;//用于記錄當(dāng)前的繪制狀態(tài) 是開(kāi)始還是結(jié)束仰迁。
    enum Mouse_SelectionState
    {
    Mouse_StartSelection,//表示當(dāng)前狀態(tài)為已經(jīng)開(kāi)始了矩形框的繪制
    Mouse_EndSelection,//表示當(dāng)前矩形框繪制結(jié)束
    Mouse_SelectionNormal//正常狀態(tài)
    };
    當(dāng)然你也可以直接用Standard_Boolean來(lái)記錄甸昏。
  3. DWORD myStartSelectionTime;//用于記錄開(kāi)始選擇框的時(shí)間。
  4. Standard_Integer myFirstCursorX;//用于記錄矩形框起點(diǎn)坐標(biāo)X
  5. .Standard_Integer myFirstCursorY;//用于記錄矩形框起點(diǎn)坐標(biāo)Y
  6. Standard_Integer mySecondCursorX;//用于記錄矩形框終點(diǎn)坐標(biāo)X
  7. Standard_Integer mySecondCursorY;//用于記錄矩形框終點(diǎn)坐標(biāo)Y

在View類構(gòu)造函數(shù)中進(jìn)行初始化

      CMyView::CMyView()
     {
       // TODO: 在此處添加構(gòu)造代碼
      this->mySelectionRectangle = new AIS_RubberBand();//初始化選擇框
       mySelectionState = Mouse_SelectionNormal; //設(shè)置初始選擇狀態(tài)
     }

在View類的析構(gòu)函數(shù)中刪除

   CMyView::~CMyView()
   {
      this->mySelectionRectangle.Nullify();
   }

具體實(shí)現(xiàn)

OnLButtonDown事件處理方法

在OnLButtonDown中進(jìn)行開(kāi)始繪制或結(jié)束繪制的判斷,如果沒(méi)有開(kāi)始繪制 就要開(kāi)始繪制,如果已經(jīng)開(kāi)始了繪制 就要結(jié)束繪制(檢查不重合后)

void CMyView::OnLButtonDown(UINT nFlags,CPoint point)
{
 // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值
    if (mySelectionState == Mouse_StartSelection)//表示已經(jīng)開(kāi)始了矩形框的繪制
    {
        //如果矩形框的繪制已經(jīng)開(kāi)始徐许,需要檢查如果當(dāng)前鼠標(biāo)點(diǎn)擊點(diǎn)point ,       
        //如果不與開(kāi)始繪制點(diǎn)重合(不落在開(kāi)始繪制點(diǎn)的范圍內(nèi)時(shí))就要結(jié)束矩形框的繪制       
        //如果重合(落在開(kāi)始點(diǎn)的tol范圍內(nèi))將保持繪制狀態(tài)
        Standard_Boolean inRect = JudgeMouseInRect(CPoint(myFirstCursorX, myFirstCursorY), point);//用于判斷當(dāng)前點(diǎn)point是否落在開(kāi)始繪制點(diǎn)的范圍內(nèi)
        if (inRect == Standard_False)//不重合結(jié)束繪制
        {
            mySecondCursorX = point.x;//記錄結(jié)束的x坐標(biāo)
            mySecondCursorY = point.y;//記錄結(jié)束的y坐標(biāo)
            mySelectionState = Mouse_EndSelection;//將狀態(tài)標(biāo)記為結(jié)束
            DrawSelectionRectangle(Standard_False);//結(jié)束矩形框繪制 參數(shù)False表示不繪制矩形框
        }
    }
    else//表示沒(méi)有開(kāi)始繪制 這時(shí)就要開(kāi)始繪制矩形框了
    {
        myFirstCursorX = point.x;//記錄開(kāi)始繪制的位置
        myFirstCursorY = point.y;
        mySecondCursorX = point.x;//同時(shí)也重置一下這個(gè)位置
        mySecondCursorY = point.y;
        mySelectionState = Mouse_StartSelection;//記錄狀態(tài)為開(kāi)始繪制
        DrawSelectionRectangle(Standard_True);//開(kāi)始繪圖啦
        myStartSelectionTime = ::GetTickCount();//這里記錄開(kāi)始繪制的時(shí)間
    }
   CView::OnLButtonDown(nFlags,point)施蜜;
}  

OnLButtonUp事件處理方法

在LButtonUp事件中判斷是否結(jié)束繪制判斷條件

  1. 如果已經(jīng)開(kāi)始可繪制 就要比對(duì)當(dāng)前鼠標(biāo)位置是否與開(kāi)始繪制的位置是否重合 這里要求不重合
  2. 當(dāng)前時(shí)間與開(kāi)始時(shí)間之差是否大于一個(gè)余量(這里給200,防止過(guò)快的操作) 這里要求大于余量
  3. 若果以上兩個(gè)條件都滿足 就結(jié)束繪制
void CMyView::OnLButtonUp(UINT nFlags,CPoint point)
{
    if (mySelectionState == Mouse_StartSelection)//開(kāi)始了繪制 就要判斷是否去結(jié)束繪制
    {
        CPoint center(myFirstCursorX, myFirstCursorY);
        Standard_Boolean inRect = JudgeMouseInRect(center, point);//判斷是否重合
        if (inRect == Standard_False)//不重合 進(jìn)行條件2的判斷
        {
            DWORD currentTime = ::GetTickCount();
            if (currentTime - myStartSelectionTime > 200)//起始時(shí)間差大于200 結(jié)束繪制
            {
                mySecondCursorX = point.x;//記錄結(jié)束時(shí)的坐標(biāo)
                mySecondCursorY = point.y;
                mySelectionState = Mouse_EndSelection;//標(biāo)記為結(jié)束
                DrawSelectionRectangle(Standard_False);//結(jié)束矩形框繪制
            }
        }
    }
     CView::OnLButtonUp(nFlags,point);
}

OnMouseMove事件處理方法

鼠標(biāo)移動(dòng)時(shí)開(kāi)始更新矩形框,如果已經(jīng)開(kāi)始了繪制 就要在鼠標(biāo)移動(dòng)時(shí)不斷更新矩形框的大小

void CMyView::OnMouseMove(UINT nFlags,CPoint point)
{
       if (mySelectionState == Mouse_StartSelection)
    {
        mySecondCursorX = point.x;
        mySecondCursorY = point.y;
        DrawSelectionRectangle(Standard_True);
    }
    CView::OnMouseMove(nFlags,point);
}

JudgeMouseInRect方法

判斷當(dāng)前坐標(biāo)是否與center坐標(biāo)重合
判斷方法 mousePoint不落在以center為半徑 r=4的范圍內(nèi) 為不重合 否則重合

Standard_Boolean CMyView::JudgeMouseInRect(CPoint center, CPoint mousePoint)
{
    Standard_Real xdis = abs(center.x - mousePoint.x);
    Standard_Real ydis = abs(center.y - mousePoint.y);
    double distance = sqrt(pow(xdis, 2) + pow(ydis, 2));//求距離
    if (distance - 4 <= Precision::Confusion())//這里設(shè)置以半徑為4的范圍 這里給了半徑為4個(gè)像素
    {
        return Standard_True;
    }
    return Standard_False;
}

DrawSelectionRectangle方法

繪制矩形選擇框 isDisplay 表示十分顯示 或 不顯示矩形框

Standard_Boolean CEquipmentCADView::DrawSelectionRectangle(Standard_Boolean isDisplay)
{
    Handle(AIS_InteractiveContext) hContext = GetDocument()->GetAISContext();
    if (!isDisplay)
    {
        hContext->Remove(this->mySelectionRectangle, Standard_False);
        hContext->CurrentViewer()->RedrawImmediate();
        return Standard_False;
    }
    //獲取視口尺寸
    Standard_Integer winViewWidth;//視口窗體寬度
    Standard_Integer winViewHeight;//視口窗體高度
    this->myView->Window()->Size(winViewWidth, winViewHeight);//獲取窗體尺寸
     //注意:這里用view的Window的size方法 而不是GetWindowRect()方法 因?yàn)镚etWindowRect()方法左右上下會(huì)少像素

    this->mySelectionRectangle->SetRectangle(myFirstCursorX, winViewHeight - myFirstCursorY, mySecondCursorX, winViewHeight - mySecondCursorY);//設(shè)置矩形框的范圍

    this->mySelectionRectangle->SetFillTransparency(0.8);//設(shè)置矩形填充的透明度為0.8

    //下面判斷是全選還是部分選取的矩形框
    //當(dāng)從左到右選取時(shí)為全選 只有物體的包圍框完全落在矩形選擇框之內(nèi)才選擇
    //當(dāng)從右到左時(shí)為部分選雌隅。一旦物體的包圍框與矩形選擇框有相交就選擇
    if (myFirstCursorX <= mySecondCursorX)
    {
        this->mySelectionRectangle->SetLineType(Aspect_TOL_SOLID);//設(shè)置邊框線型為實(shí)線
        this->mySelectionRectangle->SetFillColor(Quantity_NOC_BLUE2);//設(shè)置填充顏色為藍(lán)色
    }
    else
    {
        this->mySelectionRectangle->SetLineType(Aspect_TOL_DOT);//設(shè)置邊框線型為虛點(diǎn)
        this->mySelectionRectangle->SetFillColor(Quantity_NOC_GREEN2);//設(shè)置填充顏色為綠色
    }
    this->mySelectionRectangle->SetFilling(Standard_True);//開(kāi)啟矩形填充模式

    //下面判斷 如果已經(jīng)顯示了就更新圖形
    //沒(méi)有顯示就顯示圖像
    if (!hContext->IsDisplayed(this->mySelectionRectangle))
    {
        hContext->Display(this->mySelectionRectangle, Standard_False);//顯示對(duì)象
    }
    else
    {
        hContext->Redisplay(this->mySelectionRectangle, Standard_False);//更新對(duì)象顯示
    }
    hContext->CurrentViewer()->RedrawImmediate();

    return Standard_True;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翻默,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子恰起,更是在濱河造成了極大的恐慌修械,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件检盼,死亡現(xiàn)場(chǎng)離奇詭異肯污,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吨枉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)蹦渣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人貌亭,你說(shuō)我怎么就攤上這事柬唯。” “怎么了圃庭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵锄奢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我剧腻,道長(zhǎng)斟薇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任恕酸,我火速辦了婚禮堪滨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蕊温。我一直安慰自己袱箱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布义矛。 她就那樣靜靜地躺著发笔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凉翻。 梳的紋絲不亂的頭發(fā)上了讨,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼前计。 笑死胞谭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的男杈。 我是一名探鬼主播丈屹,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼伶棒!你這毒婦竟也來(lái)了旺垒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肤无,失蹤者是張志新(化名)和其女友劉穎先蒋,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宛渐,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞭达,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皇忿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坦仍,死狀恐怖鳍烁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情繁扎,我是刑警寧澤幔荒,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站梳玫,受9級(jí)特大地震影響爹梁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜提澎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一姚垃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盼忌,春花似錦积糯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至跨嘉,卻和暖如春川慌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工梦重, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兑燥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓忍饰,卻偏偏與公主長(zhǎng)得像贪嫂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艾蓝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • DAY1 今日關(guān)鍵詞:早起力崇!5:18分 早上好,今天開(kāi)始第一天的MOS考前學(xué)習(xí)赢织,制作Exce工作薄亮靴,以分析產(chǎn)品銷售...
    晨E戰(zhàn)到底閱讀 272評(píng)論 0 1
  • 親愛(ài)的全球易效能教練,大家早上好于置!又到了我們每周二的教練晨會(huì)時(shí)間茧吊,那在這里溫馨提示各位教練請(qǐng)您按編號(hào)加姓名的方式修...
    程彥瑞閱讀 425評(píng)論 0 0
  • 計(jì)算機(jī)由硬件和軟件構(gòu)成 計(jì)算機(jī)硬件的五大部件:運(yùn)算器、控制器八毯、存儲(chǔ)器搓侄、輸入設(shè)備、輸出設(shè)備 計(jì)算機(jī)軟件:系統(tǒng)軟件(操...
    Givemeasmi_75e7閱讀 323評(píng)論 0 0
  • 雖然現(xiàn)在已經(jīng)是凌晨2點(diǎn)了话速,為了履行我的承諾讶踪,必須寫(xiě)下我今天的成功日記,準(zhǔn)確說(shuō)是昨天的成功日記泊交。今天是我堅(jiān)持寫(xiě)...
    木子姐陪伴成長(zhǎng)閱讀 236評(píng)論 0 2
  • 金馬老師布置作業(yè)后的第一時(shí)間就在大貓城堡下單了紙質(zhì)版《劉大貓的財(cái)富之旅》乳讥,雖然金馬老師也同時(shí)發(fā)了免費(fèi)電子版,當(dāng)時(shí)想...
    爬樹(shù)的蝸牛tangbao閱讀 246評(píng)論 0 2