夏克付, 張承云
(1.安徽電子信息職業(yè)技術學院,安徽 蚌埠 233030;2.安徽科大訊飛信息科技股份有限公司,安徽 合肥 230088)
動態(tài)繪圖是指使用鍵盤、鼠標、手寫板等計算機輸入設備動態(tài)繪制圖形或圖像.動態(tài)繪圖技術是圖形圖像處理領域中的一項非常重要的技術.GDI+是圖形設備接口GDI(graphics device interface)的改進版本,提供了二維矢量圖形的顯示、圖像處理和版式處理等功能.在.NET中,GDI+提供了一系列圖形圖像處理相關的類與接口,使用這些類與接口可以很輕松地實現(xiàn)動態(tài)繪圖功能.但這種動態(tài)繪圖技術在繪圖過程中存在圖形連續(xù)繪制、閃爍和消失等問題,嚴重影響了圖形繪制的效果與效率.因此,怎樣研究一種基于GDI+的高效的動態(tài)繪圖技術,已成為當前亟待解決的問題.
動態(tài)繪圖過程一般是在按下鼠標后確定所繪圖形的起始點,移動鼠標時繪制圖形,松開鼠標后完成繪圖.因此,在實現(xiàn)動態(tài)繪圖功能時一般需要使用鼠標的按下(MouseDown)、移動(MouseMove)和松開(MouseUp)事件.在使用GDI+提供的動態(tài)繪圖技術進行動態(tài)繪圖的過程中,容易出現(xiàn)以下問題.
圖1是使用GDI+的動態(tài)繪圖技術在.NET窗體上動態(tài)繪制直線的效果.從圖中可以看出,鼠標每移動一次就會繪制一條直線,這樣從按下鼠標到松開鼠標的過程中,繪制的就不是所期望的一條直線,而是“無數條”直線.
要解決這個問題,可以在MouseMove事件中加上一條圖形清除語句,使得在每次繪制直線時清除之前所繪制的內容.但這樣做又有了新的問題,也就是永遠只能繪制一條直線.
圖1 動態(tài)繪制直線
使用GDI+的動態(tài)繪圖技術在動態(tài)繪圖時容易出現(xiàn)閃爍現(xiàn)象,特別是對圖像進行動態(tài)處理時,只要移動鼠標,圖像閃爍現(xiàn)象就非常明顯.
使用GDI+的動態(tài)繪圖技術所繪制的圖形,被其他程序界面覆蓋恢復后或程序最小化恢復后,圖形消失.要解決此問題,可以在窗體或控件的Paint事件中對消失的圖形進行重繪,但這樣做比較麻煩.
要解決動態(tài)繪圖過程中所出現(xiàn)的問題,需要引入“圖層”技術.在此引入三個“圖層”,依次分別是:永久層、臨時層和顯示層.其中永久層用于永久存儲每次動態(tài)繪制完成的圖形,臨時層用于臨時存儲鼠標一次移動時所繪制的圖形,顯示層用于在窗體或控件中顯示臨時層中所繪制的圖形.各圖層及其關系如圖2所示.
圖2 動態(tài)繪圖圖層
圖2中的箭頭表示在動態(tài)繪圖過程中該層內容的來源.永久層表示最終需要繪制的圖形,在開始繪圖之前,該層內容要么為空,要么來源于需要繪制的圖形或圖像,在繪圖過程中,該層內容來源于顯示層;臨時層表示鼠標本次移動所繪制的圖形,其內容來源于永久層,其生命周期從移動鼠標開始到松開鼠標結束;顯示層表示當前需要顯示的圖形,其內容來源于臨時層.
在.NET中,永久層和臨時層一般使用GDI+提供的Bitmap對象來實現(xiàn),顯示層一般使用窗體或控件的Image類型的屬性來實現(xiàn).在繪圖過程中,臨時層和顯示層的內容在MouseMove事件中完成,永久層的內容在MouseUp事件中完成.主要實現(xiàn)過程如下:
(1)創(chuàng)建一個全局的Bitmap對象(用于實現(xiàn)永久層),大小與窗體或控件中繪圖區(qū)域大小一致.
Bitmap bmpForever=new Bitmap(this.Width,this.Height);
(2)在MouseMove事件中創(chuàng)建一個上述全局對象的副本(用于實現(xiàn)臨時層).
Bitmap bmpTemp = (Bitmap)bmpForever.Clone();
(3)以上述副本為畫布來動態(tài)繪制圖形(如直線).
Graphics g = Graphics.FromImage(bmp-Temp);
g.DrawLine(pen,pt,e.Location);
(4)在窗體或控件中即時顯示上述副本中所繪制的圖形(用于實現(xiàn)顯示層).
this.BackgroundImage=bmpTemp;
(5)在MouseUp事件中將本次繪制完成的圖形存入上述全局對象.
Graphics g=Graphics.FromImage(bmpForever);
g.DrawImage(this.BackgroundImage,0,0);
在.NET中使用C#語言按照以上改進方法在窗體上動態(tài)繪制直線的效果如圖3所示.從圖中可以看出,可以在窗體的任意位置使用鼠標繪制直線,解決了之前動態(tài)繪圖過程中所出現(xiàn)的問題.
圖3 動態(tài)繪制直線(改進后)
圖4 動態(tài)繪圖技術應用
圖5 數據測量類
動態(tài)繪圖技術的應用非常廣泛,只要有電腦、手機等電子產品存在的地方,基本上都會用到動態(tài)繪圖技術.例如生活中最常見的手寫輸入法、幻燈片中的動態(tài)批注等都使用了動態(tài)繪圖技術.在醫(yī)院使用的各種軟件系統(tǒng)中,動態(tài)繪圖技術也隨處可見.下面以動態(tài)測量患者CT圖中的相關數據為例,介紹動態(tài)繪圖技術的應用(如圖4所示).
圖4是對某位患者腦部CT圖進行相關數據測量.從圖中可知,數據測量功能主要包括動態(tài)繪制圖形、根據CT圖的顯示大小與實際大小的比例實時測量數據,以及當前所測量數據的解釋說明.主要實現(xiàn)過程如下:
(1)設計數據測量類
根據引入“圖層”后的動態(tài)繪圖技術,以及對CT圖進行數據測量的功能需求,設計的數據測量類如圖5所示.
數據測量類(DataMeasurement)中共包括3個屬性和6個方法,這些屬性與方法的具體功能描述如表1所示.
表1 DataMeasurement類的成員功能描述
(2)創(chuàng)建應用程序,實現(xiàn)數據測量類
在Visual Studio 2008中新建一個Windows應用程序,設計圖4所示窗體,并實現(xiàn)數據測量類.而后使用該類實現(xiàn)圖4所示的數據測量功能.
GDI+提供了強大的圖形圖像處理功能,在.NET中使用GDI+幾乎可以完成所有與圖形圖像相關的操作.動態(tài)繪圖技術是使用GDI+進行動態(tài)圖形繪制的技術.通過在多個項目開發(fā)中的實踐證明,使用引入“圖層”后的動態(tài)繪圖技術,不僅解決了繪圖過程中存在的圖形連續(xù)繪制問題,還解決了使用GDI+進行圖形圖像處理時容易出現(xiàn)的閃爍現(xiàn)象,以及圖形被覆蓋或最小化后消失的現(xiàn)象,大大提高了程序的運行效率.
[1]謝超,陳毓芬.基于GDI+的電子地圖符號庫的改進[J].測繪工程,2006,15(2):45 -49.
[2]閆宇晗,常鑫.在C#中用GDI+實現(xiàn)圖像動態(tài)顯示[J].計算機技術與發(fā)展,2006,16(12):117—118.
[3]王磊.基于GDI+的圖形圖像處理[J].蘇州市職業(yè)大學學報,2008,19(4):7 -9.
[4]Christian Nagel,Bill Evjen.C#高級編程(第 6 版)[M].北京:清華大學出版社,2009.
[5]唐政,房大偉.C#項目開發(fā)全程實錄[M].北京:清華大學出版社,2010.