@版權(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á)到如下效果:
- down-move-up模式:鼠標(biāo)左鍵按下 開(kāi)始繪制矩形框, 左鍵保持按下?tīng)顟B(tài)隨著鼠標(biāo)移動(dòng)不斷更新矩形框 瘫证,鼠標(biāo)左鍵彈起矩形框繪制結(jié)束揉阎。
- 單擊 - move - 單擊 模式:鼠標(biāo)左鍵單擊(連續(xù)的down -up)開(kāi)始繪制矩形框-隨著鼠標(biāo)移動(dòng)矩形框不斷更新-鼠標(biāo)左鍵再次單擊結(jié)束繪制
- 雙擊 - move - 雙擊 模式:同上單擊模式,只是單擊改雙擊背捌。
但在MFC中區(qū)分鼠標(biāo)單擊毙籽、雙擊、左鍵按下毡庆、左鍵抬起是比較困難的一件事坑赡。因?yàn)闊o(wú)論單擊還是雙擊始終會(huì)先觸發(fā)down 。
解決方法
不處理雙擊還是單擊,僅僅在buttonDown 和buttonUp中進(jìn)行判斷
因此將以上過(guò)程簡(jiǎn)化為:
- 僅僅在鼠標(biāo)左鍵按下LeftButton中決定是否開(kāi)始繪制矩形框或結(jié)束矩形框的繪制
- 在鼠標(biāo)左鍵抬起時(shí)么抗,判斷是否結(jié)束繪制毅否。
- 鼠標(biāo)移動(dòng)過(guò)程中 ,如果開(kāi)始繪制就不斷的更新矩形框乖坠。
通過(guò)以上處理搀突。我們將決定是否開(kāi)始繪制矩形框的條件完全放在LeftButtonDown中,這樣只用判斷鼠標(biāo)是否為down 還是up來(lái)終止和結(jié)束繪制。
需要定義的變量
- Handle(AIS_RubberBand) mySelectionRectangle;//選擇框?qū)ο?/li>
- 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)記錄甸昏。- DWORD myStartSelectionTime;//用于記錄開(kāi)始選擇框的時(shí)間。
- Standard_Integer myFirstCursorX;//用于記錄矩形框起點(diǎn)坐標(biāo)X
- .Standard_Integer myFirstCursorY;//用于記錄矩形框起點(diǎn)坐標(biāo)Y
- Standard_Integer mySecondCursorX;//用于記錄矩形框終點(diǎn)坐標(biāo)X
- 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é)束繪制判斷條件
- 如果已經(jīng)開(kāi)始可繪制 就要比對(duì)當(dāng)前鼠標(biāo)位置是否與開(kāi)始繪制的位置是否重合 這里要求不重合
- 當(dāng)前時(shí)間與開(kāi)始時(shí)間之差是否大于一個(gè)余量(這里給200,防止過(guò)快的操作) 這里要求大于余量
- 若果以上兩個(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;
}