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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM