검색결과 리스트
글
격자 배경 그리기
목차
Canvas 를 사용할때, 간혹 배경을 모눈종이처럼 격자로 할 경우가 생깁니다. 손쉽게는 격자 패턴을 이미지로 만들어서 쓸 수 있지요. 하지만 이때 생기는 문제가 조금 있습니다. 만약 이 Canvas 를 Zoom 한다고 가정해 보죠. 선의 두깨는 항상 같으면 좋을듯 합니다. 모눈의 크기는 Zoom 에 따라 커지고 작아지는데 반하여, 선의 두깨는 같아야 한다는 이야깁니다.
보통 3D 를 다루는 툴의 컴퍼넌트들을 보면, 이런 방식입니다. Unity 나 3D Max 같은 툴들 말이죠.
이 경우, 격자 패턴을 배경으로 깔아 쓰는 방식은 적절하지 못합니다.
개요
FlottingGrid 라는 이름으로 격자가 들어간 Grid 를 만들어 보도록 하겠습니다.
코드의 핵심은 OnRender 를 override 하는 것입니다. 더불어 격자의 선 두깨, 선 색 등의 정보를 위해서 Property 를 몇개 추가하였습니다. Zoom 에 따른 변화들은 다음 포스팅에서 하도록 하고, 이번 포스팅에서는 격자만 그리도록 하겠습니다. 사실 아래 코드만 보고 나시면, Zoom 관련된 부분들은 직접 하실 수 있을거라고 생각됩니다. :)
아래 코드는 Zoom 과 Offset 등.. 기능을 추가하다가 중지한 것이라,, 관련 코드가 좀 섞여 있습니다 -_-;
양해 바랍니다.
[FlottingGrid]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SW.Common.Controls
{
public class FlottingGrid : Grid
{
public double ZoomRate
{
get { return (double) GetValue(ZoomRateProperty); }
set { SetValue(ZoomRateProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomRate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomRateProperty =
DependencyProperty.Register("ZoomRate", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
public int CellCount
{
get { return (int) GetValue(CellCountProperty); }
set { SetValue(CellCountProperty, value); }
}
// Using a DependencyProperty as the backing store for CellCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellCountProperty =
DependencyProperty.Register("CellCount", typeof(int), typeof(FlottingGrid), new FrameworkPropertyMetadata(8, FrameworkPropertyMetadataOptions.AffectsRender));
public double CellSize
{
get { return (double) GetValue(CellSizeProperty); }
set { SetValue(CellSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for CellSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellSizeProperty =
DependencyProperty.Register("CellSize", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(20.0, FrameworkPropertyMetadataOptions.AffectsRender));
public Brush GridBrush
{
get { return (Brush) GetValue(GridBrushProperty); }
set { SetValue(GridBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for GridBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridBrushProperty =
DependencyProperty.Register("GridBrush", typeof(Brush), typeof(FlottingGrid), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(80, 0, 0, 0)), FrameworkPropertyMetadataOptions.AffectsRender));
public Brush CellBrush
{
get { return (Brush) GetValue(CellBrushProperty); }
set { SetValue(CellBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for CellBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellBrushProperty =
DependencyProperty.Register("CellBrush", typeof(Brush), typeof(FlottingGrid), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(40, 0, 0, 0)), FrameworkPropertyMetadataOptions.AffectsRender));
public double GridBorder
{
get { return (double) GetValue(GridBorderProperty); }
set { SetValue(GridBorderProperty, value); }
}
// Using a DependencyProperty as the backing store for GridBorder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridBorderProperty =
DependencyProperty.Register("GridBorder", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(2.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double CellBorder
{
get { return (double) GetValue(CellBorderProperty); }
set { SetValue(CellBorderProperty, value); }
}
// Using a DependencyProperty as the backing store for CellBorder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellBorderProperty =
DependencyProperty.Register("CellBorder", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double GridOffsetX
{
get { return (double) GetValue(GridOffsetXProperty); }
set { SetValue(GridOffsetXProperty, value); }
}
// Using a DependencyProperty as the backing store for GridOffsetX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridOffsetXProperty =
DependencyProperty.Register("GridOffsetX", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double GridOffsetY
{
get { return (double) GetValue(GridOffsetYProperty); }
set { SetValue(GridOffsetYProperty, value); }
}
// Using a DependencyProperty as the backing store for GridOffsetY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridOffsetYProperty =
DependencyProperty.Register("GridOffsetY", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double ZoomCenterX
{
get { return (double) GetValue(ZoomCenterXProperty); }
set { SetValue(ZoomCenterXProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomCenterX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomCenterXProperty =
DependencyProperty.Register("ZoomCenterX", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.5, FrameworkPropertyMetadataOptions.AffectsRender));
public double ZoomCenterY
{
get { return (double) GetValue(ZoomCenterYProperty); }
set { SetValue(ZoomCenterYProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomCenterY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomCenterYProperty =
DependencyProperty.Register("ZoomCenterY", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.5, FrameworkPropertyMetadataOptions.AffectsRender));
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
double translatedZoomRate = this.ZoomRate;
//if (this.ZoomRate > 2.0) { translatedZoomRate = (this.ZoomRate % 2.0) + 1.0; }
//else if (this.ZoomRate < 0.5) { translatedZoomRate = (this.ZoomRate % 2.0) + 1.0; }
double scaledCellSize = this.CellSize * translatedZoomRate;
double scaledGridSize = scaledCellSize * this.CellCount;
double templateSize = scaledGridSize + (this.GridBorder / 2);
double offsetX = (this.ZoomCenterX * this.ActualWidth);
double offsetY = (this.ZoomCenterY * this.ActualHeight);
DrawingBrush imageBrush = new DrawingBrush() {TileMode = TileMode.Tile, Viewbox = new Rect(0, 0, templateSize, templateSize), Viewport = new Rect(offsetX + this.GridOffsetX, offsetY + this.GridOffsetY, templateSize, templateSize), ViewportUnits = BrushMappingMode.Absolute, ViewboxUnits = BrushMappingMode.Absolute};
DrawingGroup drawingGroup = new DrawingGroup();
Brush cellBrush = this.CellBrush.Clone();
double opacity = 0.5 + (this.ZoomRate - 1.0);
if(opacity > 1.0)
{
opacity = 1.0;
}
if(opacity < 0.1)
{
opacity = 0.1;
}
cellBrush.Opacity = opacity;
Pen gridPen = new Pen(this.GridBrush, this.GridBorder);
Pen cellPen = new Pen(cellBrush, this.CellBorder);
using(DrawingContext context = drawingGroup.Open())
{
context.DrawLine(gridPen, new Point(scaledGridSize, 0), new Point(scaledGridSize, templateSize));
context.DrawLine(gridPen, new Point(0, scaledGridSize), new Point(templateSize, scaledGridSize));
for(int c = 1; c < this.CellCount; c++)
{
var offset = (double) ((int) (scaledCellSize * c));
context.DrawLine(cellPen, new Point(offset, 0), new Point(offset, templateSize));
}
for(int r = 1; r < this.CellCount; r++)
{
var offset = (double) ((int) (scaledCellSize * r));
context.DrawLine(cellPen, new Point(0, offset), new Point(templateSize, offset));
}
}
imageBrush.Drawing = drawingGroup;
dc.DrawRectangle(imageBrush, null, new Rect(0, 0, this.ActualWidth, this.ActualHeight));
}
}
}
'Microsoft > WPF' 카테고리의 다른 글
편집용 Canvas 만들기 (0) | 2014.11.16 |
---|---|
Expanding Canvas 만들기 2 (0) | 2014.11.16 |
Expanding Canvas 만들기 (2) | 2014.11.14 |
Drag Canvas 만들기 (0) | 2014.11.13 |
TreeView Template 을 통한 Canvas 만들기 (1) | 2014.11.12 |
RECENT COMMENT