首页 新闻 会员 周边 捐助

C# WPF 制作9宫格,出现:间隔、裂痕,问题

0
悬赏园豆:10 [已解决问题] 解决于 2013-11-12 11:20

如题:

源码项目:Scale9GridTestingProject.rar

我的:Scale9Image类源码:

  1 using System;
  2 using System.Windows;
  3 using System.Windows.Controls;
  4 using System.Windows.Media;
  5 using System.Windows.Media.Imaging;
  6 
  7 namespace Scale9GridTestingProject
  8 {
  9     public class Scale9Image : Image
 10     {
 11         private ImageSource _imgSrc;
 12         private Int32Rect? _rect;
 13         private ImageSource[] _s9gFragment;
 14         private bool _bootScale9;
 15         private BitmapImage _bi;
 16 
 17         public Scale9Image()
 18             : this(null, null, true)
 19         {
 20         }
 21 
 22         public Scale9Image(ImageSource imgSrc, Int32Rect? rect, bool bootScale9)
 23             : base()
 24         {
 25             _imgSrc = imgSrc;
 26             _rect = rect;
 27             _bootScale9 = bootScale9;
 28 
 29             Source = _imgSrc;
 30         }
 31 
 32         public ImageSource imgSrc 
 33         {
 34             get { return _imgSrc; }
 35             set
 36             {
 37                 if (_imgSrc != value)
 38                 {
 39                     _imgSrc = value;
 40                     Source = _imgSrc;
 41                     InvalidateVisual();
 42                 }
 43             }
 44         }
 45         public Int32Rect? rect 
 46         { 
 47             get { return _rect; }
 48             set
 49             {
 50                 if (_rect != value)
 51                 {
 52                     _rect = value;
 53                     InvalidateVisual();
 54                 }
 55             }
 56         }
 57         public bool bootScale9 
 58         { 
 59             get { return _bootScale9; }
 60             set
 61             {
 62                 if (_bootScale9 != value)
 63                 {
 64                     _bootScale9 = value;
 65                     InvalidateVisual();
 66                 }
 67             }
 68         }
 69 
 70         protected override void OnRender(DrawingContext dc)
 71         {
 72             if (_bootScale9 && _rect != null && _rect != Int32Rect.Empty)
 73             {
 74                 OnS9GDraw(dc);
 75                 return;
 76             }
 77             
 78             base.OnRender(dc);
 79         }
 80 
 81         private void OnS9GDraw(DrawingContext dc)
 82         {
 83             if(Source == null) return;
 84 
 85             DrawFragment(dc);
 86         }
 87 
 88         private void DrawFragment(DrawingContext dc)
 89         {
 90             Int32Rect r = rect.Value;
 91             if (_s9gFragment == null)
 92             {
 93                 Uri uri = new Uri(Source.ToString(), UriKind.RelativeOrAbsolute);
 94                 _bi = new BitmapImage(uri);
 95                 _s9gFragment = GetS9GImageSource(_bi, r);
 96             }
 97             ImageSource[] images = _s9gFragment;
 98             Rect drawRect = new Rect(new Point(), new Size(r.X, r.Y));
 99             double right = _bi.PixelWidth - (r.X + r.Width);
100             double bottom = _bi.PixelHeight - (r.Y + r.Height);
101             double drawWidth = ActualWidth - r.X - right;
102             double drawHeight = ActualHeight - r.Y - bottom;
103             drawWidth = drawWidth < 0 ? 1 : drawWidth;
104             drawHeight = drawHeight < 0 ? 1 : drawHeight;
105 
106             // draw actualSize with Green color, why ActualWidth and ActualHeigth is incorrect(in runtimes see it)?
107             dc.DrawRectangle(Brushes.Green, new Pen(Brushes.Blue, 1), new Rect(0, 0, ActualWidth, ActualHeight));
108             // draw dpiSize with Red color, why Width and Height is incorrect(in runtimes see it)?
109             dc.DrawRectangle(Brushes.Red, new Pen(Brushes.Blue, 1), new Rect(0, 0, Width, Height));
110 
111             // tl
112             dc.DrawImage(images[0], drawRect);
113             // tm
114             drawRect.X += drawRect.Width;
115             drawRect.Width = drawWidth;
116             dc.DrawImage(images[1], drawRect);
117             // tr
118             drawRect.X += drawRect.Width;
119             drawRect.Width = right;
120             dc.DrawImage(images[2], drawRect);
121 
122             // ml
123             drawRect.X = 0;
124             drawRect.Y = r.Y;
125             drawRect.Width = r.X;
126             drawRect.Height = drawHeight;
127             dc.DrawImage(images[3], drawRect);
128             // mm
129             drawRect.X += drawRect.Width;
130             drawRect.Width = drawWidth;
131             dc.DrawImage(images[4], drawRect);
132             // mr
133             drawRect.X += drawRect.Width;
134             drawRect.Width = right;
135             dc.DrawImage(images[5], drawRect);
136 
137             // bl
138             drawRect.X = 0;
139             drawRect.Y = ActualHeight - bottom;
140             drawRect.Width = r.X;
141             drawRect.Height = bottom;
142             dc.DrawImage(images[6], drawRect);
143             // bm
144             drawRect.X += drawRect.Width;
145             drawRect.Width = drawWidth;
146             dc.DrawImage(images[7], drawRect);
147             // br
148             drawRect.X += drawRect.Width;
149             drawRect.Width = right;
150             dc.DrawImage(images[8], drawRect);
151 
152             // after draw done, u can see the gap of between s9gimg fragments, why ?
153             // anybody help me~~~~ >_< ~~~~
154         }
155 
156         public static ImageSource CutImage(BitmapSource source, Int32Rect clipRect)
157         {
158             ImageSource results = null;
159             var stride = clipRect.Width * (source.Format.BitsPerPixel / 8);
160             var pixelsCount = clipRect.Width * clipRect.Height;//tileWidth * tileHeight;
161             var tileRect = new Int32Rect(0, 0, clipRect.Width, clipRect.Height);
162 
163             var pixels = new int[pixelsCount];
164             //var copyRect = new Int32Rect(col * tileWidth, row * tileHeight, tileWidth, tileHeight);
165             source.CopyPixels(clipRect, pixels, stride, 0);
166             var wb = new WriteableBitmap(
167                 clipRect.Width,
168                 clipRect.Height,
169                 source.DpiX,
170                 source.DpiY,
171                 source.Format,
172                 source.Palette);
173             wb.Lock();
174             wb.WritePixels(tileRect, pixels, stride, 0);
175             wb.Unlock();
176 
177             results = wb;
178             return results;
179         }
180 
181         public static ImageSource[] GetS9GImageSource(BitmapSource source, Int32Rect clipRect)
182         {
183             ImageSource[] results = new ImageSource[9];
184             Int32Rect rect = Int32Rect.Empty;
185             int rightSideWidth = (int)(source.PixelWidth - clipRect.X - clipRect.Width);
186             //top-left
187             rect.Width = clipRect.X;
188             rect.Height = clipRect.Y;
189             results[0] = CutImage(source, rect);
190             //return results;
191             //top-middle
192             rect.X += rect.Width;
193             rect.Width = clipRect.Width;
194             results[1] = CutImage(source, rect);
195             //top-right
196             rect.X += rect.Width;
197             rect.Width = rightSideWidth;
198             results[2] = CutImage(source, rect);
199 
200             //left side
201             rect = Int32Rect.Empty;
202             rect.Y = clipRect.Y;
203             rect.Width = clipRect.X;
204             rect.Height = clipRect.Height;
205             results[3] = CutImage(source, rect);
206 
207             //middle
208             rect.X += rect.Width;
209             rect.Width = clipRect.Width;
210             results[4] = CutImage(source, rect);
211 
212             //right side
213             rect.X += rect.Width;
214             rect.Width = rightSideWidth;
215             results[5] = CutImage(source, rect);
216             //bottom-left
217             rect = Int32Rect.Empty;
218             rect.Y = clipRect.Y + clipRect.Height;
219             // rect.X = clipRect.X;
220             rect.Height = source.PixelHeight - clipRect.Height - clipRect.Y;
221             rect.Width = clipRect.X;
222             results[6] = CutImage(source, rect);
223 
224             //bottom-middle
225             rect.X += rect.Width;
226             rect.Width = clipRect.Width;
227             results[7] = CutImage(source, rect);
228             //bottom-right
229             rect.X += rect.Width;
230             rect.Width = rightSideWidth;
231             results[8] = CutImage(source, rect);
232             return results;
233         }
234     }
235 }
View Code

 

 

运行效果:

使用了两种方法,小的是使用:Grid容器9个cell分别拉伸处理,大的是自己写的:Scale9Image类处理

JaveLin的主页 JaveLin | 初学一级 | 园豆:195
提问于:2013-11-07 17:50
< >
分享
最佳答案
0

..母鸡为啥有gaps

收获园豆:10
+小马哥++ | 小虾三级 |园豆:906 | 2013-11-09 16:15

。。。我也母鸡,所以才问呐。

而且,我把Actual的宽度,都绘制出一个纯红色背景,与实际出来的9宫格图标大小又不一样大。

这又是个问题。。。

JaveLin | 园豆:195 (初学一级) | 2013-11-10 23:42

这效果,我在实际项目使用中,又不会出现裂痕。

原因不明。逻辑我是优化过,再拿到项目中使用,但逻辑都一样;

JaveLin | 园豆:195 (初学一级) | 2013-11-12 11:19
其他回答(1)
0

这效果,我在实际项目使用中,又不会出现裂痕。

原因不明。逻辑我是优化过,再拿到项目中使用,但逻辑都一样;

JaveLin | 园豆:195 (初学一级) | 2013-11-12 11:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册