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

Jave.Lin 2013-11-07 05:33:18
如题:

源码项目:Scale9GridTestingProject.rar

我的:Scale9Image类源码:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Scale9GridTestingProject
{
public class Scale9Image : Image
{
private ImageSource _imgSrc;
private Int32Rect? _rect;
private ImageSource[] _s9gFragment;
private bool _bootScale9;
private BitmapImage _bi;

public Scale9Image()
: this(null, null, true)
{
}

public Scale9Image(ImageSource imgSrc, Int32Rect? rect, bool bootScale9)
: base()
{
_imgSrc = imgSrc;
_rect = rect;
_bootScale9 = bootScale9;

Source = _imgSrc;
}

public ImageSource imgSrc
{
get { return _imgSrc; }
set
{
if (_imgSrc != value)
{
_imgSrc = value;
Source = _imgSrc;
InvalidateVisual();
}
}
}
public Int32Rect? rect
{
get { return _rect; }
set
{
if (_rect != value)
{
_rect = value;
InvalidateVisual();
}
}
}
public bool bootScale9
{
get { return _bootScale9; }
set
{
if (_bootScale9 != value)
{
_bootScale9 = value;
InvalidateVisual();
}
}
}

protected override void OnRender(DrawingContext dc)
{
if (_bootScale9 && _rect != null && _rect != Int32Rect.Empty)
{
OnS9GDraw(dc);
return;
}

base.OnRender(dc);
}

private void OnS9GDraw(DrawingContext dc)
{
if(Source == null) return;

DrawFragment(dc);
}

private void DrawFragment(DrawingContext dc)
{
Int32Rect r = rect.Value;
if (_s9gFragment == null)
{
Uri uri = new Uri(Source.ToString(), UriKind.RelativeOrAbsolute);
_bi = new BitmapImage(uri);
_s9gFragment = GetS9GImageSource(_bi, r);
}
ImageSource[] images = _s9gFragment;
Rect drawRect = new Rect(new Point(), new Size(r.X, r.Y));
double right = _bi.PixelWidth - (r.X + r.Width);
double bottom = _bi.PixelHeight - (r.Y + r.Height);
double drawWidth = ActualWidth - r.X - right;
double drawHeight = ActualHeight - r.Y - bottom;
drawWidth = drawWidth < 0 ? 1 : drawWidth;
drawHeight = drawHeight < 0 ? 1 : drawHeight;

// draw actualSize with Green color, why ActualWidth and ActualHeigth is incorrect(in runtimes see it)?
dc.DrawRectangle(Brushes.Green, new Pen(Brushes.Blue, 1), new Rect(0, 0, ActualWidth, ActualHeight));
// draw dpiSize with Red color, why Width and Height is incorrect(in runtimes see it)?
dc.DrawRectangle(Brushes.Red, new Pen(Brushes.Blue, 1), new Rect(0, 0, Width, Height));

// tl
dc.DrawImage(images[0], drawRect);
// tm
drawRect.X += drawRect.Width;
drawRect.Width = drawWidth;
dc.DrawImage(images[1], drawRect);
// tr
drawRect.X += drawRect.Width;
drawRect.Width = right;
dc.DrawImage(images[2], drawRect);

// ml
drawRect.X = 0;
drawRect.Y = r.Y;
drawRect.Width = r.X;
drawRect.Height = drawHeight;
dc.DrawImage(images[3], drawRect);
// mm
drawRect.X += drawRect.Width;
drawRect.Width = drawWidth;
dc.DrawImage(images[4], drawRect);
// mr
drawRect.X += drawRect.Width;
drawRect.Width = right;
dc.DrawImage(images[5], drawRect);

// bl
drawRect.X = 0;
drawRect.Y = ActualHeight - bottom;
drawRect.Width = r.X;
drawRect.Height = bottom;
dc.DrawImage(images[6], drawRect);
// bm
drawRect.X += drawRect.Width;
drawRect.Width = drawWidth;
dc.DrawImage(images[7], drawRect);
// br
drawRect.X += drawRect.Width;
drawRect.Width = right;
dc.DrawImage(images[8], drawRect);

// after draw done, u can see the gap of between s9gimg fragments, why ?
// anybody help me~~~~ >_< ~~~~
}

public static ImageSource CutImage(BitmapSource source, Int32Rect clipRect)
{
ImageSource results = null;
var stride = clipRect.Width * (source.Format.BitsPerPixel / 8);
var pixelsCount = clipRect.Width * clipRect.Height;//tileWidth * tileHeight;
var tileRect = new Int32Rect(0, 0, clipRect.Width, clipRect.Height);

var pixels = new int[pixelsCount];
//var copyRect = new Int32Rect(col * tileWidth, row * tileHeight, tileWidth, tileHeight);
source.CopyPixels(clipRect, pixels, stride, 0);
var wb = new WriteableBitmap(
clipRect.Width,
clipRect.Height,
source.DpiX,
source.DpiY,
source.Format,
source.Palette);
wb.Lock();
wb.WritePixels(tileRect, pixels, stride, 0);
wb.Unlock();

results = wb;
return results;
}

public static ImageSource[] GetS9GImageSource(BitmapSource source, Int32Rect clipRect)
{
ImageSource[] results = new ImageSource[9];
Int32Rect rect = Int32Rect.Empty;
int rightSideWidth = (int)(source.PixelWidth - clipRect.X - clipRect.Width);
//top-left
rect.Width = clipRect.X;
rect.Height = clipRect.Y;
results[0] = CutImage(source, rect);
//return results;
//top-middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[1] = CutImage(source, rect);
//top-right
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[2] = CutImage(source, rect);

//left side
rect = Int32Rect.Empty;
rect.Y = clipRect.Y;
rect.Width = clipRect.X;
rect.Height = clipRect.Height;
results[3] = CutImage(source, rect);

//middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[4] = CutImage(source, rect);

//right side
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[5] = CutImage(source, rect);
//bottom-left
rect = Int32Rect.Empty;
rect.Y = clipRect.Y + clipRect.Height;
// rect.X = clipRect.X;
rect.Height = source.PixelHeight - clipRect.Height - clipRect.Y;
rect.Width = clipRect.X;
results[6] = CutImage(source, rect);

//bottom-middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[7] = CutImage(source, rect);
//bottom-right
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[8] = CutImage(source, rect);
return results;
}
}
}



运行效果:
...全文
296 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangxinbo 2014-09-26
  • 打赏
  • 举报
回复
楼主 能把改好的源码发给我一份么 836390007@qq.com
Jave.Lin 2013-11-11
  • 打赏
  • 举报
回复
可以结贴了。。。 这个Scale9Image.cs类,我放到项目中,去使用,又没发现,有裂痕。 而且,Width,Height怎么设置都不会出现了。 当然,因为有些代码优化过。 话说,CSDN的人感觉越来越少了。
Jave.Lin 2013-11-07
  • 打赏
  • 举报
回复
。。。。。。没有人的?

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧