日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC+GDI+绘制出雷达余晖效果

發布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC+GDI+绘制出雷达余晖效果 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MFC+GDI+繪制出雷達余暉效果


1.首先要畫出靜態的坐標軸,用雙緩沖方法在onpain消息中繪制。繪制方法都比較簡單。聲明一個內存DC,繪制一個圓形,再把坐標軸畫上去。

void CDlg_RadarScanning::OnPaint() {CPaintDC dc(this); // device context for painting// TODO: 在此處添加消息處理程序代碼// 不為繪圖消息調用 CDialogEx::OnPaint()GetClientRect(&WinRect);CenterPoint.X = WinRect.Height()/2.0;CenterPoint.Y = CenterPoint.X;ellipseRect2 = Rect(2,2,WinRect.Height()-4,WinRect.Height()-4); //外切矩形區域BitRect.Equals(ellipseRect2);pDC = this->GetDC();pDC->FillSolidRect(0,0,WinRect.right,WinRect.bottom,RGB(0,0,0));//隨后建立與屏幕顯示兼容的內存顯示設備MemDC.DeleteDC();MemDC.CreateCompatibleDC(pDC);MemBitmap.DeleteObject();MemBitmap.CreateCompatibleBitmap(pDC,WinRect.Width(),WinRect.Height());//將位圖選入到內存顯示設備中//只有選入了位圖的內存顯示設備才有地方繪圖,畫到指定的位圖上CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);Graphics gp(MemDC.m_hDC);gp.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);//抗鋸齒 REAL startAngle = 0.0f; // 設置起點角度REAL sweepAngle = 360.0f; // 設置旋轉角度Brush* brush = NULL;brush = new SolidBrush(Color::Green);gp.FillEllipse(brush,ellipseRect2.Height/2,ellipseRect2.Height/2,5,5);//圓心// PointF* StarPoint = new PointF(1,ellipseRect2.Height/2); // PointF* EndPoint= new PointF(ellipseRect2.Width,ellipseRect2.Height/2);PointF StarPoint(1,ellipseRect2.Height/2);PointF EndPoint(ellipseRect2.Width,ellipseRect2.Height/2+2);gp.DrawLine(&Pen(Color::Green,2),*(&StarPoint),*(&EndPoint));//水平坐標軸StarPoint.X = ellipseRect2.Width/2+2;EndPoint.X = StarPoint.X;StarPoint.Y = 1;EndPoint.Y = ellipseRect2.Height;gp.DrawLine(&Pen(Color::Green,2),*(&StarPoint),*(&EndPoint));//豎直坐標軸int Gap =ellipseRect2.Height/10+2;//刻度間隙int count = 5;for (int i=0;i<count;i++)//同心圓{gp.DrawArc(&Pen(Color::Green,2),ellipseRect2,startAngle,sweepAngle);//畫圓ellipseRect2.X = ellipseRect2.X +Gap;ellipseRect2.Y = ellipseRect2.Y +Gap;ellipseRect2.Width = ellipseRect2.Width - 2*Gap;ellipseRect2.Height = ellipseRect2.Height-2*Gap;}FontFamily fontFamily(L"微軟雅黑"); Gdiplus::Font myFont(&fontFamily, 10, FontStyleRegular, UnitPoint); //第二個是字體大小SolidBrush blackBrush(Color(255, 215, 0)); //半透明+文字RGB顏色int iOverrange = WinRect.Height()/10;CString strTemp;StringFormat format; format.SetAlignment(StringAlignmentNear); //文本排列方式,即在對應位置居中、靠左、靠右for (int i=5;i>=0;i--)//標明刻度{strTemp.Format("%d",i*2);WCHAR* wchar= strTemp.AllocSysString(); //wcscpy_s(string, CT2CW(str)); //如果使用MFC中的CString,需要這樣轉換成WCHARPointF school_site((REAL)(5-i)*iOverrange, (REAL)WinRect.Height()/2);//文字放置的像素坐標gp.DrawString(wchar, wcslen(wchar), &myFont, school_site, &format, &blackBrush );//把string繪制到圖上 }strTemp.Format("刻度/KM");WCHAR* wchar1= strTemp.AllocSysString();PointF school_site1((REAL)2, (REAL)2);//文字放置的像素坐標gp.DrawString(wchar1, wcslen(wchar1), &myFont, school_site1, &format, &blackBrush );////pDC->TransparentBlt(0,0,WinRect.Height()-1,WinRect.Height()-1,&MemDC,0,0,ellipseRect2.Width,ellipseRect2.Height,TRANSPARENT);pDC->BitBlt(0,0,WinRect.Height()-1,WinRect.Height()-1,&MemDC,0,0,SRCCOPY);m_iMetersPerPx = 10000.0/(WinRect.Height()/2.0);//10KM與圖像刻度比例MemDC.SelectObject(pOldBit);gp.ReleaseHDC(MemDC.m_hDC);}

2.其次是繪制一個漸變的扇形區域,原點和角度要定好,而且要求是能夠旋轉的扇形。從簡單的旋轉開始就是模仿秒針旋轉。一開始我也是只繪制一根線旋轉。圖形旋轉時會留有上一次的圖形,所以我們還需要把上一次角度的圖形抹掉,重新定位新的角度的圖形。我選擇的辦法是開啟一個定時器,用之前畫好的內存DC不斷地去覆蓋上一張圖,在覆蓋完成后再在上面繪制新角度的旋轉圖形即可。圖形旋轉我是用矩陣旋轉。

//該代碼寫在定時器即可static double fPi = 4.0*atan(1.0);//180度double fAngle = fPi/2,fDAngle = 2.0*fPi/60.0;//360度分成60份//轉盤看為時鐘盤,擺針為秒針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;//以系統時間為當前比例//double fTime =30;double fAng = fPi/2.0 - fTime * (2.0*fPi) /30.0;//360度分的刻度影響擺針旋轉速度,分得越少越快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);//將內存位圖貼上再劃線可將上一次圖形覆蓋//旋轉扇形static int angl = 10;//每次旋轉角度Graphics graphics(MyDC->m_hDC);graphics.SetSmoothingMode(SmoothingModeAntiAlias);//矩陣旋轉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++;//以下均為旋轉秒針 // 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窗口。至于每一個按鈕都是對應一個封裝的結構體,里面含有距離、高度和按鈕句柄等信息,不斷地調用movewindow即可實現移動。

//.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);//根據刻度算出距離,高度這里為十分之一距離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;}

下面是用到的幾個方法:

//更新列表數據 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;} }//按鈕點擊消息,通過發送消息給主窗口類 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; }

總結:
使用MFC確實不好做,我查了一下很多都是QT。關鍵是GDI+繪圖和矩陣旋轉比較難。雖然這個是我自己寫的,但是工程是公司的,我不好公開全部代碼,有什么問題可以問我。

以下是提供可學習

1.GDI+學習及代碼總結之------畫線、區域填充、寫字
https://blog.csdn.net/harvic880925/article/details/9023329
2.GDI+繪制極坐標圖、雷達圖
https://blog.csdn.net/iteye_15968/article/details/82334555
3.GDI+旋轉圖片的幾種方法
https://blog.csdn.net/fyl_077/article/details/44456213

總結

以上是生活随笔為你收集整理的MFC+GDI+绘制出雷达余晖效果的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。