MFC+GDI+绘制出雷达余晖效果
MFC+GDI+繪制出雷達余暉效果
1.首先要畫出靜態(tài)的坐標軸,用雙緩沖方法在onpain消息中繪制。繪制方法都比較簡單。聲明一個內(nèi)存DC,繪制一個圓形,再把坐標軸畫上去。
2.其次是繪制一個漸變的扇形區(qū)域,原點和角度要定好,而且要求是能夠旋轉(zhuǎn)的扇形。從簡單的旋轉(zhuǎn)開始就是模仿秒針旋轉(zhuǎn)。一開始我也是只繪制一根線旋轉(zhuǎn)。圖形旋轉(zhuǎn)時會留有上一次的圖形,所以我們還需要把上一次角度的圖形抹掉,重新定位新的角度的圖形。我選擇的辦法是開啟一個定時器,用之前畫好的內(nèi)存DC不斷地去覆蓋上一張圖,在覆蓋完成后再在上面繪制新角度的旋轉(zhuǎn)圖形即可。圖形旋轉(zhuǎn)我是用矩陣旋轉(zhuǎn)。
//該代碼寫在定時器即可static double fPi = 4.0*atan(1.0);//180度double fAngle = fPi/2,fDAngle = 2.0*fPi/60.0;//360度分成60份//轉(zhuǎn)盤看為時鐘盤,擺針為秒針SYSTEMTIME tmNow;GetLocalTime(&tmNow);//s為中心點,e為變化后的點,兩點連起來形成擺針//Pen sPen(Color(255, 0, 0), 3); CPen mypen(PS_SOLID,2,RGB(255,255,255));CPen* pOldPen;CDC* MyDC = this->GetDC();pOldPen=MyDC->SelectObject(&mypen);Point s(CenterPoint.X,CenterPoint.Y), e; double fTime = tmNow.wSecond + tmNow.wMilliseconds/1000.0 + 0;//以系統(tǒng)時間為當前比例//double fTime =30;double fAng = fPi/2.0 - fTime * (2.0*fPi) /30.0;//360度分的刻度影響擺針旋轉(zhuǎn)速度,分得越少越快e.X = (int)(CenterPoint.X + (WinRect.Height()/2.0) * cos(fAng)); e.Y = (int)(CenterPoint.Y - (WinRect.Height()/2.0) * sin(fAng));MyDC->BitBlt(0,0,WinRect.Height(),WinRect.Height(),&MemDC,0,0,SRCCOPY);//將內(nèi)存位圖貼上再劃線可將上一次圖形覆蓋//旋轉(zhuǎn)扇形static int angl = 10;//每次旋轉(zhuǎn)角度Graphics graphics(MyDC->m_hDC);graphics.SetSmoothingMode(SmoothingModeAntiAlias);//矩陣旋轉(zhuǎn)Matrix matrix;matrix.Translate(CenterPoint.X, CenterPoint.Y, MatrixOrderAppend);//matrix.Scale(2, 2, MatrixOrderAppend);matrix.RotateAt(angl, PointF(CenterPoint.X, CenterPoint.Y), MatrixOrderAppend);matrix.Translate(-CenterPoint.X, -CenterPoint.Y);graphics.SetTransform(&matrix); LinearGradientBrush linGrBrush(Point(0,0),Point(120,120),Color(0,255,255,255),Color(255,0,255,100));//漸變畫刷//graphics.DrawPie(&Pen(Color::Green,2),(int)0, (int)0,WinRect.Height(),WinRect.Height(),0,60);graphics.FillPie(&linGrBrush,(int)0, (int)0,WinRect.Height(),WinRect.Height(),0,60);//繪制漸變扇形//graphics.FillRectangle(&linGrBrush,(int)CenterPoint.X,(int)CenterPoint.Y, 50, WinRect.Height()/2);angl++;//以下均為旋轉(zhuǎn)秒針 // graphics.DrawLine(&Pen(Color::White,2),(int)CenterPoint.X,(int)CenterPoint.Y,(int)e.X,(int)e.Y); // MyDC->MoveTo(CenterPoint.X,CenterPoint.Y); // MyDC->LineTo(e.X,e.Y);MyDC->SelectObject(pOldPen);ReleaseDC(MyDC);pOldPen->DeleteObject();mypen.DeleteObject();3.下面是添加目標。新建一個透明的對話框疊加到當前雷達掃描的對話框,新對話框重繪透明的按鈕類,再貼圖到按鈕上,還要添加按鈕的點擊響應消息。然后在雷達掃描窗口上聲明新窗口的對象Create窗口。至于每一個按鈕都是對應一個封裝的結(jié)構(gòu)體,里面含有距離、高度和按鈕句柄等信息,不斷地調(diào)用movewindow即可實現(xiàn)移動。
//.h struct FlyBtInfo {double iDistance;double iHeight;CCDrawButtonTM flyBt;//句柄BOOL bShow;BOOL bSelected; }; CDlg_DrawFly *m_DrawFlyDlg; FlyBtInfo m_DrawFly[3];//.cpp if(m_DrawFlyDlg==NULL){m_DrawFlyDlg = new CDlg_DrawFly(this);m_DrawFlyDlg->Create(IDD_DLG_DRAWFLY,this);m_DrawFlyDlg->ShowWindow(SW_SHOW);}memcpy(&m_DrawFly[0].flyBt,&m_DrawFlyDlg->m_OneFlyBt,sizeof(CCDrawButton));m_DrawFly[0].bShow=FALSE;m_DrawFly[0].bSelected =FALSE;memcpy(&m_DrawFly[1].flyBt,&m_DrawFlyDlg->m_TwoFlyBt,sizeof(CCDrawButton));m_DrawFly[1].bShow=FALSE;m_DrawFly[1].bSelected =FALSE;memcpy(&m_DrawFly[2].flyBt,&m_DrawFlyDlg->m_ThreeFlyBt,sizeof(CCDrawButton));m_DrawFly[2].bShow=FALSE;m_DrawFly[2].bSelected =FALSE;//第一個定時器 //飛機1static int x1 =WinRect.Height()/2.0*(1-sin(3.14/4));if (x1<(WinRect.Height()/2)){m_DrawFly[0].flyBt.MoveWindow(x1-10,x1-10,25,25);//m_DrawFly[0].flyBt.Invalidate();m_DrawFly[0].flyBt.ShowWindow(SW_SHOW);//根據(jù)刻度算出距離,高度這里為十分之一距離double a =WinRect.Height()/2-x1+10;m_DrawFly[0].iDistance = sqrt(pow(a,2)*2)*m_iMetersPerPx;m_DrawFly[0].iHeight = m_DrawFly[0].iDistance/10;if (m_DrawFly[0].bSelected){UpdateFlyDataToList(0);}x1 ++;} else{x1 =WinRect.Height()/2.0*(1-sin(3.14/4));}//飛機2static int x2 = WinRect.Height()/2-5;static int y2 =WinRect.Height()/2-5;int x21 = WinRect.Height()/2*(1+sin(3.14/4));int y21 = WinRect.Height()/2*(1-sin(3.14/4));if (x2<x21 || y2>y21){m_DrawFly[1].flyBt.MoveWindow(x2,y2,25,25);//m_DrawFly[1].flyBt.Invalidate();m_DrawFly[1].flyBt.ShowWindow(SW_SHOW);double a1 = pow(WinRect.Height()/2.0-x2,2);double a2 = pow(WinRect.Height()/2.0-y2,2);m_DrawFly[1].iDistance = sqrt(a1+a2)*m_iMetersPerPx;m_DrawFly[1].iHeight = m_DrawFly[1].iDistance/10;if (m_DrawFly[1].bSelected){UpdateFlyDataToList(1);}x2 ++;y2 --;}else{x2 = WinRect.Height()/2-5;y2 =WinRect.Height()/2-5;}下面是用到的幾個方法:
//更新列表數(shù)據(jù) void CDlg_RadarScanning::UpdateFlyDataToList(int iTranceBatch) {int BatchTemp;int count = m_FlydataList.GetItemCount();for (int i =0;i<count;i++){BatchTemp = atoi(m_FlydataList.GetItemText(i,0));if (BatchTemp == iTranceBatch){CString strDistance;strDistance.Format("%.2f",m_DrawFly[iTranceBatch].iDistance);m_FlydataList.SetItemText(i,1,strDistance);strDistance.Format("%.2f",m_DrawFly[iTranceBatch].iHeight);m_FlydataList.SetItemText(i,2,strDistance);}} } //點擊按鈕時切換位圖 void CDlg_RadarScanning::ChangeFlyColor(int iTranceBatch) {switch(iTranceBatch){case 0:m_DrawFlyDlg->m_OneFlyBt.UpdateBtn("res\\airport.png","res\\airport.png","res\\airport.png","res\\airport.png","");m_DrawFlyDlg->m_OneFlyBt.Invalidate();m_DrawFlyDlg->m_TwoFlyBt.UpdateBtn("res\\airport4.png","res\\airport4.png","res\\airport4.png","res\\airport4.png","");m_DrawFlyDlg->m_TwoFlyBt.Invalidate();break;case 1:m_DrawFlyDlg->m_OneFlyBt.UpdateBtn("res\\airport2.png","res\\airport2.png","res\\airport2.png","res\\airport2.png","");m_DrawFlyDlg->m_OneFlyBt.Invalidate();m_DrawFlyDlg->m_TwoFlyBt.UpdateBtn("res\\airport5.png","res\\airport5.png","res\\airport5.png","res\\airport5.png","");m_DrawFlyDlg->m_TwoFlyBt.Invalidate();break;} }//按鈕點擊消息,通過發(fā)送消息給主窗口類 void CDlg_DrawFly::OnBnClickedOnedrawbutton() {m_Parent->SendMessage(WM_DRAWFLY_BT_MSG,IDC_ONEDRAWBUTTON,0);// TODO: 在此添加控件通知處理程序代碼 } void CDlg_DrawFly::OnBnClickedTwodrawbutton() {// TODO: 在此添加控件通知處理程序代碼m_Parent->SendMessage(WM_DRAWFLY_BT_MSG,IDC_TWODRAWBUTTON,0); } void CDlg_DrawFly::OnBnClickedThreedrawbutton() {// TODO: 在此添加控件通知處理程序代碼m_Parent->SendMessage(WM_DRAWFLY_BT_MSG,IDC_THREEDRAWBUTTON,0); }//這個方法用于響應按鈕點擊事件 LRESULT (主窗口類)::OnDrawFlyBTDepose(WPARAM wParam, LPARAM lParam) {switch(wParam){case IDC_ONEDRAWBUTTON:{m_RadarScanningDlg->ChangeFlyColor(0);m_RadarScanningDlg->m_CurSelectAim =0;m_RadarScanningDlg->m_DrawFly[0].bSelected =TRUE;CString strTemp;strTemp.Format("00 跟蹤");m_RadarScanningDlg->m_FlydataList.SetItemText(0,0,strTemp);m_RadarScanningDlg->m_FlydataList.SetItemText(1,0,"01");}//SelectRadarTrackBatch(0);break;case IDC_TWODRAWBUTTON:{m_RadarScanningDlg->ChangeFlyColor(1);m_RadarScanningDlg->m_CurSelectAim =1;m_RadarScanningDlg->m_DrawFly[1].bSelected =TRUE;CString strTemp;strTemp.Format("01 跟蹤");m_RadarScanningDlg->m_FlydataList.SetItemText(1,0,strTemp);m_RadarScanningDlg->m_FlydataList.SetItemText(0,0,"00");}//SelectRadarTrackBatch(1);break; }return 1; }總結(jié):
使用MFC確實不好做,我查了一下很多都是QT。關鍵是GDI+繪圖和矩陣旋轉(zhuǎn)比較難。雖然這個是我自己寫的,但是工程是公司的,我不好公開全部代碼,有什么問題可以問我。
以下是提供可學習
1.GDI+學習及代碼總結(jié)之------畫線、區(qū)域填充、寫字
https://blog.csdn.net/harvic880925/article/details/9023329
2.GDI+繪制極坐標圖、雷達圖
https://blog.csdn.net/iteye_15968/article/details/82334555
3.GDI+旋轉(zhuǎn)圖片的幾種方法
https://blog.csdn.net/fyl_077/article/details/44456213
總結(jié)
以上是生活随笔為你收集整理的MFC+GDI+绘制出雷达余晖效果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 开源绘画板项目 (Sca
- 下一篇: 分治3--黑白棋子的移动