GSI

VisualBrush 사용한 Grid 객체 렌더링 하기.


2D 형태의 객체를 3D 화면에 렌더링 하는 방법을 적을려고 합니다.
이때 사용하게 되는게 VisualBrush가 있는데요.
아래의 사용법을 가지고 처리해줄 수가 있습니다.


Window.Resource에 등록해서 할수도 있을듯 한데요.
이번 예제는 화면에 그려지고 있는 Grid를 3D 화면에 그려 보는것으로 마치겠습니다.

Start!!!

프로젝트를 생성합니다.
아래와 같이 WPF Application(*.exe)를 선택 합니다.
Name는 VisualBrushTest로 입력하고 Ok를 누릅니다.
사용자 삽입 이미지

Window를 선택하고 배경색은 검정 계통으로 보이게 합니다.
흰색일때는 왠지 테스트 하기가 불편한듯 해서 ^^.
사용자 삽입 이미지

VisualBrush로 사용할 Grid 객체를 선택하고 생성합니다.
사용자 삽입 이미지
아래와 같이 테스트를 위해서 간단한 사각형을 Grid에 추가 하고 Grid의 이름을 부여 합니다.
사용자 삽입 이미지

Viewport3D 객체를 추가 해야 하는데요.
사실 이게 직접 xaml을 코딩 하기도 좀 번거롭고 해서 Tools에 있는 Make Image 3D
를 사용해 보겠습니다.
"TestGrid"를 선택하고 Make Image 3D를 바로 하면 좋겠지만. 이게 되지를 않습니다.
사용자 삽입 이미지

그래서 아래와 같이 우측의 Project 탭을 선택하고 VisualBrushTest를 선택한 후에
마우스 오른쪽 버튼을 클릭해서 컨텍스트 메뉴를 뛰우게 됩니다.
그리고 나서 Add Existing Item...를 선택 하게 됩니다.
선택후에 나오는 Add Existing Item 창에서 샘플로 사용할 이미지를 선택 합니다.
이 이미지는 나중에 지워도 괜찮은거니 아무거나 해주심 됩니다. ^^
사용자 삽입 이미지

그림 샘플에 있는 이미지를 추가 해봤습니다. 아래와 같이 이미지가 추가 되었죠.
사용자 삽입 이미지

이 이미지를 선택한 후에 컨텍스트 메뉴에서 Insert를 해주면 화면에 표시가 되게 됩니다.
사용자 삽입 이미지

이제 Viewport3D를 만들어 보겠습니다.
Image 객체는 이 메뉴가 활성화 되어서 보이게 됩니다.
Tools>Make Image 3D...를 선택 합니다. 이제 Objects and Timeline 화면에 보시면
Image 가 Viewport3D로 되어 있는 것을 볼 수 있습니다.
중앙의 윈도우 화면의 이미지는 그대로 보이게 되죠.
트랜스폼이나 기타 조작을 해주지 않았으니 당연하겠죠 ^^.
사용자 삽입 이미지

화면을 3차원인거 처름 보이게 하기 위해서 조금 트랜스폼을 조작해 보겠습니다.
여기서는 방법이 몇가지 될수 있겠죠.
좌측의 메뉴를 이용해서 하는 방법을 우선 보겠습니다.
Camera Orbit 메뉴를 선택 하고 좌측의 Viewport3D를 선택하고 객체를 3차원으로
변형할 수 있습니다.
사용자 삽입 이미지
[참고] 위에서 보시는 이미지를 보면 Viewport3D의 화면 영역 안에서 clip되는걸
볼수 있습니다. 이것을 없애고 싶다면 아래의 체크 박스를 없애면 됩니다.
사용자 삽입 이미지

이제 샘플로 사용한 이미지를 없애고 위에서 작업한 Grid를 추가해 보겠습니다.
Design에서 XAML 페이지로 이동하고 나면 좀 많은 코드가 생기게 됩니다.
아까 "푸른언덕.jpg"를 추가 했으니 그쪽으로 가면 되겠죠...
사용자 삽입 이미지
위에서 보는 것과 같이 DiffuseMaterial.Brush에 VisualBrush를 붙여 보겠습니다.
사실 DiffuseMaterial 말고도 몇개 더 있다는 것을 3D를 해보신 분이라면 아실겁니다. ^^
자. 이제 아래와 같이 이 부분을 수정하게 됩니다. 우리가 아까 Grid의 이름을
TestGrid로 한거 기억 나시죠?. 아래와 같이 입력합니다.
사용자 삽입 이미지
아래와 같이 화면이 Grid와 같이 나오게 됩니다.
사용자 삽입 이미지

Blend 툴에서 Grid의 내용을 수정하거나 하면 동적으로 Viewport3D의 화면도
바뀌게 되어 있습니다.
보통 이게 동영상이나 기타반사 효과 또는 젖은 효과라고도 하던데요.
이런 트낌을 줄때 많이들 하게 되는거 같아요.

여기까지 해보신 분이라면 많은 생각이 될게 될거 같아요.
몇가지 개선 사항을 적어 볼까 합니다.

1. TestGrid를 Window.Resource에 추가 해서 화면에 보이지는 않지만 내부 데이터를
   접근하고 하면서 화면에는 Viewport3D 의 형태로 표현도 가능하죠.
2. 그리고 3DTools 라이브러리를 사용 하게 되면 Window Form도 여기에 붙여서
    3D 상에서의 윈도우 컨트롤이 가능하게 됩니다.

이거 말고도 다양한 효과를 줄 수 있을거 같아요.
이번 강좌는 여기까지 하고 3DTools를 이용한 외국 사이트의 내용을 나름대로
정리 해서 올릴까 합니다. 어쩔지 ^^.. 많은 의견 주세요.

Posted by gsi
:

MessageBox 사용하기

C# 2007. 9. 2. 13:24 |

//그냥 해당 글을 출력할때
MessageBox.Show("Closing called");

//해당 결과를 받아서 처리 하고 싶을때
string msg = "Data is dirty. Close without saving?";
MessageBoxResult result =
    MessageBox.Show(
        msg,
        "Data App",
        MessageBoxButton.YesNo,
        MessageBoxImage.Warning);
if (result == MessageBoxResult.No)
{
    // If user doesn't want to close, cancel closure
    e.Cancel = true;
}
Posted by gsi
:

DB는 초급이라.. 아무래도 다 생소하다 ^^..

우선 로그인 페이지를 만들어 볼까 하는데.
필요한게 ID, Pass, LoginButton 이 필요할거 같다.

ID와 Pass를 입력한 후에 LoginButton을 클릭 하면,
해당 ID를 where 절에 포함해서 ID, Pass를 받아 오면 될거 같다.

OleDbDataAdapter 구문에 쿼리를 넣어서 받아 오는 코드이다.

OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT ID, Pass FROM Login WHERE ID='aaa';", conn);
위에서 보는 것과 같이 aaa라는 사용자의 ID, Pass 내용을 가져 오는 구문이다.
Posted by gsi
:

DB명 : member.mdb
테이블 이름 : BookTable
테이블 내용 : ID(일련번호), Title(텍스트)

cs 파일 내용

네임 스페이스

using System.Data.OleDb;
(이것만 선언 해서 안되는거 같네욤, References 에 "System.Data"를
추가해주어야 합니다.)

OleDbConnection, OleDbDataAdapter 처리
string mdbFile = Path.Combine(AppDataPath, "d:\\member.mdb");
string connString = string.Format(
                "Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}", mdbFile);
OleDbConnection conn = new OleDbConnection(connString);
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM BookTable;", conn);

DataSet 연결 (전역으로 만들어 놓는다.)

DataSet myDataSet;
adapter.Fill(myDataSet, "BookTable");

활용

ListBox에 연결시...

myListBox.DataContext = myDataSet;

... 나머지는 xaml에서 처리가능...

<StackPanel>
        <StackPanel.Resources>
            <c:IntColorConverter x:Key="MyConverter"/>

            <DataTemplate x:Key="BookItemTemplate">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="250" />
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Path=Title}" Grid.Column="0"
            FontWeight="Bold" />
                </Grid>
            </DataTemplate>
        </StackPanel.Resources>

        <ListBox Name="myListBox" Height="200"
      ItemsSource="{Binding Path=BookTable}"
      ItemTemplate  ="{StaticResource BookItemTemplate}"/>
        <Button Click="OnClick">Add Record</Button>
    </StackPanel>

foreach 문을 사용해서 비교 할때...

DataTable dt = myDataSet.Tables["BookTable"];
foreach (DataRow row in dt.Rows)
{
    string ss = row["Title"].ToString();
}
- "BookTable" 테이블 명이다.
- "Title" 컬럼 번호. (0, 1, 2, 인덱스도 가능하다.)

DataRow를 사용해서 Row 추가 할때...

DataTable myDataTable = myDataSet.Tables["BookTable"];
DataRow row = myDataTable.NewRow();
row["Title"] = "손병욱";
myDataTable.Rows.Add(row);  //<--이것은 DB랑은 상관없다.


위의 내용을 토대로 해서 기본 테이블에서 내용을 가져 와서 검색 하고
하는 등의 내용을 해결할 수 있을거 같다.
위의 내용을 토대로 로그인 페이지를 만들어 볼려고 한다.






 

Posted by gsi
:

Storyboard 를 사용한 TransformGroup를 C#에서 처리 하는 방법


Blend에서 Timeline을 생성하고 오브젝트를 움직이면 에니메이션 처리를 할수 있다.
가장 간단하게 하면서도 효과적인 에니메이션을 구현할 수 있다.

에니메이션 쪽을 보면 Transform에 여러개의 객체가 붙을수 있다.

만약 Button 의 이름이 btn이라고 하고 예로 들어 보겠다.

btn.RenderTransform 에 붙을수 있는 것은 아래와 같을 것이다.

btn.RenderTransform = new RotateTransform(0);
btn.RenderTransform = new ScaleTransform(1, 1);
btn.RenderTransform = new SkewTransform(0, 0);
btn.RenderTransform = new TranslateTransform(10, 10);



그리고 위의 4개를 통합해서 사용할 수 있는것으로 TransformGroup를 들수 있다.

...
btn.RenderTransform = tGroup;



위에서 보는 것과 같이 5개의 속성을 연결 시킬 수가 있다.

몇가지 테스트를 해봤고,
RenderTransform에 TransformGroup를 붙이지 않고 개별적인
속성을 붙이게 되면 Animation할때도 그 속성에 대한 정보만 제어 할 수 있다.
즉, 이동만을 하고 싶은 것이라면 TranslateTransform만 연결해서 사용하면 될듯 하다.

구체적인 예제를 만들지는 않았지만.
궁금하면 질문 해주기 바랍니다.

아래의 코드는 4개의 속성 정보를 다 연동하고 난 후에 제어 하는
아주 심플한 예제 입니다.
물론 자료형을 사용해서 배열로 정보들을 저장하고 조금더
깔끔하고 효과적으로 처리 할 수도 있을거 같다.
그리고 현재 코드는 2D의 처리만 가능한 것이다.

-------------------------------------------------------------------------
전제조건 :
Blend에서 기본 오브젝트를 우선 제작한다.
1. 버튼 두개를 제작한다.
2. 텍스트 박스를 하나 만든다. 이름은 TextBox2로 지정한다.

자.. 프로그램 코드는 *.cs 파일에서만 구동되므로 바로 설명 하겠다.

제어에 필요한 변수를 아래와 같이 만들었습니다.

//에니메이션 이름에 사용할 것을 지정
private string aniTrans = "_aniTrans";
private string aniSkew = "_aniSkew";
private string aniScale = "_aniScale";
private string aniRotate = "_aniRotate";

//트랜스폼을 제어 하기 위해서 변수를 설정
private TransformGroup group;
private RotateTransform rotate;
private ScaleTransform scale;
private SkewTransform skew;
private TranslateTransform trans;

//스토리 보드의 속성정보를 저장할 변수 설정
private Storyboard transStoryX;
private Storyboard transStoryY;
private Storyboard RotateStory;

//에니메이션 변수 설정
private DoubleAnimation myTransX;
private DoubleAnimation myTransY;
private DoubleAnimation myRotate;

public Window1()
{
    ...
    group = new TransformGroup();
    rotate = new RotateTransform(0);
    scale = new ScaleTransform(1, 1);
    skew = new SkewTransform(0, 0);
    trans = new TranslateTransform(50, 50);

    group.Children.Add(rotate);
    group.Children.Add(scale);
    group.Children.Add(skew);
    group.Children.Add(trans);

    this.RegisterName(aniTrans, trans);
    this.RegisterName(aniSkew, skew);
    this.RegisterName(aniScale, scale);
    this.RegisterName(aniRotate, rotate);

    TextBox2.RenderTransform = group;
}

private void OnLoaded(object sender, RoutedEventArgs e)
{
    myTransX = new DoubleAnimation();
    myTransY = new DoubleAnimation();
    myRotate = new DoubleAnimation();

    Storyboard.SetTargetName(myTransX, aniTrans);
    Storyboard.SetTargetProperty(myTransX, new PropertyPath(TranslateTransform.XProperty));
    Storyboard.SetTargetName(myTransY, aniTrans);
    Storyboard.SetTargetProperty(myTransY, new PropertyPath(TranslateTransform.YProperty));
    Storyboard.SetTargetName(myRotate, aniRotate);
    Storyboard.SetTargetProperty(myRotate, new PropertyPath(RotateTransform.AngleProperty));

    transStoryX = new Storyboard();
    transStoryX.Children.Add(myTransX);
    transStoryY = new Storyboard();
    transStoryY.Children.Add(myTransY);
    RotateStory = new Storyboard();
    RotateStory.Children.Add(myRotate);
}

private void OnClick(object sender, RoutedEventArgs e)
{
    myTransX.To = -50;
    myTransX.Duration = new Duration(TimeSpan.FromMilliseconds(800));
    myTransY.To = -50;
    myTransY.Duration = new Duration(TimeSpan.FromMilliseconds(800));
    myRotate.To = -50;
    myRotate.Duration = new Duration(TimeSpan.FromMilliseconds(800));

    transStoryX.Begin(this);
    transStoryY.Begin(this);
    RotateStory.Begin(this);
}

private void OnClick2(object sender, RoutedEventArgs e)
{
    myTransX.To = 120;
    myTransX.Duration = new Duration(TimeSpan.FromMilliseconds(800));
    myTransY.To = 150;
    myTransY.Duration = new Duration(TimeSpan.FromMilliseconds(800));
    myRotate.To = 270;
    myRotate.Duration = new Duration(TimeSpan.FromMilliseconds(800));

    transStoryX.Begin(this);
    transStoryY.Begin(this);
    RotateStory.Begin(this);
}


아.. 내용이 많아 지네욤..

우선 한번만 지정하는 부분과 매번 동작상황에 맞게 값을 입력해줘야 하는것으로
세분화를 해봤습니다.
Windows1()에 있는 내용은 기본적으로 설정할 부분이며,

OnClick(), OnClick1() 에는 버튼에 대한 이벤트 입니다.
아무래서 여기서 From, To, Duration을 설정해 줘야 할듯 합니다.

아. 참고로 From을 설정하지 않으면 현재 위치에서 To까지의 진행을
하게 됩니다. 처음에 이게 궁금했는데 아주 편한듯 합니다. ^^

그리고 Storyboard 여기 설정하는 부분이 솔직이 아직 다 이해가 가질 않습니다.
위의 코드 처름 하나하나의 속성을 처리 하는 부분에서는 별다른
문제가 없지만 path 형태의 처리는 아직 공부 중입니다. ^^

음.. 대충 설명은 이것으로 마치겠습니다.
샘플 받아서 실행해 보시고 분석해 보시면 더 도움 될거 같아욤.
아무쪼록 좋지 않은 내용을 봐주셔서 감사 ^^

Posted by gsi
: