為了讓大家更深入的了解和使用C#,我們將開始這一系列的主題為“C#發現之旅 ”的技術講座。考慮到各位大多是進行WEB數據庫開發的,而所謂發現就是發現我們所 不熟悉的領域,因此本系列講座內容將是C#在WEB數據庫開發以外的應用。目前規劃的主要內 容是圖形開發和XML開發,並計劃編排了多個課程。在未來的C#發現之旅中,我們按照由淺入 深,循序漸進的步驟,一起探索和發現C#的其他未知的領域,更深入的理解和掌握使用C#進 行軟件開發,拓寬我們的視野,增強我們的軟件開發綜合能力。
本次課程說明
本課程是Windows圖形開發入門,算是圖形開發知識掃盲,主要介紹圖形編程的一些 基礎理論知識,並無配套演示源代碼。其中包括
WEB數據庫開發和圖形開發的比較
Windows圖形子系統基本原理
圖形設備上下文
矢量圖形和位圖
圖形坐標系統
圖形界面基本元素
用戶界面事件
在此我假設各位具有一 定的計算機軟件開發基礎,了解基本的計算機軟硬件知識,但對Windows圖形開發則理解模糊 ,不甚了解。因此就介紹一下Windows圖形開發的基本原理,並不涉及到實際的開發,未來的 序列培訓中將以本次培訓為基礎,使用C#進行實際的Windows圖形開發演示。
WEB數據 庫開發和圖形開發的比較
現來講講WEB數據庫開發和圖形開發的比較。大家大多是搞 WEB數據庫開發的,其用戶界面基本上都是依賴HTML來進行描述,其實桌面開發也是大有可為 的,而桌面開發中很重要的一部分就是圖形開發。圖形開發和Web開發相比具有很大的不同, 其開發思想,技術手段,調試技巧等有著很大的不同現按以下幾個方面進行簡單說明。
面向的領域
Web數據庫編程和圖形開發存在比較大的區別,Web數據庫編程大 部分是面向工程開發的,其中充滿了各種業務數據結構,業務邏輯處理。而圖形開發相對而 言技術因素更多些,面向的領域比較專業和底層。對於那些想在純粹的技術上所有突破的人 來說,圖形開發是一種不錯的選擇。
難度
圖形開發比較難於學習和掌握,因 此熟練掌握圖形開發的開發人員相對比較少,而且各種軟件技能培訓機構都提供對WEB數據庫 開發的培訓,而提供圖形開發培訓的則很少。難就人少,人少競爭就少,因此圖形軟件開發 能力就成為一種與眾不同的軟件開發能力。
與數據庫的關系
Web數據庫應用系 統比較依賴關系型數據庫,數據庫是其系統中最重要的部分。而圖形開發則偏重於用戶界面 和圖形文檔輸出,因此對數據庫的依賴相對少些,很多圖形軟件的正常運行是不需要數據庫 的。
軟件設計和開發
比較復雜的圖形開發需要使用大量的軟件設計模式,有 時還需要文檔對象模型這種比較高級的軟件設計模型,這些復雜的軟件設計模式在常規的中 小型WEB數據庫開發中使用不多,因此深入學習圖形開發將明顯的增強開發者的軟件設計能力 。
相對於Web數據庫編程,圖形開發在開發,調試和優化手段上有著很大的不同,在 某些情況下,圖形程序的調試是相當困難的,而圖形程序所特有的抗閃爍優化過程是比較艱 難的,非常考驗開發者的軟件開發能力。
應用
在目前的企業信息化和電子政 務中,WEB數據庫開發模式占據著主流,但圖形開發仍然具有很廣泛的應用,而且很多是比較 底層的,基礎性的軟件開發。比如WEB浏覽器,VS.NET開發環境,甚至Windows操作系統本身 都是圖形開發的產品,WEB軟件中的圖表,曲線圖等HTML難於展現的用戶界面,一般也有賴於 圖形編程來實現。
展望
對於很多人來說,圖形開發是一個全新的開發領域, 需要使用新的軟件設計理驗和開發模式,但圖形開發也是一個豐富多彩的世界,有著非常多 的技術等待大家的探索。圖形開發雖然比較難,但仍然值得大家學習和使用。圖形開發難度 大,技術含量高,是一種優質的軟件開發能力。若大家想探索新的技術領域,並獲得與眾不 同的開發能力,那就可以從現在開始學習Windows圖形開發。
Windows圖形子系統基本 原理
Windows操作系統具有最明顯的特點是具有圖形化用戶界面,這種技術大大改善 了用戶體驗,使得大量的普通使用者能方便的學習和使用Windows操作系統,這是微軟取得巨 大成功的一個重要因素。
Windows操作系統針對圖形開發也提供了強大的編程接口, 使得開發者可以方便的在Windows上面開發具有專業效果的圖形化用戶界面軟件。在Windows 以前,開發者要實現圖形化用戶界面,則需要具備相當多的計算機硬件知識,計算機軟件業 界在圖形化用戶界面方面進展緩慢,而Windows則提供了一個很方便的圖形開發平台,使得大 量的圖形化用戶界面軟件迅速湧現,從而推動了計算機軟件業界整體快速發展。
Windows操作系統中包含了一個圖形子系統,專門用於管理各種圖形輸出設備,包括 顯示器,打印機,繪圖儀等。由於Windows系統啟用保護模式,應用程序沒有權限直接訪問計 算機硬件,因此都必須調用Windows的圖形子系統來操作圖形設備。下圖就是Windows環境下 圖形軟件的基本原理。
Windows提供 了一個GDI32.DLL,稍微了解圖形開發的都知道這個DLL,它包含了大部分的Windows的圖形子 系統的API函數。各種開發語言,包括VB,VC,C#,Delphi等等都能調用這些API函數來進行圖形 開發。
Windows通過這些API獲得應用系統的圖形操作請求後,內部進行一番處理,然 後根據目標圖形硬件調用相應的設備驅動程序。
若應用系統請求在顯示器上顯示圖形 ,則Windows會首先設置計算機顯存,然後忙其他事,而顯卡中有一個獨立的處理器能自主訪 問顯存,根據其中的數據來設置顯示器中顯示的內容。顯卡是固定每過一段時間訪問顯存, 刷新顯示器,因此它有一個頻率的參數。比如它的頻率是50HZ,則它是每20毫秒訪問顯存, 刷新顯示器。顯卡自己有處理器來進行這樣的操作,這種操作算是硬件操作,其過程不受操 作系統的感知和控制。理解這個原理,對理解和消除用戶界面閃爍有著很大的幫助。
若應用系統請求進行打印輸出,則Windows首先將打印樣式輸出到打印任務隊列中,然後調用 打印機驅動程序進行文檔的打印,由於具有打印任務隊列,因此多個軟件可同時進行打印輸 出,而不必等待打印機硬件空閒。在Windows2000或更高版本的Windows操作系統中,有一個 名為”Print Spooler”的服務,該服務就是用於管理打印任務隊列的,若該服務 停止,則系統即使連接了打印機也不能進行打印輸出。
圖形設備上下文
在了 解了Windows圖形子系統的基本原理後,我們可以開始了解Windows圖形開發了,在Windows圖 形開發中有一個很重要的概念就是-圖形設備上下文。
句柄
對Windows編程有 所了解的應該知道,WindowsAPI是一個個C語言樣式的函數,應用程序訪問大部分的操作系統 資源是通過一種叫句柄的整數類型數據。例如程序訪問文件,網絡資源,圖片,創建窗體等 等都會事先調用API函數獲得一個句柄,句柄可以理解成系統資源的唯一編號,應用程序應當 好好保存這個句柄,妥善利用,不用時一定要使用API函數釋放掉。
圖形設備上下文 句柄
應用軟件進行圖形操作時也得使用API函數申請一個圖形設備上下文句柄,以後 所有的圖形操作都是針對這個句柄來進行的,應用軟件完成圖形操作後一定要使用API釋放這 個圖形設備上下文句柄。
圖形設備上下文是一種抽象概念,不限制到具體硬件,因此 Windows內部可以在這個抽象概念上大做文章,圖形設備上下文句柄可以指向顯示器,也可以 指向打印機或其他圖形硬件,這個過程對應用軟件是透明的,因此應用系統在此基礎上能比 較容易的實現所見即所得功能。可以做到一份圖形操作代碼,既可以向計算機屏幕輸出圖形 ,也可以控制打印機輸出圖形,這方便了圖形開發。
軟件設計模式
這種抽象 概念應用到不同的具體應用,是一種軟件設計模式。比如在C#中有一個抽象類 System.IO.Stream , 它表示一個抽象的流的概念,而.NET框架中在這個抽象概念的流上面實 現了各種具體的流,比如針對文件,HTTP資源,內存等等。應用軟件只要編寫代碼將數據保 存到抽象的流中,則同一份代碼,可以同時將數據保存到本地文件,HTTP文件,FTP文件或內 存中。這方便了程序的開發和擴展。
矢量圖形和位圖
概念
圖形開發中 有兩個重要的概念就是矢量圖形和位圖。
所謂矢量圖形,就是使用平面幾何中的點線 面等抽象概念來描述圖形。而位圖是采用大量的密集像素二維數組來描述圖形的。
對 於計算機來說,矢量圖復雜,但數據量小,可無級縮放;而位圖顯示過程簡單,但數據量大 ,放大時顯示效果差。
例子
我們的電腦中存在很多矢量圖和位圖的例子。例 如Flash是比較典型的矢量圖軟件,它生成的圖形文件.swf文件小,放大時顯示質量有保障; 而Windows畫圖板是操作位圖的,生成的圖形文件.bmp文件大,放大時顯示質量差。
還比如Windows字體。Windows字體有位圖字體和TrueType字體,位圖字體是基於位圖概念的 ,而TrueType字體是基於矢量圖形的。目前大部分字體是TrueType字體,我們可以設置這種 字體的樣式,大小,使用TrueType字體的文本即使顯示得非常大,其文本輪廓線條還是很清 晰的。目前少數字體是位圖字體,最常見的是Windows記事本默認使用的Fixedsys字體,這種 字體放大顯示時存在明顯的鋸齒。打印輸出質量不高。
圖形坐標系統
卡笛爾 直角坐標
描述和顯示矢量圖形時需要一個坐標系統,目前采用卡笛爾坐標,也就是具 有X-Y軸的直角坐標。圖形中每個圖形元素都由若干個X-Y坐標值和寬度高度值來確定。比如 一個點用一對XY值來確定位置,而一個線段用兩個XY值來定位,而矩形用一個XY值和寬度高 度值來定位。而圓或橢圓則用一個外切矩形來確定。
度量單位
坐標系還需要 指定度量單位,度量單位可以采用厘米,英寸。對於圖形用戶界面軟件很多時候采用像素單 位。
厘米,英寸等是抽象的度量單位,圖形采用這種抽象單位度量則是絕對准確的。 而像素度量單位是和圖形硬件相關的,一般情況下,顯示器像素長度是96個像素一英寸,而 打印機則是幾百個甚至上千個像素一英寸。因此相同的圖形,若采用像素大小,則在顯示器 中顯示和實際打印的大小相差是很大的。在這種情況下應當采用抽象的厘米和英寸等度量單 位,這樣才能做到所見即所得。
在.NET中已經考慮到了這種情況,枚舉類型 System.Drawing.GraphicsUnit 就列出了一些標准的坐標度量單位。
坐標轉換- Matrix(黑客帝國?)
坐標系還可以轉換,轉換類型主要有平移,旋轉和縮放。平移 是指坐標原點(XY值都為0的點)上下左右移動,而坐標度量單位等屬性不改變;旋轉是指坐 標系整體的以原點為中心,順時針旋轉一定的角度;而縮放則是將X軸或Y軸方向進行縮小或 放大,X方向和Y方向的縮放可以是獨立的。
大家都知道電影《黑客帝國》,這個電影 的英文名為Matrix,.NET框架也提供了一個Matrix,它就是坐標轉換對象,使用方便。它內 部是一個3X3的矩陣,坐標系的平移旋轉和縮放是通過一種矩陣運算來實現的。使用坐標轉換 對象,.NET程序可以很方便的實現某些特效,比如文本的垂直顯示,文本的拉伸或壓縮顯示 等等。
圖形界面基本元素
我們進行的大部分圖形開發是操作矢量圖形的。在 平面幾何中,矢量圖形是有點線面組成的。因此一個個點,線或面就是矢量圖形的基本元素 。實際圖形開發中,主要的圖形界面基本元素有文本,直線段,矩形,橢圓(包括正圓), 橢圓弧(包括圓弧),還有一些其他曲線。基本的繪圖操作有繪制線條和填充區域。使用上 述方法就能繪制出絕大多數的圖形。
在Windows圖形用戶界面中,使用最多的圖形基 本元素是文本和矩形。各種窗體,控間,其輪廓都是矩形。文本可以是單行,多行,可分為 左對齊,居中對齊和右對齊等等。繪制文本和矩形是最簡單最基本的圖形操作。
用戶 界面事件
大部分的圖形化用戶界面需要響應用戶界面事件來實現互動式用戶體驗,用 戶界面事件主要包括窗體重繪事件,鼠標鍵盤事件,定時器事件,OLE拖拽事件等等,其中最 重要的就是窗體重繪事件和鼠標鍵盤事件了。
Windows底層使用Windows消息的方式向 應用程序通知各種事件,而.NET框架封裝了這些消息處理,並提供了一些可擴展的編程接口 來方便進行事件響應編程。比如我們可以掛上控件的MouseDown事件,也可以重寫控件的 OnMouseDown方法來處理鼠標按鍵按下事件。
窗體重繪事件
用戶界面事件中必 須處理的事件是窗體重繪事件。Windows是多任務操作系統,它允許顯示器上同時顯示多個窗 體,於是窗體之間不可避免的發生覆蓋。一個窗體的部分或全部可能被覆蓋和重新顯示。當 控件由被遮蓋到顯示時,應用軟件需要重新繪制控件的用戶界面。
如圖所示,窗體2 覆蓋了窗體1,此時我的控件有一部分被覆蓋了,當用戶設置了窗體1靠前顯示時,我的控件 原先被窗體2覆蓋的部分給顯示出來了,此時形成了一個剪切矩形,程序需要重新繪制我的控 件的用戶界面,很顯然,程序只需要繪制剪切矩形所包括的部分,其他的部分就不需要顯示 ,這樣我們就能使用這個剪切矩形來優化我們的程序,減少圖形繪制工作量。
我的控 件不需要判斷什麼時候由於窗體重新顯示時要重新繪制用戶界面,Windows操作系統會判斷這 種情況,然後通過消息通知我的控件要重新繪制用戶界面,而且在通知的時候就告訴了剪切 矩形的位置和大小。
在..NET平台 上,.NET框架已經封裝了底層的消息處理,並提供了Paint事件或OnPaint方法的編程接口。 我們需要掛靠控件的Paint事件,或者重寫OnPaint方法來重新繪制用戶界面。在這個事件中 系統提供兩個參數,一個是圖形繪制對象Graphics,另外一個是名為ClipRectangle的剪切矩 形對象,也就是要重新繪制區域的邊框。ClipRectangle是優化圖形繪制操作的基礎。
鼠標事件
大部分情況下用戶要求能使用鼠標操作來進行處理,此時圖形軟件 必須響應用戶的鼠標操作來進行某些處理,在C#圖形軟件開發中,我們需要響應控件的鼠標 事件,我們需要掛靠控件的MouseDown或重寫OnMouseDown方法來處理鼠標按鍵按下事件,使 用MouseMove或重寫OnMouseMove方法來處理鼠標移動事件,使用MouseUp事件或重寫 OnMouseUp方法來處理鼠標按鍵松開事件。
鍵盤事件
用戶也經常要求能使用鍵 盤來進行操作,比如對於文本編輯器,用戶需要使用鍵盤來輸入大量的文本字符,移動光標 等等。此時圖形軟件必須響應用戶的鍵盤操作來進行某些處理,在C#圖形軟件開發中,我們 需要響應控件的鍵盤事件,我們需要使用KeyDown或重寫OnKeyDown方法來處理鍵盤按鍵按下 事件,使用KeyUp事件或重寫OnKeyUp方法來處理鍵盤按鍵松開事件,使用KeyPress或 OnKeyPress方法來處理鍵盤字符事件。
其他事件
在C#中我們還可以處理其他 的事件,比如我們在窗體中放置了一個定時器控件,則我們可以處理它的定時器事件來固定 的每隔一段時間進行操作。我們從Windows資源管理器中拖拽一個文件到我們的程序中,我們 可以響應控件的OLE拖拽事件來接受拖拽過來的文件的數據。
通過各種各樣的事件, 我們就可以實現圖形用戶界面的各種動態操作特性。這樣就維持了圖形軟件的正常運行,並 提供了互動的用戶體驗。
小結
本次課程主要是說明了Windows圖形開發的基本 原理,圖形開發的一些理論知識。圖形開發是一個很大的話題,其理論知識涉及很廣泛,對 此本次課程無法一一說明,在未來的培訓中,將開始使用C#來實踐圖形開發,並在開發過程 中補充說明其中涉及到的各種軟件開發知識。
大家若打算認真學習圖形開發,可以發 揮主觀能動性,多多自我學習和相互學習。大家用慣了ASP.NET,對圖形編程有些陌生,從下 一次課程開始,我們將一起去發現C#圖形開發。