블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

With recent Unity versions (2020, 2021 and 2022) Flutter Android builds will take a lot longer, because it also has to compile the IL2CPP code from Unity.

From the Readme:

  • Android builds takes forever to complete Unity 2022.1.*, remove these lines from unityLibrary/build.gradle filecommandLineArgs.add("--enable-debugger")
    commandLineArgs.add("--profiler-report")
    commandLineArgs.add("--profiler-output-file=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_conv.traceevents")

Here is some testing to check how to speed things up.

Unity settings

IL2CPP Code Generation

  • Build Settings -> IL2CPP Code Generation: select Faster (smaller) builds instead of Faster runtime.
  • Or C# EditorUserBuildSettings.il2CppCodeGeneration = UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize;

C++ compiler configuration

  • In Player settings -> Other settings -> configuration, select Debug.
  • Or C# PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, Il2CppCompilerConfiguration.Debug);

Disable script debugging

Don't bother setting this in the Unity settings, it will be overridden by the build script.
Assets/FlutterUnityIntegration/Editor/build.cs
In the function DoBuildAndroid() remove the line enabling script debugging.
playerOptions.options = BuildOptions.AllowDebugging;
This is the same as removing commandLineArgs.add("--enable-debugger") from the build.gradle file after an export.

Measuring results

When you run a Flutter build, there are multiple IL2CPP stages that report their duration, with 2 sections taking far longer than all others.
We can compare these build durations when using different settings in Unity.

Log of the slow armv7 and arm64 sections

Starting: Z:\fuw20221.1.0+7\2021\example\android\unityLibrary\src\main\Il2CppOutputProject\IL2CPP\build\deploy\bee_backend\win-x64\bee_backend.exe --profile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/backend_profiler1.traceevents" --stdin-canary --dagfile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/bee.dag" --continue-on-failure --dagfilejson="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/bee.dag.json" FinalProgram
WorkingDir: Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate
ExitCode: 0 Duration: 2m:04s
Build succeeded with 553 successful nodes and 0 failed ones

Starting: Z:\fuw20221.1.0+7\2021\example\android\unityLibrary\src\main\Il2CppOutputProject\IL2CPP\build\deploy\bee_backend\win-x64\bee_backend.exe --profile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/backend_profiler1.traceevents" --stdin-canary --dagfile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/bee.dag" --continue-on-failure 
--dagfilejson="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/bee.dag.json" FinalProgram
WorkingDir: Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate
ExitCode: 0 Duration: 2m:03s
Build succeeded with 553 successful nodes and 0 failed ones
 

Results

The exact durations here aren't important, as this will be different of every computer and project setup.
This is after flutter clean and a fresh Unity export. Any subsequent runs will be faster because of caching.

Flutter build apk, with an export from Unity 2021.3.5f1 in android/unityLibrary on Windows 10.

Settingarmv7 durationarm64 duration

example project 2m:04s 2m:03s
1 - Code generation (faster builds) 1m:41s 1m:38s
2 - Compiler configuration (debug) 45s 43s
3 - No script debugging 30s 30s
1 + 2 35s 34s
1 + 2 + 3 23s 25s

Conclusion

My advice is to add this to the build script in DoBuildAndroid() for any test or debug builds, remove it for final release builds.

//Assets/FlutterUnityIntegration/Editor/build.cs
bool isReleaseBuild = false;

#if UNITY_2022_1_OR_NEWER
    PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, isReleaseBuild ? Il2CppCompilerConfiguration.Release : Il2CppCompilerConfiguration.Debug);
    PlayerSettings.SetIl2CppCodeGeneration(UnityEditor.Build.NamedBuildTarget.Android, UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize);
#elif UNITY_2021_2_OR_NEWER
    PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, isReleaseBuild ? Il2CppCompilerConfiguration.Release : Il2CppCompilerConfiguration.Debug);
    EditorUserBuildSettings.il2CppCodeGeneration = UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize;
#endif
 

If it doesn't affect your workflow, disable script debugging.

// playerOptions.options = BuildOptions.AllowDebugging;

And if you are developing on an arm64 device anyway, temporarily remove the armv7 build target from the Unity player settings.

 

 

[출처] https://github.com/juicycleff/flutter-unity-view-widget/issues/643

 

[Android] Tips to reduce android build times. · Issue #643 · juicycleff/flutter-unity-view-widget

With recent Unity versions (2020, 2021 and 2022) Flutter Android builds will take a lot longer, because it also has to compile the IL2CPP code from Unity. From the Readme: Android builds takes fore...

github.com

 

반응형
Posted by blueasa
, |

[추가] 2024-03-06

2024년 기준 폰 스펙이 많이 올라와서 이젠 최신폰에서 326으로는 깨지는게 보인다.

그래서 아이폰 최신인 아이폰15(460ppi)에 맞추기로 했다.

→ Target DPI : 326 -> 460으로 변경

----

 

1. Player Settings - Resolution and Presentation - Resolution Scaling

    1.1. Disabled → Fixed DPI로 변경

    1.2.1 Target DPI(Default:30) 280으로 변경(iPhone 13에서도 깨지는지 모르겠다고 함)

    1.2.2 Target DPI 326으로 변경(iPhone XR/11 : 326) : 나는 아이폰 기준 맞추기 위해 326으로 변경함

        [참조] https://techblog.kayac.com/unity-fixed-dpi

Fixed DPI : 280

 

2. Android 6.0(API Level 23) 이상이면 Android Texture Format : ASTC 사용 권장

    2.1. iPhone은 이전부터 ASTC 사용 권장하기 때문에 Android 6.0 이상이면 양쪽 플랫폼 동일하게 ASTC 사용가능 할 듯

 

 

[출처] 게임코디-선후님

 

 

반응형
Posted by blueasa
, |

[링크] https://blog.naver.com/dj3630/221461311485

 

[유니티 기초] - Audio

적절한 배경음악이나 효과음만으로도 게임의 분위기가 크게 좌우된다. 유니티는 사운드 미들웨어인 FMO...

blog.naver.com

 

반응형
Posted by blueasa
, |

gamebryotip

Gamebryo / 2011. 3. 21. 20:14
맵 처리

* 그라운드 매쉬 * 지형높이 : 아바타 좌표에서 높은 높이에서 Picking 함. (테스트 완료)

* 오브젝트 충돌 : 겜브리오 충돌시스템 사용함. MAX에서 충돌박스 심기

* 지형위 오브젝트로 이동 Issue : Picking 기법 체크

* 정적오브젝트

  • 애니메이션 오브젝트 테스트 완료

* 동적맵구성

  • Issue : 레벨 에디팅
아바타

* 충돌박스

  • 큐브타입으로 심어서 테스트 완료

* 애니메이션

  • Max에서 Gamebryo Animation Manager를 통한 텍스트키 심기
    • Gamebryo Tools에서 Animation Manager아이콘을 클릭한다.
    • Sequence Tags란에 속해있는 Extra Info Tags란에서 설정하면 된다.
    • Key Text에서 텍스트 키 이름을 입력하고 Tag Time에서 원하는 시간을 입력한 후 Add Info Tag버튼을 누르면 텍스트키가 등록된다.

* 파츠

* 도구장착

익스포트

* Max의 dummy는 플러그인에서 성능 향상 쪽을 확인해서 Off해줄것 ( 자식없는것 없애는 게 있음 )

  • Scene Graph Optimization 더블클릭 할것

* Max hierarchy와 똑같은 구조의 Scene graph Export하기

  • Scene Graph Optimization에서 Remove childless nodes, Remove single-child nodes, Merge sibling nodes, Merge sibling NiTriShape objects 4개의 항목을 off한다.

메뉴얼_위치_artist_s_guide_-_gamebryo_3ds_max_plug-in_-_3ds_max_plug-in_tutorials_-_changing_optimization_setting_in_3ds_max}

* 애니메이션 매니저 사용하기 ⇒ .kf .kfm 파일을 뽑기 위해선 애니메이션 매니저를 반드시 써야한다. 메뉴얼_위치_artist_s_guide_-_gamebryo_3ds_max_plug-in_-_3ds_max_plug-in_tutorials_-_simple_animation_sequence}

* Gamebryo에서 캐릭터가 정면( X축 양의방향 )을 향하게 하려면 Max에선 캐릭터가 Y축 음의 방향을 바라보게 한 후 익스포트 해야한다.

* File Export Script관련( .nif .kf .kfm )

  • Controller Extractor
    • Plug-in 중에 Controller Extractor를 찾아 더블클릭하면 관련 옵션을 수정할 수 있다.
    • 메뉴얼을 보면 시퀀스 추출 방법 선택, KF file naming convention, KFM file 생성 유무, 시퀀스간 트랜지션 셋팅 등을 설정할 수 있다.
    • @ Root같은 .kf 파일이름에 Actor Roots Name(character name)을 집어 넣지 않으려면 KF File Naming Convention란에서 Use character name 항목을 비활성화 시키면 된다.

메뉴얼_위치_reference_-_toollibs_-_tool_plug-ins_-_controller_extractor}

* Hidden object 제거하고 Export하는 방법

  • Process Script에서 Edit버튼을 누르고 Remove Hidden Object Plug-in을 추가
  • Move up 버튼을 눌러 최상위로 올림
  • Plug-in 중에 Scene Graph Optimization을 더블클릭해서 에디트창을 오픈
  • Remove childless nodes 체크( Remove Hidden Object Plug-in을 추가 함으로써 Hidden Object의 Geometry는 모두 Export되지 않는다. Node의 자식이 없다는 건 Geometry가 없다는 것과 상통하므로 자식이 없는 불필요한 Node들은 제거해서 Export한다. 단, Leaf Node나 단일 Node가 필요한 Dummy일 경우에는 이 옵션을 체크 안 하거나 유저지정속성을 통해 Node가 유지되도록 해야한다. )

* Optimization을 통해 제거 될 수 있는 Node들을 보존하는 방법

  • Scene Graph Optimization 내 Remove childless nodes나 Remove single-child nodes 항목을 체크하면 필요 없는 Node들을 제거하게 된다. 그러나 특정 문자열을 통해 노드가 제거하지 못하게 보존하는 방법이 있다.
  • 해당 오브젝트 속성( Object Properties )을 열면 4번째 탭에 User Defined라는 항목이 있다. 항목을 선택해 공란에 “NiOptimizeKeep”라는 특수 문자열을 넣으면 된다.

* 파츠 아이템( 옷, 안경등 신체의 직접적으로 접촉되는 것들, 스킨정보 必 ) Export

  • 캐릭터에 아이템을 장착한 상태에서 Export하면 된다.
  • 장착한 아이템 빼놓고 나머지 것들은 모두 Hidden Object로 설정한다.
  • 캐릭터에 biped정보도 함께 Export한다.
  • 캐릭터와 아이템은 따로 링크를 시키지 않는다.

* 파츠 아이템( 손에 붙이는 무기나 오브젝트, 현재는 스킨정보 無 ) Export

  • 캐릭터 biped정보는 필요 없고 순수 아이템 정보만 Export하면 된다.
  • 캐릭터 본( 예시: 손, 발 )과 연결될 아이템 부위에 Dummy를 하나 만들어 아이템에 링크 시킨다.
  • 원점에 위치하여 Export한다.

* 파츠 관련 이슈

  • 예를들어 손에 주전자를 Attach한다고 할 때, 현 시점(2008.09.24)에서는 본에 직접적으로 Attach를 하지만 차후에는 손에 Dummy를 만들어 붙일 수 있게 변경 할 것이다.
  • 손 <ATTACH> Dummy - 주전자 ==============⇒ 손 - Dummy <ATTACH> Dummy - 주전자
  • 현재 손에 붙이는 무기나 오브젝트는 스키닝 정보가 없는 것들만 가능하지만 차후에는 스키닝 정보가 있는 것들도 지원해야 할 것이다.

* 각 애니메이션 별 Loop속성 설정 방법

  • 캐릭터 애니메이션(kfm)
    • Animation Manager에서 Loop Sequence란에 박스 체크
  • 텍스처 좌표 애니메이션( ifl파일을 이용했을 경우 )
    • Material Editor에서 맵핑 된 텍스처(ifl파일)를 선택
    • 선택된 맵 에디터에서 Time란 안에 End Condition란에서 선택한 후 체크
  • 오브젝트 트랜스폼 애니메이션
    • Max 메인메뉴에서 Graph Editors → Track View - Curve Editor 선택하면 에디터 창이 열림
    • 메뉴에서 Controller → Out-of-Range Types 선택하면 에디터 창이 열림
    • Loop 그래프 밑에 버튼 2개를 모두 활성화 시킴
    • 파티클 애니메이션
    • 파티클 오브젝트를 선택하고 Max 기본 툴바에서 Modify를 선택
    • 여러가지 파티클에 관련된 파라미터란들이 나오는데 스크롤을 쭈욱내리면 제일 밑에 Gamebryo Export Params란이 있다. 거기 안에 Simulation Options란에서 선택한 후 체크
  • Loop속성이 잘 적용됐는지 확인 하는 방법
  • Max에서 애니메이션 작업을 한 후 Asset Viewer에서 애니메이션을 돌려보면 보통 Loop를 하게 된다. 그러나 이걸 100% 신뢰해서는 안 된다. Asset Viewer가 내부적으로 Loop를 돌리기 때문이다( 추측 -_-;;; ) 그러므로 정작 App에서는 Loop가 안 될수 있다. Loop속성이 On이 되었는지 정확히 판단하려면 Time Controller를 뒤져봐야 한다.
  • Asset Viewer의 Scene Graph Tree에서 해당하는 Geometry를 선택하면 노드에 관한 정보가 나온다. 보통 부모노드에 트랜스폼 정보가 있으므로 부모노드의 Time Controller 정보를 보면 된다.
  • 해당 하는 Controller를 더블클릭 해서 Basic Info란의 Cycle Type을 확인해서 LOOP( Max에서 Loop를 On했을 경우)라고 써 있으면 정상적으로 익스포팅 된 것이다. 참고로 텍스처 좌표 애니메이션은 Max에서 키를 안 잡기 때문에 Time Controller에 아무 정보도 기입되어 있지 않다.

카메라

* Gamebryo좌표계랑 Max좌표계는 같은 오른손 좌표계를 쓰지만 방향을 나타내는 카메라 뷰 벡터들( Up, Direction, Right )은 서로 다르다.

  • Gamebryo( Up : 양의 Y축, Dir : 양의 X축, Right : 양의 Z축 )
  • Max( UP : 양의 Z축, Dir : 양의 Y축, Right : 양의 X축 )
  • 그러므로 맥스에서 익스포터한 오브젝트들이 정상적으로 보이게 하려면 카메라를 X축으로 -90도 Z축으로 90도 회전해야 한다.

메뉴얼_위치_programmers_s_guide_-_general_topics_-_programming_for_scene_rendering_-_viewing_geometry_-_cameras}

이펙트

* 빌보드 * 파티클

  • Issue : Max 기반의 Effect 작업방식 확인 필요 .
물리
리소스 관리
게임로직


출처 :  
http://joygram.org/wiki/doku.php?id=gamebryotip
반응형

'Gamebryo' 카테고리의 다른 글

[펌] 게임브리오 관련..  (0) 2011.07.25
Gamebryo Default Coordinate  (0) 2011.06.17
[Link] 게임브리오 강의  (0) 2011.03.28
Posted by blueasa
, |

C++ 을 배운지 꽤 오래 되었지만, 아직도 코드 리뷰를 통해 다른 개발자들의 코드를 볼 때면 한숨이 나오는 경우가 많습니다.

이런 경우가 반복되다 보니, 예전에 몇 가지 코딩 규칙 비슷하게 만들어놓은 자료가 있어 포스팅해 봅니다.  자료가 만들다 말아 내용이 중구난방이네요..  앞으로도 계속 내용 보강해 나가겠습니다.

 

    포인트 핸들 및 윈도우 핸들 체크

-       함수로 전달된 포인터 인자나, new 로 생성한 포인터 등 모든 포인터는 사용하기 직전 포인터 검사를 수행

-       가급적 STL 컨테이너를 사용해서 아예 포인터를 사용하지 않는 것이 정신건강에 이롭다. (STL 자체적으로 메모리 생성 및 소멸)

-       메모리 LEAK 을 막기 위해 SMART POINT 와 같은 Wrapper 클래스를 만든다.

-       (윈도우 프로그램의 경우)윈도우 API 호출 직전 항상 윈도우 핸들이 정상인지 IsWindow 와 같은 함수로 검사한다.

 

    DRY(Don't Repeat Your Code)원칙

-       같은 코드를 여기 저기 중복해서 사용하지 말아야 한다. (☞ 실용주의 프로그래머 참고). 중복해서 사용할 경우 코드 량이 늘어날 뿐만 아니라 유지보수 cost 가 같이 늘어 나고, 추후 추가/개선/변경 등의 요구사항으로 인한 모듈 수정 시 여러 소스를 함께 수정해야 한다.

-       동일한 코드를 공용 루틴(함수)으로 개발 – 2~3줄 짜리 복잡한 if 문도 bool 를 리턴 하는 함수로 개발(Refactoring 참고)

 

    클래스간 종속성 최소화

-       대규모 프로젝트에서는 공통모듈이 변경되어도 이를 사용하는 모듈이 문제가 없도록 반드시 공통모듈은 인터페이스 기반(데이터가 없는, virtual 가상함수로만 구성된)으로 구현한다. (The C++ Programming Language 참고)

-       A 클래스 → B 클래스 → C 클래스를 사용할 경우 각 클래스는 자기가 직접 다루는 클래스(A B, B C) 만 알아야 한다. A 클래스는 C 클래스를 직/간접적으로 include 해서는 안되며 C 클래스의 변경으로 인해 A 클래스가 컴파일 되어서는 안 된다. A 클래스가 C 를 직접 접근할 경우가 있다면 B 클래스에 위임함수를 만들어 해결한다. (☞ 실용주의 프로그래머 참고)

-       B 클래스가 A 클래스로 어떤 데이터를 전달할 경우가 있다면(주로 이벤트 발생시 값을 전달하기 위해) A 클래스의 최소 인터페이스만을 B 클래스에 전달하여(COM 의 이벤트 소스 방식) 종속성을 최소화 한다. (Developer’s Workshop To COM and  ATL 3.0 참고)

 

    함수 인자 전달

-       함수의 인자는 최대 7개를 넘지 않아야 한다(Code Complete 2 참고)

-       클래스 인스턴스를 함수 인자로 넘겨서는 안 된다(특히 함수 인자로 CString 을 넘기는 경우가 많음. CString → const CString& CString*, const char* 등으로 수정한다. )

 

    오류조건을 먼저 검사하여 오류 체크로 인해 코드 가독성이 떨어지지 않도록 하자.

-       특정 오류조건이 발생하면 더 이상 함수 수행에 의미 없을 경우, 이러한 오류 조건들은 함수초입단계부터 먼저 확인해서 바로 리턴 한다

-       위와 같이 오류조건이 먼저 확인되면 프로그램 코드에서 if depth 가 줄어 들고 코드 읽기가 수월해 지는 장점이 있다.

Before

After

void CClass::OnTest()

{

 ...

 ...

 if (m_pWndMain)

 { 

  DoSomething1();

 }

 ...

 if (m_pWndMain)

 { 

  DoSomething2();

 }

 

}

void CClass::OnTest()

{

 if (m_pWndMain == NULL)

  return;

 ...

 ...

 DoSomething1();

 ...

 DoSomething2();

 

}

 

    긴 함수 쪼개기 (Refactoring 참고)

-       긴 함수는 작은 여러 개의 함수로 쪼갠다(Refactoring 책에 의하면 2-3줄 짜리 함수로까지 쪼개어서 코드 가독성을 높이도록 하고 있음)

-       작은 함수로 쪼개다 보면, 작은 함수를 재활용하게 될 수 있고

-       긴 함수보다 코드 읽기가 수월해 지며

-       결국 유지보수가 쉬워진다

 

    enum 값 선언 시 _START, _END 를 활용하자( CODE COMPLETE2 참고)

-       enum 으로 선언된 값들을 변수나 for loop 를 이용하여 반복 계산할 경우가 종종 있는데 이 경우 enum 시작과, 끝을 나타내는 값을 enum 선언에 포함하면 유용하게 사용할 수 있다.

-       추후 enum 에 값을 추가해야 할 경우 _END 값을 사용한 배열은 코드 변경없이 크기가 늘어남

-       For 루프 등에 _START, _END 을 사용할 수 있어 유지 보수에 유리

Before

After

enum WEEK_NAME

{

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

};

 

int nWeeks[SATERDAY + 1];

}

enum WEEK_NAME

{

           WEEK_STAR       = 0,

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

           WEEK_END        = 6,

};

 

int nWeeks[WEEK_END + 1];

 

 

    복잡한 제어문을 가진 루틴을 피하자  

-       If 문은 2 depth 이상 들어 갈 경우 refactoring 하라 (CODE COMPLETE2)

     대부분 코드를 제대로 이해하지 못해 복잡한 코드를 작성하고 있다.

     개발자 90% 2 depth 이상 들어가는 if 문장을 이해하지 못한다

-       IF~ELSE IF ~ELSE IF ~ …. ELSE 가 길게 이어질 경우 SWITCH 문으로 바꾼다

-       IF 문이 길게 늘어 질 경우 함수로 분리한다

-       C++ factory 개념으로 상속을 이용한 클래스를 만드는 방법도 활용


반응형
Posted by blueasa
, |

완전샤푸님의 블로그에서 발췌하였습니다.

눈에 보이는 괜찮은 팁이 몇 가지 있네요. ^^

 

 

 

- Form

 

 

1. MDI 폼의 경우 자식 폼에 MDI 부모 품을 설정 하는 방법
// 자식 폼의 생성자에서 부모 폼의 인스턴스를 넘겨 주어 설정하도록 한다.

public ChildForm( MainForm frm )

{

        InitializeComponent();


        this.MdiParent = frm;

……….

}





2. 다이얼로그 폼 사용

LogInForm frm = new LogInForm();

frm.StartPosition = FormStartPosition.CenterScreen;  // 다이얼로그 폼을 중심으로 이동

frm.ShowDialog();

                    

if( DialogResult.OK == frm.DialogResult )

{

      ………………………………………

}







- 컨트롤



1. 리스트, 리스트뷰 컨트롤



- 컬럼 지정

: 리스트 및 리스트 뷰 컨트롤의 컬럼을 프로그래밍으로 지정 할 수 있지만 디자인 모드에서 더욱 쉽게

추가 할 수 있다. 예는 리스트 뷰로 하지만 리스트 컨트롤과 방법은 같다.

리스트 뷰 컨트롤을 지정한다.


속성 창에서 ‘Colummns’ 속성을 클릭 한다.



‘ColumnHeader 컬렉션 편집기가 나타난다.


여기서 컬럼을 추가 하기 위해 ‘추가’버튼을 누르면 오른쪽에 속성을 주는 부분이 나온다. 컬럼명과 넓이 등을 지정하면 된다.

* 프로그래밍적 방법
ListView.Columns.Add( "이름", 40, HorizontalAlignment.Center );





- 데이터 모두 삭제
ListView.Items.Clear();




- 데이터 추가

ListViewItem lvi = new ListViewItem();

lvi.SubItems.Add( “최흥배” );

lvi.SubItems.Add( “프로그래머팀” );

lvi.SubItems.Add( “서버파트” );

ListView.Items.Add( lvi );

ListView.Refresh();




- 데이터 추가 2

: 위의 방식은 컬럼의 첫번째가 이미지 리스트인 경우는 좋지만 리스트 뷰의 첫 컬럼에 어떤 문자를

나타내고 싶은 경우는 되지 않는다. 이런 경우 ListVieeItem의 생성자의 인자에 첫 컬럼에 나타내고 싶은

문자를 지정해 줘야 한다.

ListViewItem lvi = new ListViewItem( iCount.ToString() );

lvi.SubItems.Add( “최흥배” );

lvi.SubItems.Add( “프로그래머팀” );

lvi.SubItems.Add( “서버파트” );

ListView.Items.Add( lvi );

ListView.Refresh();




- 삽입된 모든 데이터 순회
int iItemNum = ListView.Items.Count;

for( int i = 0; i < iItemNum; ++i )

{

        iYear = Convert.ToInt32(ListView.Items[i].SubItems[ 0 ].Text );

        ………..

|




- 기존 데이터 수정

……….

ListView.Items[i].SubItems[ 0 ].Text = iYear.ToString();

……..




- 특정 데이터 삭제 ( 순회 방법을 foreach를 사용함 )

………

foreach( ListViewItem lvi in ListView.Items )

{

        if( lvi.SubItems[ 0 ].Text == “2005” )

               ListView.Items.Remove( lvi );

}

…………




- 리스트 뷰의 특정 행을 선택한 경우 알고 싶을 때
ListView.SelectedListViewItemCollection  Items = ListView.SelectedItems;


// 리스트 뷰의 컨트롤 속성이 멀티 선택 가능 상태에서 복수 개 선택을 하였다면 선택된 것이 다 나온다.
foreach( ListViewItem lvi in Items )

{

…….

}





2. 콤보 박스


- 콤보 박스의 데이터 모두 삭제

: combobox.Items.Clear();




- 데이터 추가

: combobox.Items.Add( “LIFEOnline” );




- 목록 중 지정된 데이터 목록을 찾아서 선택 되도록 하기

int index = combobox.Items.IndexOf(“LIFEOnline” );

if( index < 0 )

return;


combobox.SelectedIndex = index;







3. 그리드 컨트롤


- 그리드 컨트롤을 실행 시 데이터 추가

DataGrid grid = new DataGrid();

DataTable dt = new DataTable();

DataRow dr;



// 컬럼 헤드를 추가

dt.Columns.Add( new DataColumn("아이템", typeof(string)) );

dt.Columns.Add( new DataColumn("Code", typeof(Int32)) );

                                

// 레코드 추가                                

dr = dt.NewRow();

  

dr[ 0 ] = “칼”;  // 아이템 컬럼에 아이템 이름 추가

dr[ 0 ] = 110;    // 코드 컬럼에 코드 번호 추가

                                

dt.Rows.Add(dr);  // 레코드를 추가 한다.



DataView dv = new DataView(dt); // 데이터 뷰를 만든다.

grid.DataSource= dv;               // 그리드 컨트롤에 추가



- 그리드 컨트롤의 컬럼 스타일 지정

그리드 컨트롤에 데이터를 넣르면 컬럼이 지멋대로 되는 경우가 있다.. 이럴 때 원하는 스타일로

컬럼을 지정하면 된다..다만 꼭 데이터를 다 넣은 후에 해야 된다. 그전에 하면 데이터를 넣으면서
원하지 않는 상태로 변경되어 버린다.

…………………………………………………………….

DataGridTableStyle gtStyle1 = new DataGridTableStyle();  



gtStyle1.GridColumnStyles.Add(new DataGridTextBoxColumn());

gtStyle1.GridColumnStyles[0].MappingName = “아이템”; // 이 이름이 컬럼 스타일을 바꾸기를 원하는 컬럼의

                                                                          // 텍스트와 꼭 같아야 된다.

gtStyle1.GridColumnStyles[0].HeaderText = “아이템”;    // 컬럼의 텍스트를 지정한다.

gtStyle1.GridColumnStyles[0].Alignment = HorizontalAlignment.Center; // 중간 정렬

gtStyle1.GridColumnStyles[0].Width = 70;                               // 폭 지정

gtStyle1.GridColumnStyles[0].NullText = string.Empty;




gtStyle1.GridColumnStyles.Add(new DataGridTextBoxColumn());

gtStyle1.GridColumnStyles[0].MappingName = “Code”;    // 이 이름이 컬럼 스타일을 바꾸기를 원하는 컬럼의

                                                                 // 텍스트와 꼭 같아야 된다.

gtStyle1.GridColumnStyles[0].HeaderText = “Code”;       // 컬럼의 텍스트를 지정한다.

gtStyle1.GridColumnStyles[0].Alignment = HorizontalAlignment.Center; // 중간 정렬

gtStyle1.GridColumnStyles[0].Width = 70;                               // 폭 지정

gtStyle1.GridColumnStyles[0].NullText = string.Empty;



grid.TableStyles.Add(gtStyle1);            // 그리드 컨트롤에 세팅 한다.

……………………………………………………………..










- ADO.NET

1. 오라클 DB 연결

string strCommonConnection = “Data Source=ORA10;User ID=admin;assword=1111”;

OracleConnection OraCommonDBConnt = new OracleConnection( strCommonConnection );

OraCommonDBConnt.Open();




2. 오라클 DB 끊기

if( ConnectionState.Open == OraCommonDBConnt.State  )

        OraCommonDBConnt.Close();




3. DataSet을 사용한 쿼리 작업

OracleDataAdapter OraDataAdapter = new OracleDataAdapter();

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = “SELECT * FROM Member”;

OraDataAdapter.SelectCommand =  cmd;

OraDataAdapter.Fill( ResultDataSet , strTableName );




4. DataReader를 사용한 쿼리 작업

OracleDataAdapter OraDataAdapter = new OracleDataAdapter();

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = “SELECT * FROM Member”;

DataReader outDataReader = cmd.ExecuteReader();

              

if( false == outDataReader.HasRows )

return false;


………….

// 원하는 필드의 인덱스 번호를 알아낸다.

int IndexDex   = outDataReader.GetOrdinal("Dex");

…………..




while( dataReader.Read() )

{

   …………………..

    CharInfo.DEX = outDataReader.GetInt32( IndexDex );

   ……………….

}




5. 테이블의 데이터 모두 삭제

string strContext = "DELETE FROM " + TableName;

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = strContext;

cmd.ExecuteNonQuery();




6. DataSet의 내용을 DataGrid 컨트롤에 넣기

GridQueryResult.SetDataBinding( ResultDataSet, strTableName );




7. 간단하게 DataSet을 이용한 테이블의 데이터 갱신

// 이전에 쿼리 작업을 한 DataAdapter를 사용해야 된다. 그렇지 않을 경우 DataAdapter에 업데이트 및 삭제 로직을

// 등록 해줘야 된다.

// 이 작업은 쿼리를 하여 DataGrid 컨트롤에 넣은 경우 DataGrid의 데이터를 수정 한 후 이 내용을 DB에 업데이트

// 하고 싶을 때 사용한다.

OracleCommandBuilder cb = new OracleCommandBuilder( OraDataAdapter );

cb.RefreshSchema();

OraDataAdapter.Update( dataset, TableName );




8. DataSet의 내용을 XML 파일로 저장

DataSet ds = new DataSet();

……….

ds.WriteXml( filename );
// 이후 위의 7번 방식을 이용해서 데이터를 추가 한다.

……





9. 테이블의 모든 데이터를 지우고 XML의 데이터를 추가 하기

// 테이블의 레코드를 모두 지운다.

……….

// ds 라는 DataSet에서 XML 파일을 읽어 들인다.

DataSet ds = new DataSet();

ds.ReadXml( textBoxFilePath.Text );










- 파일



1. 클래스 단위로 파일에 쓰기

이 직렬화 방식은 꼭 .NET 플랫폼에서 서로 파일을 읽고 쓸 때만 사용 가능하다.
만약 .NET으로 만든 프로그램에서 아래와 같이 파일을 만들고 이것을 네이티브에서

읽으면 앞에 다른 값이 들어가 있다( 정확하게는 직렬화 되는 클래스의 메타 정보가

들어가 있다 ).


FileStream GloveFile = new FileStream( "0.ipt", FileMode.Create);

BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize( GloveFile, ItemFileclass );





2. 현재 실행 하고 있는 프로그램의 실행 경로 얻기

Environment.CurrentDirectory

를 이용하면 실행 경로를 얻을 수 있다.







- 네트워크

1. 웹에 있는 파일을 받기

정확하게 말하면 http 프로토콜을 이용하여 웹에 있는 파일을 다운로드 하는 방식을 말한다.

WebRequest myWebRequest = WebRequest.Create("http://jacking75.cafe24.com/Index.hml");

WebResponse myWebResponse = myWebRequest.GetResponse();



Stream ReceiveStream = myWebResponse.GetResponseStream();



ReceiveStream 객체를 파일 스트림을 이용하여 파일로 저장 하던가 다른 스트림으로 사용하면 된다.








- ETC



1. C#에서의 XML 주석 코드 제작을 위한 주석 작성 요령

: public bool IsEnableExecute( int iReqList )
{

    …………

}

가 있다면

/// <summary>

/// 현재 수행하는 기능을 수행 가능한가

/// <summary>

/// <param name="iReqList">수행할 기능의 인덱스</param>

/// <returns name="true">수행가능</returns>

/// <returns name="false">수행불능</returns>

public bool IsEnableExecute( int iReqList )
{

    …………

}

이렇게 작성한다.




2. 다른 클래스에 있는 const로 정의한 상수를 이용 방법
: 상수는 다음과 같이 정의 되어 있다.

public class PacketDefine

{

   Public const int Packet_First = 0;

   ………..

}



이것을 Command 클래스에서 사용 할려면

…………

Int packetfirst = PacketDefine.Packet_First;

………….


사용한다.




3. 데이터 변환.

: 데이터 변환을 위해서는 Convert의 멤버를 사용한다.

Convert.Toxxx( xxx )를 사용하면 된다.
예) 스트링을 int 변환
Convert.ToInt32( string );




3. 바이트 배열을 지정된 위치와 크기로 복사할 경우
: Buffer.BlockCopy( ……. );




4. 클래스의 크기를 알고 싶을 때

: Marshal.SizeOf(LoginPacket)

LoginPacket는 인스턴스 화된 객체이어야만 한다. LoginPacket의 클래스인 LOGIN_PACKET를 사용하면 안된다.




5. 외부 프로그램 실행

: 여기서 인터넷 익스플로어를 실행해서 본인의 홈페이지에 가는 것을 예를 들겠다.

System.Diagnostics.Process IEProcess = new System.Diagnostics.Process();

IEProcess.StartInfo.FileName = "iexplore.exe";

IEProcess.StartInfo.Arguments = "http://jacking75.cafe24.com ";

IEProcess.Start();



6. 메시지 박스

- 일반 메시지 박스 사용

MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?" );



- YES / NO 버튼 사용

if( DialogResult.Yes == MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?",

                                                            "이진 파일 저장", MessageBoxButtons.YesNo ) )



7. 한글 파일 출력 문제

- 정확한 이유는 모르지만 한글을 파일에 입력할 때 인코딩을 Default 방식으로 지정하면

한글 XP에서는 한글을 아스키 코드 값으로 제대로 인식하지만 윈도우 2003에서는 한글을

유니코드 방식으로 인식하여 한글 1글자를 아스키 코드 1글자로 인식하는 경우가 있다.


string strValue = “개”;

encodedBytes = System.Text.Encoding.Default.GetBytes(strValue);        



한글 XP에서 읽는다면 encodedBytes의 길이가 2개로 나오지만 윈도우 2003에서는

길이가 1로 된다.



이 문제를 해결할려면 인코딩 방식을 명시적으로 지정해야 된다.

string strValue = “개”;

encodedBytes = System.Text.Encoding.GetEncoding(949).GetBytes(strValue);




8. 폼의 마우스 커서 변경

- 화살표 마우스 커서      this.Cursor = Cursors.Arrow;

- 모래시계 커서                this.Cursor = Cursors. WaitCursor;

- 손 커서                         this.Cursor = Cursors. Hand;

- 기본 커서                      this.Cursor = Cursors. Default;

등등…….




9. 네이티브의 time(&time_t)에서 얻은 초단위의 시간을 C#에서 사용

- time함수를 이용하여 얻은 시간은 시작이 1970년부터이고 C#의 경우는

0년 1월1일 부터이다..그래서 서로 호환이 되지 않느다. 이것을 해결할려면

다음과 같이 하면 된다.



int iTime = C타임함수값;    
DateTime dt = new DateTime(1970, 1, 1, 9, 0, 0); // 한국은 GMT+9시간
dt = dt.AddSeconds(iTime);

반응형
Posted by blueasa
, |