В идеальном мире, по версии Microsoft, дизайнеры творят интерфейс в Expression Blend, а программисты пишут бэкенд на C#. В реальности же дизайнеры творят в Photoshop, а программисты ломают голову как вот эту красивую кнопку сконвертировать в XAML, да так чтобы без большого количества костылей. Многие добиваются в этом выдающихся результатов. Стоит только слегка поискать и в сети найдётся куча вариантов, как можно из элементов WPF собрать довольно сложные дизайнерские решения. К сожалению, пару раз так повозившись и оценив затраты по времени понимаешь, что оно того не стоит, проще взять исходный элемент из нарезки как есть, т.е. в виде изображения. И такой вариант, как по мне, является наилучшим с точки зрения продуктивности, однако есть одно НО.
Картинкам часто нельзя изменить пропорции. Края изображения сильно сжимаются с одной стороны и растягиваются с другой. К примеру, дизайнер прислал нам изображения кнопки:
Вставив её в проект и слегка изменив пропорции получим следующую непотребщину:
Встаёт вопрос, как при ресайзе изображения сохранить края в таком виде, как предполагал дизайнер?
Посмотрим на структуру изображения, его можно условно разделить на 9 регионов: 4 угла, 4 края и центр.
При изменении пропорций нам надо, чтобы углы в этой сетке не изменяли размер совсем, края растягивались только в ширь, а центр мог менять размер свободно.
Этого добьёмся разрезав исходное изображение на регионы разместив в сетке элемента Grid.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | < UserControl x:Class = "UniformImageNamespace.UniformImage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" > < UserControl.Template > < ControlTemplate > < Grid SnapsToDevicePixels = "True" > < Grid.RowDefinitions > < RowDefinition Height = "Auto" /> < RowDefinition /> < RowDefinition Height = "Auto" /> </ Grid.RowDefinitions > < Grid.ColumnDefinitions > < ColumnDefinition Width = "Auto" /> < ColumnDefinition /> < ColumnDefinition Width = "Auto" /> </ Grid.ColumnDefinitions > < Image Grid.Row = "0" Grid.Column = "0" Stretch = "None" Source = "{Binding TopLeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "0" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding TopImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "0" Grid.Column = "2" Stretch = "None" Source = "{Binding TopRightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "1" Grid.Column = "0" > < Border.Background > < ImageBrush ImageSource = "{Binding LeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Border Grid.Row = "1" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding CenterImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Border Grid.Row = "1" Grid.Column = "2" > < Border.Background > < ImageBrush ImageSource = "{Binding RightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "2" Grid.Column = "0" Stretch = "None" Source = "{Binding BottomLeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "2" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding BottomImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "2" Grid.Column = "2" Stretch = "None" Source = "{Binding BottomRightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Grid > </ ControlTemplate > </ UserControl.Template > </ UserControl > |
Я создал пользовательский элемент управления с названием UniformImage.
В ячейки элемента Grid помещены части исходного изображения, нарезать которое будем в code behind. Также для нейтрализации проблем при состыковке регионов, задано свойство SnapsToDevicePixels. Заметьте, что крайние регионы изображения пришлось вставить в виде фона элемента Border. На это пришлось пойти, так как иначе элемент Image некорректно отображал свои пропорции.
Переходя к коду C# добавим два свойства: одно типа ImageSource для задания исходного изображения и второе StaticArea типа Thikness для получения толщины границы изображения, которая должна быть статична при ресайзе.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public static readonly DependencyProperty StaticAreaProperty = DependencyProperty.Register( "StaticArea" , typeof (Thickness), typeof (UniformImage), new PropertyMetadata(InvalidateImage) ); public Thickness StaticArea { get { return (Thickness)GetValue(StaticAreaProperty); } set { SetValue(StaticAreaProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( "Source" , typeof (ImageSource), typeof (UniformImage), new PropertyMetadata(InvalidateImage) ); public ImageSource Source { get { return (ImageSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } |
Метод InvalidateImage() в обоих свойствах будет отвечать за обновление регионов изображения при изменении этих свойств.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private static void InvalidateImage(DependencyObject d, DependencyPropertyChangedEventArgs e) { var uniformImage = (UniformImage)d; uniformImage.TopLeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Top, uniformImage); uniformImage.TopImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Top, uniformImage); uniformImage.TopRightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Top, uniformImage); uniformImage.LeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Center, uniformImage); uniformImage.CenterImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Center, uniformImage); uniformImage.RightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Center, uniformImage); uniformImage.BottomLeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Bottom, uniformImage); uniformImage.BottomImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Bottom, uniformImage); uniformImage.BottomRightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Bottom, uniformImage); } |
Недоступные извне свойства для хранения частей изображения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | protected static readonly DependencyProperty TopLeftImageProperty = DependencyProperty.Register( "TopLeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopLeftImage { get { return (ImageSource)GetValue(TopLeftImageProperty); } set { SetValue(TopLeftImageProperty, value); } } protected static readonly DependencyProperty TopImageProperty = DependencyProperty.Register( "TopImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopImage { get { return (ImageSource)GetValue(TopImageProperty); } set { SetValue(TopImageProperty, value); } } protected static readonly DependencyProperty TopRightImageProperty = DependencyProperty.Register( "TopRightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopRightImage { get { return (ImageSource)GetValue(TopRightImageProperty); } set { SetValue(TopRightImageProperty, value); } } protected static readonly DependencyProperty RightImageProperty = DependencyProperty.Register( "RightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource RightImage { get { return (ImageSource)GetValue(RightImageProperty); } set { SetValue(RightImageProperty, value); } } protected static readonly DependencyProperty BottomRightImageProperty = DependencyProperty.Register( "BottomRightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomRightImage { get { return (ImageSource)GetValue(BottomRightImageProperty); } set { SetValue(BottomRightImageProperty, value); } } protected static readonly DependencyProperty BottomImageProperty = DependencyProperty.Register( "BottomImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomImage { get { return (ImageSource)GetValue(BottomImageProperty); } set { SetValue(BottomImageProperty, value); } } protected static readonly DependencyProperty BottomLeftImageProperty = DependencyProperty.Register( "BottomLeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomLeftImage { get { return (ImageSource)GetValue(BottomLeftImageProperty); } set { SetValue(BottomLeftImageProperty, value); } } protected static readonly DependencyProperty LeftImageProperty = DependencyProperty.Register( "LeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource LeftImage { get { return (ImageSource)GetValue(LeftImageProperty); } set { SetValue(LeftImageProperty, value); } } protected static readonly DependencyProperty CenterImageProperty = DependencyProperty.Register( "CenterImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource CenterImage { get { return (ImageSource)GetValue(CenterImageProperty); } set { SetValue(CenterImageProperty, value); } } |
Метод GetCroppedPart() будет рассчитывать и возвращать нужный кусок изображения. За непосредственно нарезку будет отвечать встроенный в .NET класс CroppedBitmap, на вход конструктора которого подаются координаты региона изображения и его размеры.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | private static ImageSource GetCroppedPart(AlignmentX alignmentX, AlignmentY alignmentY, UniformImage uniformImage) { ImageSource imageSource = uniformImage.Source; if (imageSource == null ) return null ; double totalWidth = imageSource.Width; double totalHeight = imageSource.Height; Thickness staticArea = uniformImage.StaticArea; if (totalWidth <= 0 || totalHeight <= 0) return null ; // Предопределенные размеры double topHeight = staticArea.Top; double centerHeight = totalHeight - (staticArea.Top + staticArea.Bottom); double bottomHeight = staticArea.Bottom; double leftWidth = staticArea.Left; double centerWidth = totalWidth - (staticArea.Left + staticArea.Right); double rightWidth = staticArea.Right; // Предопределенные отступы double centerTopMargin = staticArea.Top; double bottomTopMargin = totalHeight - staticArea.Bottom; double centerLeftMargin = staticArea.Left; double rightLeftMargin = totalWidth - staticArea.Right; // Расчет позиции и размера региона в зависимости от его выравнивания double topMargin = 0; double leftMargin = 0; double width = 0; double height = 0; switch (alignmentX) { case AlignmentX.Left: width = leftWidth; break ; case AlignmentX.Center: leftMargin = centerLeftMargin; width = centerWidth; break ; case AlignmentX.Right: leftMargin = rightLeftMargin; width = rightWidth; break ; } switch (alignmentY) { case AlignmentY.Top: height = topHeight; break ; case AlignmentY.Center: topMargin = centerTopMargin; height = centerHeight; break ; case AlignmentY.Bottom: topMargin = bottomTopMargin; height = bottomHeight; break ; } if (height <= 0 || width <= 0) return null ; if (topMargin < 0) topMargin = 0; if (leftMargin < 0) leftMargin = 0; if (height + topMargin > totalHeight) height = totalHeight - topMargin; if (width + leftMargin > totalWidth) width = totalWidth - leftMargin; return new CroppedBitmap( (BitmapSource)imageSource, new Int32Rect(( int )leftMargin, ( int )topMargin, ( int )width, ( int )height)); } |
На этом всё! Пример использования:
1 2 3 4 5 6 7 8 | < Window x:Class = "UniformImageNamespace.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "clr-namespace:UniformImageNamespace" > < local:UniformImage Source = "button.png" StaticArea = "30" /> </ Window > |
Теперь можем менять пропорции изображения не переживания за его вид.
Исходный код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | < UserControl x:Class = "UniformImageNamespace.UniformImage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" > < UserControl.Template > < ControlTemplate > < Grid SnapsToDevicePixels = "True" > < Grid.RowDefinitions > < RowDefinition Height = "Auto" /> < RowDefinition /> < RowDefinition Height = "Auto" /> </ Grid.RowDefinitions > < Grid.ColumnDefinitions > < ColumnDefinition Width = "Auto" /> < ColumnDefinition /> < ColumnDefinition Width = "Auto" /> </ Grid.ColumnDefinitions > < Image Grid.Row = "0" Grid.Column = "0" Stretch = "None" Source = "{Binding TopLeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "0" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding TopImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "0" Grid.Column = "2" Stretch = "None" Source = "{Binding TopRightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "1" Grid.Column = "0" > < Border.Background > < ImageBrush ImageSource = "{Binding LeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Border Grid.Row = "1" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding CenterImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Border Grid.Row = "1" Grid.Column = "2" > < Border.Background > < ImageBrush ImageSource = "{Binding RightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "2" Grid.Column = "0" Stretch = "None" Source = "{Binding BottomLeftImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> < Border Grid.Row = "2" Grid.Column = "1" > < Border.Background > < ImageBrush ImageSource = "{Binding BottomImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Border.Background > </ Border > < Image Grid.Row = "2" Grid.Column = "2" Stretch = "None" Source = "{Binding BottomRightImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" /> </ Grid > </ ControlTemplate > </ UserControl.Template > </ UserControl > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace UniformImageNamespace { public partial class UniformImage : UserControl { public static readonly DependencyProperty StaticAreaProperty = DependencyProperty.Register( "StaticArea" , typeof (Thickness), typeof (UniformImage), new PropertyMetadata(InvalidateImage) ); public Thickness StaticArea { get { return (Thickness)GetValue(StaticAreaProperty); } set { SetValue(StaticAreaProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( "Source" , typeof (ImageSource), typeof (UniformImage), new PropertyMetadata(InvalidateImage) ); public ImageSource Source { get { return (ImageSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } public UniformImage() { InitializeComponent(); } protected static readonly DependencyProperty TopLeftImageProperty = DependencyProperty.Register( "TopLeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopLeftImage { get { return (ImageSource)GetValue(TopLeftImageProperty); } set { SetValue(TopLeftImageProperty, value); } } protected static readonly DependencyProperty TopImageProperty = DependencyProperty.Register( "TopImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopImage { get { return (ImageSource)GetValue(TopImageProperty); } set { SetValue(TopImageProperty, value); } } protected static readonly DependencyProperty TopRightImageProperty = DependencyProperty.Register( "TopRightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource TopRightImage { get { return (ImageSource)GetValue(TopRightImageProperty); } set { SetValue(TopRightImageProperty, value); } } protected static readonly DependencyProperty RightImageProperty = DependencyProperty.Register( "RightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource RightImage { get { return (ImageSource)GetValue(RightImageProperty); } set { SetValue(RightImageProperty, value); } } protected static readonly DependencyProperty BottomRightImageProperty = DependencyProperty.Register( "BottomRightImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomRightImage { get { return (ImageSource)GetValue(BottomRightImageProperty); } set { SetValue(BottomRightImageProperty, value); } } protected static readonly DependencyProperty BottomImageProperty = DependencyProperty.Register( "BottomImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomImage { get { return (ImageSource)GetValue(BottomImageProperty); } set { SetValue(BottomImageProperty, value); } } protected static readonly DependencyProperty BottomLeftImageProperty = DependencyProperty.Register( "BottomLeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource BottomLeftImage { get { return (ImageSource)GetValue(BottomLeftImageProperty); } set { SetValue(BottomLeftImageProperty, value); } } protected static readonly DependencyProperty LeftImageProperty = DependencyProperty.Register( "LeftImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource LeftImage { get { return (ImageSource)GetValue(LeftImageProperty); } set { SetValue(LeftImageProperty, value); } } protected static readonly DependencyProperty CenterImageProperty = DependencyProperty.Register( "CenterImage" , typeof (ImageSource), typeof (UniformImage) ); protected ImageSource CenterImage { get { return (ImageSource)GetValue(CenterImageProperty); } set { SetValue(CenterImageProperty, value); } } private static void InvalidateImage(DependencyObject d, DependencyPropertyChangedEventArgs e) { var uniformImage = (UniformImage)d; uniformImage.TopLeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Top, uniformImage); uniformImage.TopImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Top, uniformImage); uniformImage.TopRightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Top, uniformImage); uniformImage.LeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Center, uniformImage); uniformImage.CenterImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Center, uniformImage); uniformImage.RightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Center, uniformImage); uniformImage.BottomLeftImage = GetCroppedPart(AlignmentX.Left, AlignmentY.Bottom, uniformImage); uniformImage.BottomImage = GetCroppedPart(AlignmentX.Center, AlignmentY.Bottom, uniformImage); uniformImage.BottomRightImage = GetCroppedPart(AlignmentX.Right, AlignmentY.Bottom, uniformImage); } private static ImageSource GetCroppedPart(AlignmentX alignmentX, AlignmentY alignmentY, UniformImage uniformImage) { ImageSource imageSource = uniformImage.Source; if (imageSource == null ) return null ; double totalWidth = imageSource.Width; double totalHeight = imageSource.Height; Thickness staticArea = uniformImage.StaticArea; if (totalWidth <= 0 || totalHeight <= 0) return null ; // Предопределенные размеры double topHeight = staticArea.Top; double centerHeight = totalHeight - (staticArea.Top + staticArea.Bottom); double bottomHeight = staticArea.Bottom; double leftWidth = staticArea.Left; double centerWidth = totalWidth - (staticArea.Left + staticArea.Right); double rightWidth = staticArea.Right; // Предопределенные отступы double centerTopMargin = staticArea.Top; double bottomTopMargin = totalHeight - staticArea.Bottom; double centerLeftMargin = staticArea.Left; double rightLeftMargin = totalWidth - staticArea.Right; // Расчет позиции и размера региона в зависимости от его выравнивания double topMargin = 0; double leftMargin = 0; double width = 0; double height = 0; switch (alignmentX) { case AlignmentX.Left: width = leftWidth; break ; case AlignmentX.Center: leftMargin = centerLeftMargin; width = centerWidth; break ; case AlignmentX.Right: leftMargin = rightLeftMargin; width = rightWidth; break ; } switch (alignmentY) { case AlignmentY.Top: height = topHeight; break ; case AlignmentY.Center: topMargin = centerTopMargin; height = centerHeight; break ; case AlignmentY.Bottom: topMargin = bottomTopMargin; height = bottomHeight; break ; } if (height <= 0 || width <= 0) return null ; if (topMargin < 0) topMargin = 0; if (leftMargin < 0) leftMargin = 0; if (height + topMargin > totalHeight) height = totalHeight - topMargin; if (width + leftMargin > totalWidth) width = totalWidth - leftMargin; return new CroppedBitmap( (BitmapSource)imageSource, new Int32Rect(( int )leftMargin, ( int )topMargin, ( int )width, ( int )height)); } } } |
Исходники на GitHub.