MFC 绘制坐标及波形图函数

  最近因为课程需要,自己设计了一些相对简单的绘制坐标和波形图的函数,这些函数不够理想,但是对于简单要求足够了,以后自己会逐渐的完善这些函数。这里先把他们放这里,以免找不到。

  在MFC中,如果不是绘制动态波形图,一般都要在OnPaint或者OnDraw里面进行绘制,但是大家都知道,如果把一大串的绘图用的代码都放到OnPaint或者OnDraw会很纠结的。如果把绘图的代码整理起来,放到一个或者几个函数里面,这样会使得代码易懂且美观,另外最大的优点是绘图函数可以很好的复用,以后再用,只用改动极少的地方。这些绘图函数就是你的经验,就是你比别人快的地方。

  我先阐述我的思路:首先,如果是绘制静态图,为了能够在移动窗口时图片依旧存在,我看到最多的方法是用双缓存技术,这个技术我就不解释了,百度上面多得是。绘制图形的代码会比较多,如果为了复用,只能把绘图分解,这在面向对象中经常用到,我要记住,大家也要记住。因为人与人的理解会不同,所以把动作分解的方式也肯定会不一样,我认为,只要目的达到了而且又没有特别明显的差距,什么样的方法都是OK的,不能因为他是大神,他是权威,他的就是最好的,大多时候是合适的才是最好的。过多的否定自己的想法会使得自己思想僵化,总是以为自己办不到,总以为别人的最好,我觉得这样不利于自己成长,不利于自己原创思想的迸发。对于绘图,首先要有笔吧,而笔呢,什么颜色?多粗?然后是你绘画在什么地方?比如画在纸上,你的纸张有多大?纸张的背景颜色什么?白的?黑的?。。。这些物质上的准备都是必须的吧?所以,第一个函数就是准备“笔”和“纸”的,如果有必要,自己还可以细分选择“笔”和”纸“的动作,这里我觉得我暂时用不到,我就不再细分下去了。剩下的事情就是真正的画图了,画得怎么样就考验个人能力了,就像画家之间的绘画能力一样,画得好,画得差都体现在这里。当然前面选择“笔”和选择“纸张”也考验人,图形的绘制考验人的审美能力和绘画能力,选择什么样的“笔”和“纸”自己定。对于绘制波形图,肯定先要绘制坐标框架,然后再绘制波形,因为如果先绘制波形,那么波形就会有可能被坐标框遮住一部分;同样如果要在图中有网格,那么肯定也是先绘制坐标框架再绘制网格最后绘制波形,这些和实际绘图有所区别。

  现在开始代码。首先是在OnPaint里面,准备“笔”和“纸”

 1 void DTTFDlg::OnPaint()
 2 {
 3     CPaintDC dc(this); // device context for painting
 4     // TODO: 在此处添加消息处理程序代码
 5     // 不为绘图消息调用 CDialog::OnPaint()
 6     CWnd* pWnd;
 7     CRect rc;
 8     pWnd = GetDlgItem(IDC_STATIC_FFTPIC);
 9     pWnd->GetWindowRect(rc);
10     CDC* pdc = pWnd->GetDC();
11     StartDraw(rc,pdc,1);
12 }
View Code

准备“笔”和“纸”的函数,

 1 void DTTFDlg::StartDraw(CRect rc, CDC* pdc, int flag)
 2 {
 3     CPen newPen;       // 用于创建新画笔   
 4     CPen *pOldPen;     // 用于存放旧画笔   
 5     CBrush newBrush;   // 用于创建新画刷   
 6     CBrush *pOldBrush; // 用于存放旧画刷   
 7 
 8     int width = rc.Width();
 9     int height = rc.Height();
10 
11 //绘图前的准备,一般不要改
12 //*******************************************************************    
13     CDC   MemDC;   //首先定义一个显示设备对象   
14     CBitmap   MemBitmap;//定义一个位图对象    
15   //随后建立与屏幕显示兼容的内存显示设备   
16     MemDC.CreateCompatibleDC(NULL);   
17   //这时还不能绘图,因为没有地方画   ^_^   
18   //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小   
19     MemBitmap.CreateCompatibleBitmap(pdc,width,height);       
20   //将位图选入到内存显示设备中   
21   //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上   
22     CBitmap   *pOldBit=MemDC.SelectObject(&MemBitmap);     
23   //先用背景色将位图清除干净,这里我用的是白色作为背景   
24   //你也可以用自己应该用的颜色   
25     MemDC.FillSolidRect(0,0,width,height,RGB(0,0,0));   
26 //*******************************************************************
27 
28 //按照自己的情况来选择背景颜色
29 //*******************************************************************
30     // 创建黑色新画刷   
31     newBrush.CreateSolidBrush(RGB(0,0,0));     
32     pOldBrush = MemDC.SelectObject(&newBrush);   
33     // 以黑色画刷为绘图控件填充黑色,形成黑色背景   
34     MemDC.Rectangle(rc);   
35     // 恢复旧画刷   
36     MemDC.SelectObject(pOldBrush);   
37     // 删除新画刷   
38     newBrush.DeleteObject();    
39     // 创建实心画笔,粗度为1,颜色为绿色   
40     newPen.CreatePen(PS_SOLID, 1, RGB(0,255,0));   
41     // 选择新画笔,并将旧画笔的指针保存到pOldPen   
42     pOldPen = MemDC.SelectObject(&newPen);   
43 //*******************************************************************
44 
45 
46 //放置要用到的绘图函数
47 //*******************************************************************
48 //绘制网格
49     DrawPic(rc, &MemDC,1);
50 //绘制图形
51     Plot(rc,&MemDC,1);
52 //*******************************************************************
53  
54 
55 //处理后事,一般不用改
56 //*******************************************************************
57     MemDC.SelectObject(pOldPen);    // 恢复旧画笔   
58     newPen.DeleteObject();            // 删除新画笔   
59 //将内存中的图拷贝到屏幕上进行显示    
60     pdc->BitBlt(0,0,width,height,&MemDC,0,0,SRCCOPY);     
61 //绘图完成后的清理   
62     MemBitmap.DeleteObject();   
63     MemDC.DeleteDC();  
64 //*******************************************************************
65 }
View Code

绘制网格,9列5行,

  1 void DTTFDlg::DrawGrid(CRect rc, CDC* pdc, int flag)
  2 {
  3 //绘制网格的参数
  4     int x = g;
  5     int y = g;
  6     int h = height - 2*g;
  7     int w = width - 2*g;
  8     int wg = (int)(w/10);
  9     int hg = (int)(h/6);
 10     int sg = (width - 2*g)/50;
 11 
 12     int wi[10];
 13     int hi[5];
 14     int i;
 15 //竖线
 16     switch(w%10)
 17     {
 18     case 0:
 19         for(i = 0; i < 10; i++)
 20             wi[i] = wg;
 21         break;
 22     case 1:
 23         for(i = 0; i < 10; i++)
 24         {
 25             if(i == 0)
 26                 wi[i] = wg+1;
 27             else
 28                 wi[i] = wg;
 29         }
 30         break;
 31     case 2:
 32         for(i = 0; i < 10; i++)
 33         {
 34             if(i <= 1)
 35                 wi[i] = wg+1;
 36             else
 37                 wi[i] = wg;
 38         }
 39         break;
 40     case 3:
 41         for(i = 0; i < 10; i++)
 42         {
 43             if(i <= 2)
 44                 wi[i] = wg+1;
 45             else
 46                 wi[i] = wg;
 47         }
 48         break;
 49     case 4:
 50         for(i = 0; i < 10; i++)
 51         {
 52             if(i <= 3)
 53                 wi[i] = wg+1;
 54             else
 55                 wi[i] = wg;
 56         }
 57         break;
 58     case 5:
 59         for(i = 0; i < 10; i++)
 60         {
 61             if(i <= 4)
 62                 wi[i] = wg+1;
 63             else
 64                 wi[i] = wg;
 65         }
 66         break;
 67     case 6:
 68         for(i = 0; i < 10; i++)
 69         {
 70             if(i <= 5)
 71                 wi[i] = wg+1;
 72             else
 73                 wi[i] = wg;
 74         }
 75         break;
 76     case 7:
 77         for(i = 0; i < 10; i++)
 78         {
 79             if(i <= 6)
 80                 wi[i] = wg+1;
 81             else
 82                 wi[i] = wg;
 83         }
 84         break;
 85     case 8:
 86         for(i = 0; i < 10; i++)
 87         {
 88             if(i <= 7)
 89                 wi[i] = wg+1;
 90             else
 91                 wi[i] = wg;
 92         }
 93         break;
 94     case 9:
 95         for(i = 0; i < 10; i++)
 96         {
 97             if(i <= 8)
 98                 wi[i] = wg+1;
 99             else
100                 wi[i] = wg;
101         }
102         break;
103     }
104 //横线
105     switch(h%6)
106     {
107     case 0:
108         for(i = 0; i < 5; i++)
109             hi[i] = hg;
110         break;
111     case 1:
112         for(i = 0; i < 5; i++)
113         {
114             if(i == 0)
115                 hi[i] = hg+1;
116             else
117                 hi[i] = hg;
118         }
119         break;
120     case 2:
121         for(i = 0; i < 5; i++)
122         {
123             if(i <= 1)
124                 hi[i] = hg+1;
125             else
126                 hi[i] = hg;
127         }
128         break;
129     case 3:
130         for(i = 0; i < 5; i++)
131         {
132             if(i <= 2)
133                 hi[i] = hg+1;
134             else
135                 hi[i] = hg;
136         }
137         break;
138     case 4:
139         for(i = 0; i < 5; i++)
140         {
141             if(i <= 3)
142                 hi[i] = hg+1;
143             else
144                 hi[i] = hg;
145         }
146         break;
147     case 5:
148         for(i = 0; i < 5; i++)
149         {
150             if(i <= 4)
151                 hi[i] = hg+1;
152             else
153                 hi[i] = hg;
154         }
155         break;
156 
157     }
158 
159 //刻度
160     int temp1;
161     int temp2;
162     int j = 0;
163     int gi[50];
164     for(i = 0; i < 10; i++)
165     {
166         temp1 = wi[i]/5;
167         temp2 = wi[i]%5;
168         switch(temp2)
169         {
170         case 0:
171             for(j = 0; j < 5; j++)
172                 gi[5*i+j] = temp1;
173             break;
174         case 1:
175             for(j = 0; j < 5; j++)
176             {
177                 if(j == 0)
178                     gi[5*i+j] = temp1 + 1;
179                 else
180                     gi[5*i+j] = temp1;
181             }
182             break;
183         case 2:
184             for(j = 0; j < 5; j++)
185             {
186                 if(j <= 1)
187                     gi[5*i+j] = temp1 + 1;
188                 else
189                     gi[5*i+j] = temp1;
190             }
191             break;
192         case 3:
193             for(j = 0; j < 5; j++)
194             {
195                 if(j <= 2)
196                     gi[5*i+j] = temp1 + 1;
197                 else
198                     gi[5*i+j] = temp1;
199             }
200             break;
201         case 4:
202             for(j = 0; j < 5; j++)
203             {
204                 if(j <= 3)
205                     gi[5*i+j] = temp1 + 1;
206                 else
207                     gi[5*i+j] = temp1;
208             }
209             break;
210         }
211     }
212 
213 
214     CPen newPen;
215     CPen* pOldPen;
216 
217     if(flag == 0)
218         newPen.CreatePen(PS_DOT,1,RGB(128,128,128));    //网格的颜色为灰色
219     else
220         newPen.CreatePen(PS_DOT,1,RGB(169,169,169));    //网格的颜色为深灰色
221     pOldPen = pdc->SelectObject(&newPen);        //选择画笔
222 
223 //绘制竖线
224     for(int i = 0; i < 9 ; i++)
225     {
226         x = x + wi[i];
227         y = y + hi[i];
228         //绘制竖虚线
229         pdc->MoveTo(x,g);
230         pdc->LineTo(x,height-g);
231         //绘制横虚线
232         if(i < 5 && i != 2)
233         {
234             pdc->MoveTo(g,y);
235             pdc->LineTo(width-g,y);
236         }
237     }
238 
239 //销毁画笔
240     newPen.DeleteObject();
241 
242     if(flag == 0)
243         newPen.CreatePen(PS_SOLID,1,RGB(255,255,255));    //定义画笔,颜色为白色
244     else
245         newPen.CreatePen(PS_SOLID,1,RGB(0,0,0));    //定义画笔,颜色为黑色
246         pdc->SelectObject(newPen);    //选择新画笔
247 
248 //绘制坐标轴的边框
249     x = g;
250     y = g;
251     pdc->MoveTo(g,g);
252     pdc->LineTo(width-g,g);
253     pdc->MoveTo(width-g,g);
254     pdc->LineTo(width-g,height-g);
255     pdc->MoveTo(width-g,height-g);
256     pdc->LineTo(g,height-g);
257     pdc->MoveTo(g,height-g);
258     pdc->LineTo(g,g);
259 //绘制x轴轴线
260     pdc->MoveTo(x,y+3*hg);
261     pdc->LineTo(width-g,y+3*hg);
262 
263 //绘制刻度
264     int x1 = g;
265     int yv = y+3*hg;
266     for(int i = 0; i < 50; i++)
267     {
268         x1 = x1 + gi[i];
269         pdc->MoveTo(x1,yv+3);
270         pdc->LineTo(x1,yv-2);
271     }
272 
273     pdc->SelectObject(pOldPen);
274     newPen.DeleteObject();
275 }
View Code

绘制波形图

 1 CPen newPen;
 2     CPen* pOldPen;
 3     newPen.CreatePen(PS_SOLID,1,RGB(178,34,34));    //绘制曲线的颜色,火砖色
 4     pOldPen = pdc->SelectObject(&newPen);
 5     
 6     int height = rc.Height();
 7     int width = rc.Width();
 8     int w = width - 2*g;
 9     int h = height - 2*g;
10 
11     int x = g;
12     int y = g;
13     int i;
14 
15     double W = double(w*100)/100.0;
16     double H = double(h*100)/100.0;
17 
18     pdc->MoveTo(g,(int)(height/2));
19 
20     for(i = 0; i < m_PointNum;i++)
21     {    
22         x = g + int(W*xdata.retrieveAt(i)/xdata.maxValue());    //xdata要绘图的数据
23         y = (int)(height/2)-int(H/2*ydata.retrieveAt(i)/ydata.maxValue());//ydata要绘图的数据
24         pdc->LineTo(x,y);
25     }
26     pdc->SelectObject(pOldPen);
27     newPen.DeleteObject();
View Code

上面出现的变量,

1 //边框到窗口的距离
2     int g;    
3 //用于存储数据,arrayListType我自己写的
4     arrayListType<double> xdata;
5     arrayListType<double> ydata;
6 // 用于记录坐标点个数,在视图类构造函数中初始化为0。
7     int m_PointNum; 
View Code

 

转载于:https://www.cnblogs.com/WastonLiang/archive/2013/05/25/3099421.html

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值