이번에는 캔버스를 이용하여 그림판처럼 선과 원, 네모 등을 그려볼 것이다.


전체 xaml코드

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
<Window x:Class="_0312.paint"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_0312"
        mc:Ignorable="d"
        Title="paint" Height="600" Width="1000"
        MouseLeftButtonDown="canvas_MouseLeftButtonDown" MouseLeftButtonUp="canvas_MouseLeftButtonUp" MouseMove="canvas_MouseMove"
        MouseRightButtonDown="canvas_MouseRightButtonDown" MouseRightButtonUp="canvas_MouseRightButtonUp"
        >
    <Grid>
        <Border x:Name="canvasborder" BorderBrush="Pink" BorderThickness="3" CornerRadius="10" Margin="10,50,10,10">
            <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="489" Margin="7,7,0,0" VerticalAlignment="Top" Width="952">
            </Canvas>
        </Border>
 
        <Button x:Name="button_line" Content="선" HorizontalAlignment="Left" Margin="15,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_line_Click" />
        <Button x:Name="button_circle" Content="원" HorizontalAlignment="Left" Margin="80,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_circle_Click"/>
        <Button x:Name="button_rectangle" Content="네모" HorizontalAlignment="Left" Margin="145,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_rectangle_Click"/>
        <Button x:Name="button_erase" Content="지우개" HorizontalAlignment="Left" Margin="210,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_erase_Click"/>
        
        <Button x:Name="button_fileopen" Content="파일열기" HorizontalAlignment="Left" Margin="509,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_fileopen_Click" />
        <Button x:Name="button_jsonsave" Content="save" HorizontalAlignment="Left" Margin="739,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_jsonsave_Click" />
        <Button x:Name="button_jsonload" Content="load" HorizontalAlignment="Left" Margin="797,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_jsonload_Click" />
        
        <Button x:Name="button_paint" Content="배경색" HorizontalAlignment="Left" Margin="863,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_paint_Click"/>
        <Button x:Name="button_allerase" Content="전체삭제" HorizontalAlignment="Left" Margin="923,7,0,0" VerticalAlignment="Top" Width="50" Height="35" Click="button_allerase_Click"/>
        <Button x:Name="color_black" Content=" " HorizontalAlignment="Left" Margin="337,13,0,0" VerticalAlignment="Top" Width="25" Height="25" BorderBrush="Black" Background="Black" Click="color_black_Click" />
        <Button x:Name="color_red" Content=" " HorizontalAlignment="Left" Margin="369,13,0,0" VerticalAlignment="Top" Width="25" Height="25" BorderBrush="Black" Background="Red" Click="color_red_Click"/>
        <Button x:Name="color_blue" Content=" " HorizontalAlignment="Left" Margin="401,13,0,0" VerticalAlignment="Top" Width="25" Height="25" BorderBrush="Black" Background="Blue" Click="color_blue_Click"/>
        <Button x:Name="color_green" Content=" " HorizontalAlignment="Left" Margin="433,13,0,0" VerticalAlignment="Top" Width="25" Height="25" BorderBrush="Black" Background="green" Click="color_green_Click"/>
        <Button x:Name="color_yellow" Content=" " HorizontalAlignment="Left" Margin="465,13,0,0" VerticalAlignment="Top" Width="25" Height="25" BorderBrush="Black" Background="Yellow" Click="color_yellow_Click" />
        <ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="274,14,0,0" VerticalAlignment="Top" Width="50" SelectionChanged="comboBox_SelectionChanged">
            <ComboBoxItem>10</ComboBoxItem>
            <ComboBoxItem IsSelected="True">20</ComboBoxItem>
            <ComboBoxItem>30</ComboBoxItem>
        </ComboBox>
    </Grid>
</Window>
 
cs




기본 자료는 여기를 참고 →

https://docs.microsoft.com/ko-kr/dotnet/framework/wpf/graphics-multimedia/shapes-and-basic-drawing-in-wpf-overview



우선 선긋기부터.

캔버스를 하나 만들어준다. 그리고 마우스를 클릭하면 mClicked를 true로 바꾸고 현재위치를 prePosition에 넣는다.

1
2
3
4
5
 private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    mClicked = true;
    prePosition = e.GetPosition(canvas);
}
cs



그리고 마우스를 움직이면 새로운 위치를 받아 이전위치에서 현재위치까지의 선을 긋는다.

새로 그은 선을 캔버스의 자식으로 넣어주고 이전위치에 현재위치를 넣어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
    var nowPosition = e.GetPosition(canvas);
    if (mClicked)
    {
        // 선
        if (lineClicked)
        {
            Line line = new Line();
            line.X1 = prePosition.X;
            line.X2 = nowPosition.X;
            line.Y1 = prePosition.Y;
            line.Y2 = nowPosition.Y;
            line.Stroke = mycolor;
            line.StrokeThickness = 2;
            canvas.Children.Add(line);
 
            prePosition = nowPosition;
        }
cs

이런 식으로 작은 무수히 많은 선들로 그림판의 펜 기능을 만들 수 있다.





다음은 사각형 그리기

사각형의 위치는 margin을 이용해 시작점을 잡고, width와 height로 크기를 조절한다.


예외로는 시작점보다 현재위치의 x값이나 y값이 더 뒤로가게되면 너비,높이에 -1을 곱해 양수로 만들어주고

여백을 현재 x,y값으로 바꾸어주어 뒤쪽 방향으로도 정상적으로 사각형이 출력되도록 만든다.

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
// 사각형그리기
if (rectangleClicked)
{
    if (e.MouseDevice.LeftButton == MouseButtonState.Pressed)
    {
        Rectangle myrectangle = new Rectangle();
        
        myrectangle.Stroke = Brushes.Plum;
        myrectangle.Fill = mycolor;
        myrectangle.Opacity = 0.8;
 
        double left = prePosition.X;
        double top = prePosition.Y;
 
        double width = nowPosition.X - prePosition.X;
        double height = nowPosition.Y - prePosition.Y;
 
        if (nowPosition.X < prePosition.X)
        {
            left = nowPosition.X;
            width *= -1;
        }
        if (nowPosition.Y < prePosition.Y)
        {
            top = nowPosition.Y;
            height *= -1;
        }
 
        myrectangle.Margin = new Thickness(left, top, 00);
        myrectangle.Width = width;
        myrectangle.Height = height;
 
        canvas.Children.Remove(temprectangle);
        temprectangle = myrectangle;
        canvas.Children.Add(myrectangle);
    }
    else
        temprectangle = null;
}
cs

그리고 마우스를 이동할때마다 이전에 그렸던 사각형을 삭제하고 새로운 사각형을 생성함으로서

그림판처럼 생성될 사각형이 이동되는 것을 미리 확인 할 수있다. 마우스를 떼면 그자리에 그대로 사각형이 남는다.


지우개도 사각형과 같은 방식으로 색깔만 흰색으로 구현하였다.




다음은 원그리기

원도 사각형과 마찬가지이다.

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
// 원그리기
if (circleClicked)
{
    if (e.MouseDevice.LeftButton == MouseButtonState.Pressed)
    {
        Ellipse myellipse = new Ellipse();
        myellipse.Fill = mycolor;
        myellipse.StrokeThickness = 2;
        myellipse.Stroke = Brushes.LightSkyBlue;
        myellipse.Opacity = 0.8;
 
        double width = nowPosition.X - prePosition.X;
        double height = nowPosition.Y - prePosition.Y;
 
        double left = prePosition.X;
        double top = prePosition.Y;
 
        if (nowPosition.X < prePosition.X)
        {
            left = nowPosition.X;
            width *= -1;
        }
        if (nowPosition.Y < prePosition.Y)
        {
            top = nowPosition.Y;
            height *= -1;
        }
 
        myellipse.Margin = new Thickness(left, top, 00);
        myellipse.Width = width;
        myellipse.Height = height;
 
        canvas.Children.Remove(tempellipse);
        tempellipse = myellipse;
        canvas.Children.Add(myellipse);
    }
    else
        tempellipse = null;
}
cs




마우스를 떼면 변수와 나머지를 초기화해주어 동작을 하지않도록 한다.

1
2
3
4
5
6
private void canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    mClicked = false;
    temprectangle = null;
    tempellipse = null;
}
cs



이미지의 전체 삭제는 canvas.Children.Clear()를 하면 자식들이 전부 날아가서 캔버스가 초기화상태로 돌아간다.

배경화면도 투명으로 같이 초기화 해주었다.

1
2
3
4
5
private void button_allerase_Click(object sender, RoutedEventArgs e)
{
    canvas.Children.Clear();
    canvas.Background = Brushes.Transparent;
}
cs



그 외 도형선택과 색상변경은 아래와 같이 노가다로 만들었다. (좋지못한 예)

1
2
3
4
5
6
7
8
9
private void color_red_Click(object sender, RoutedEventArgs e)
{
    mycolor = Brushes.Red;
    color_black.Opacity = 1.0;
    color_red.Opacity = 0.5;
    color_blue.Opacity = 1.0;
    color_green.Opacity = 1.0;
    color_yellow.Opacity = 1.0;
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
private void button_line_Click(object sender, RoutedEventArgs e)
{
    lineClicked = true;
    circleClicked = false;
    rectangleClicked = false;
    eraseClicked = false;
 
    button_line.BorderBrush = Brushes.Red;
    button_circle.BorderBrush = Brushes.Black;
    button_rectangle.BorderBrush = Brushes.Black;
    button_erase.BorderBrush = Brushes.Black;
}
cs


지우개 크기는 콤보박스를 이용해 사이즈를 조절해주었다.

1
2
3
4
private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    erasesize = (comboBox.SelectedIndex + 1* 10;
}
cs


배경색도 그냥 캔버스의 Background를 바꾸면 끝이다.

1
2
3
4
5
private void button_paint_Click(object sender, RoutedEventArgs e)
{
    canvas.Background = mycolor;
    canvasborder.BorderBrush = Brushes.Pink;
}
cs


'프로그래밍 공부 > WPF' 카테고리의 다른 글

json 저장, 불러오기  (0) 2018.04.02
파일 불러오기, 이미지 출력 및 이동하기  (0) 2018.04.02
음악 재생하기 (MediaPlayer 사용)  (1) 2018.04.02
계산기 만들기  (0) 2018.04.02
WPF 시작하기  (0) 2018.04.02
Posted by misty_
,