CPF 入門教程 - 繪圖(四)
阿新 • • 發佈:2020-09-21
CPF NetCore跨平臺UI框架,增加了Vlc支援跨平臺播放視訊。
系列教程
CPF 入門教程(一)
CPF 入門教程 - 資料繫結和命令繫結(二)
CPF 入門教程 - 樣式和動畫(三)
CPF 入門教程 - 繪圖(四)
一般來說是不需要自己寫繪圖程式碼的,大部分UI效果通過控制元件元素(CPF.Shapes提供基礎圖形控制元件)組合和SVG組合就可以實現。
如果需要自定義控制元件繪製特殊的控制元件,可以繼承Control或者UIElement重寫OnRender方法來繪製自己需要的效果。呼叫 Invalidate 或者在依賴屬性上設定AffectsRender來重新整理介面。
/// <summary> /// 背景填充 /// </summary> [UIPropertyMetadata(null, UIPropertyOptions.AffectsRender)]//屬性變化之後自動重新整理 public ViewFill Background { get { return (ViewFill)GetValue(); } set { SetValue(value); } }
protected override void OnRender(DrawingContext dc) { var s = ActualSize; var rect = new Rect(0, 0, s.Width, s.Height); var ba = Background; if (ba != null) {//填充背景 using (var brush = ba.CreateBrush(rect, Root.RenderScaling)) { dc.FillRectangle(brush, rect); } } }
其中Background 是 ViewFill 型別,ViewFill和Brush區別就是ViewFill和UI元素相關,可以支援相對或者絕對的效果,以及DPI的縮放。
繪圖使用DrawingContext來操作,支援常規的圖形繪製,比如線條,文字,路徑等等。
使用剪輯區域的時候需要PushClip和PopClip配對,就是當你設定一個剪輯區域,使用完了之後你需要把你這個剪輯區域刪除。可以設定多次剪輯區域,像括號一樣配對和範圍。
dc.PushClip(rect);//設定一個剪輯區域 //繪圖操作 dc.DrawImage(bmp, rect, rect....... //.......... dc.PopClip();
矩陣使用
var old = dc.Transform;//獲取原來的矩陣 var eff = old; eff.Translate(-off.X + effectOffset.X, -off.Y + effectOffset.Y);//矩陣變換 dc.Transform = eff;//應用新矩陣 //繪圖操作 dc.Transform = old;//恢復原來的
PathGeometry 支援WPF和SVG的path裡的字串格式資料,隱式轉換。可以組合貝塞爾曲線,圓弧,線段等等用來繪製各種複雜的圖形效果。再通過DrawingContext繪製出來
比如:
PathGeometry path="m85.33333,682.66667l853.33334,0l0,21.33333l-853.33334,0l0,-21.33333z";
在位圖裡繪圖
using (Bitmap bmp = new Bitmap(width, height)) { using (var dc = DrawingContext.FromBitmap(bmp)) { //繪圖操作 } }
Bitmap的指標和畫素操作
/// <summary> /// 將圖片轉換成黑白色效果 /// </summary> /// <param name="bmp">原圖</param> public static unsafe void GrayScale(Bitmap bmp) { //確定影象的寬和高 int height = bmp.Height; int width = bmp.Width; using (var l = bmp.Lock()) {//l.DataPointer就是資料指標,一般不建議直接使用,因為不同平臺,不同圖形介面卡,不同點陣圖格式,資料格式不一樣,那你就需要判斷不同格式來遍歷指標資料處理了 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { l.GetPixel(x, y, out byte a, out byte r, out byte g, out byte b); var p = (byte)Math.Min(255, 0.7 * r + (0.2 * g) + (0.1 * b)); l.SetPixel(x, y, a, p, p, p); } // x } // y } }