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

카테고리

분류 전체보기 (2794)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (11)
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

.NET 기반에서 C#으로 윈도우메세지를 핸들링하기 위해서는 WndProc를 오버라이드하여 사용하는 것으로 많이 알려져 있습니다. 하지만 .Net CF 에서는 Form클래스에 WndProc메소드가 기본적으로 존재하지 않습니다. 대신에 MessageWindow클래스를 이용하여 WndProc를 오버라이드하면 윈도우 메세지를 핸들링할 수 있도록 지원해줍니다.

 

그럼, 간단하게 폼 위에서 마우스가 이동하면, 이때 마우스 좌표값을 윈도우 메세지 형태로 날려서

이 값을 Form의 Text속성에 표시하는 예제를 함께 구현해 보도록 하지요.

 

우선 MessageWindow 클래스 사용을 위해서는 다음과 같이 참조추가를 해주어야 합니다.

 

 

 

사용하기 원하는 코드에서

 

using Microsoft.WindowsCE.Forms;

 

이제 MessageWindow를 사용할 수 있게 됩니다.

 

아래는 기본적으로 프로젝트 생성시에 생성되는 폼(frmMain)에서

MessageWindow를 상속받아 WndProc를 오버라이드한 클래스를 이용하는 코드입니다.

굵은 부분을 참고하면 어떤식으로 윈도우메세지를 핸들링하는지 흐름을 파악할 수 있을 겁니다.

 

frmMain 코드 - 프로젝트 생성시 생성되는 기본 폼

 

    public partial class frmMain : Form
    {
        MsgWindow MsgWin = null;

 

        public frmMain()
        {
            InitializeComponent();

            this.MsgWin = new MsgWindow(this);
        }

 

        //마우스 이동시에 메세지를 생성하여 날려주는 작업을 해주겠습니다.

        protected override void OnMouseMove(MouseEventArgs e)
        {
            Message msg = Message.Create(MsgWin.Hwnd, MsgWindow.WM_CUSTOMMSG,

                                                            (IntPtr)e.X, (IntPtr)e.Y);
            MessageWindow.SendMessage(ref msg);
            base.OnMouseMove(e);
        }

       

        //MsgWin을 통해 현재 폼에 접근할 수 있도록 메소드를 하나 정의합니다.

        public void RespondToMessage(int x, int y)
        {
            this.Text = "X = " + x.ToString() + ", Y= " + y.ToString();
        }
    }

 

 

 

 MesssageWindow를 상속받아 WndProc를 오버라이드

 

    public class MsgWindow : MessageWindow
    {
        public const int WM_CUSTOMMSG = 0x0400;

        private frmMain msgform;

 

        public MsgWindow(frmMain msgform)
        {
            this.msgform = msgform;
        }

 

        protected override void WndProc(ref Message msg)
        {
            switch (msg.Msg)
            {
                case WM_CUSTOMMSG:
                    this.msgform.RespondToMessage((int)msg.WParam, (int)msg.LParam);
                    break;
            }
           
            base.WndProc(ref msg);
        }
    }

 

반응형
Posted by blueasa
, |

이번 내용은 C# 주의해서 보아야 할 것들에 대한 정리 두번째 강좌로서 OOP 관련한 것들을 순서없이 정리한 것입니다.

C#과 OOP
C# 클래스는 메소드, 속성외에 인덱서, 프로퍼티, 생성자, 연산자, 델리게이트, 이벤트 등을 포함한다.


[static과 instance]
Static 키워드와 함께 선언된 필드는 정적 필드 혹은 정적 데이터로 불려진다. 그리고 static 으로 선언되지 않은 필드들은 인스턴스 필드 혹은 인스턴스 데이터로 불려진다.
Static 키워드는 액세스 한정과는 아무런 상관이 없다.(private static/public static 모두 가능)

인스턴스 메소드도 정적 메소드와 같이 메모리에 한번만 저장되고 클래스와 전체적으로 연관되어 있다.

정적으로 선언된 메소드에서는 인스턴스 필드에 액세스할 수 없다.

참조는 메모리의 주소값을 나타내는 32비트의 숫자이므로 참조를 복사하거나 비교하는 것이 성능면에서 봤을 때 아주 우수하다. 그러므로 되도록이면 참조를 사용하는 것이 좋다.

[상속]
인터페이스 상속/ 구현상속
기본클래스/수퍼클래스, 파생클래스/서브클래스
상속의 원칙
파생클래스에 필드, 메소드, 프로퍼티 등 어떠한 형식의 멤버들도 새롭게 추가할 수 있지만, 기본클래스에는 정의되지 않아야 그렇게 할 수 있다.
기본클래스에 정의된 메소드나 프로퍼티의 구현을 교체할 수 있다.(프로퍼티는 구현을 가지지 않는다.) 메소드의 새로운 구현이 이전의 구현을 오버라이드(Override) 한다.
기본클래스에 대한 메소드를 오버라이드할 때는 반드시 override 키워드 사용

기본클래스의 메소드가 가상(virtual)으로 선언되지 않으면 그 메소드를 override 할 수 없도록 한다.
각 파생클래스는 오직 하나의 기본 클래스로 부터만 상속 받을 수 있다.

[Object 클래스]

메소드 액세스한정 역할
string ToString() public virtual 객체의 문자열 표현을 반환한다.
int GetHashTable() public virtual 어떤 테이블에서 객체의 인스턴스를 효율적으로 찾아볼 수 있도록 하기 위해 디잔인된 객체의 해시 값을 반환한다.
bool Equals(object obj) public virtual 객체의 두 인스턴스를 비교하여 같은 인스턴스인지 판단한다.
bool Equals(object objA, objB) public static 객체의 두 인스턴스를 비교하여 같은 인스턴스인지 판단한다.
bool ReferenceEquals(object objA, object objB) public static 두 참조가 같은 객체를 참조하고 있는지 비교한다.
Type GetType() public 객체의 데이터 형식을 반환한다.
object MemberwiseClone() protected 객체의 복사본을 만든다.
void Finalize() protected virtual 리소스를 해지하기 위한 상황에서 사용한다.


object라 함은 System.Object를 의미한다.
object 키워드는 변수나 인수의 데이터 형식을 선언할 때와 같인 클래스가 무엇을 의미하는지 명시해 줄수 없을 때도 사용 가능하다.

System.Object.GetType은 가상으로 정의되지 않았기 때문에 ToString()과는 달리 GetType()을 오버라이드 할 수 없다.

[가상 메소드와 비가상 메소드]
이 둘의 차이점은 메소드가 실행 시에 호출되는 방식이다.

메소드가 가상이 아니라면, 컴파일러는 단순히 참조가 선언된 데이터 형식을 사용한다.

만약 메소드가 가상이면 컴파일러는 참조가 실제로 무엇을 가리키고 있는지 실행 시에 점검하는 코드를 만들어 낸다. 그리고 이 인스턴스가 어떤 클래스가 인스턴스인지를 구분하여 적절한 메소드 오버라이드를 호출한다. 예를 들어 가상 메소드가 100번 반복되는 루프 안에서 호출된다면 이 프로그램은 참조 변수가 참조하고 있는 인스턴스 형식을 100번 검사해야 한다. 왜냐면 매번 반복 수행할 때마다 참조는 다른 인스턴스를 가리킬수 있기 때문이다.

[메소드 숨기기]
파생클래스에서 new 키워드를 사용하여 동일한 signature를 가진 기본클래스의 메소드를 숨길 수 있다.

[추상 함수와 기본클래스]
클래스가 추상으로(abstract)으로 선언되면 인스턴스화될 수 없다
메소드를 추상으로 정의하면 이는 파생클래스에서 오버라이드 된다고 가정하므로 구현될 필요 없다.
클래스내의 어떤 메소드가 추상이면 클래스 자신도 추상이어야 한다.
추상클래스로부터 파생된 비추상 클래스는 반드시 추상 메소드를 오버라이드해야 한다.

[sealed 클래스와 sealed 메소드]
추상클래스나 추상메소드의 반대 개념
상속되거나 오버라이드 될 수 없다.

[기본 클래스의 메소드 호출하기]
base 키워드 사용

[상속]
메소드 뿐만 아니라 구현된 다른 클래스 멤버도 오버라이드 할 수 있고 숨길수 있다. 즉 프로퍼티도 원한다면 가상으로 선언할 수 있고, 오버라이드할 수 있다.
필드는 가상으로 선언되거나 오버라이드될 수 없다. 하지만 파생 클래스에 동일한 이름의 다른 필드를 선언함으로써 기본 클래스의 필드를 숨길 수는 있다.
정적 메소드를 가상으로 선언할 수는 없지만 인스턴스 메소드처럼 숨길 수는 있다.
T형식으로 선언된 참조 변수가 T로부터 파생된 클래스의 어떤 인스턴스를 참조할 수 있다. 그렇다고 해서 T내에 선언되지 않은 어떤 멤버를 그 변수를 통하여 참조할 수 있는 것은 아니다.

[메소드 오버로딩(Overloading)]
오버로딩과 오버라이드는 아무 상관 없다.
메소드 오버로딩은 상속이나 가상 메소드와는 아무런 상관이 없다.
매개변수를 명시적으로 형식 변환하여 오버로드가 가지는 매개변수의 데이터형식과 정확하게 일치시켜 주는 것이 좋다.
오버로드의 signature가 달라야 한다. 단지 반환형식만이 다른 것이 아니라, 매개변수의 이름과 데이터 형식이 달라야 한다.
두개의 메소드가 실제로 다른 일을 하는 우에는 오버로딩을 사용하면 안된다.
기본매개변수 public doSomeThing(int x, int y=10)과 같은 문법을 사용할 수 있는 VB/VC++ 과는 달리 C#에서는 이것이 가능하지 않아 메소드 오버라이딩을 사용해야 한다.

[생성(Construction)과 정리(Disposal)]

생성자는 그것을 포함하고 있는 클래스아 같은 이름으로 선언되면 어떠한 반환 형식도 가질 수 없다.
클래스 안에 어떠한 생성자도 정의하지 않았다면 컴파일러는 암시적으로 기본적인 초기화를 클래스 인스턴스 내의 멤버 변수에 적용시킨다.

생성자의 다른 용도로서 클래스의 인스턴스가 얼마나 많이 생성되었는가를 세는 것이다.

Public class Authenticator
{
private static unit nInstancesCreated=0;

public Authenticator(string initialPassword)
{
++nInstancesCreated;
Password = initialPassword;
}
private string Password;
private static uint minPasswordLength = 6;
}


정적생성자
클래스에 어떤 매개변수도 받아들이지 않는 정적 생성자를 정의할 수 있다. 클래스의 객체가 생성되지 않고 단 한번만 수행된다. 필요한 이유는 정적 변수의 값을 초기화하기 위해서이다.



class Authenticator
{
static Authenticator()
{
minPasswordLength=6;
}
public Authenticator()
{
Password = “lskdflsdf’;
}
public Authenticator(string initialPassword)
{
Password = initialPassword;
}
private string Password;
private static uint minPasswordLength;
}

정적 생성자가 클래스의 인스턴스 멤버에 액세스할 수 없고 정적 멤버에만 액세스할 수 있다는 것은 매우 당연하다.
두개 이상의 정적 생성자를 가진 클래스를 작성하는 경우에는 어떤 정적 생성자가 먼저 실행해야 하는지가 정의되지 않는다. 그러므로 이미 실행되었거나 앞으로 실행될 다른 정적 생성자에 의존하는 코드를 정적 생성자 안에 넣어서는 안된다.

[상수(const) 필드와 읽기전용(readonly) 필드]
둘 다 값이 바뀔 수 없는 상수로 간주된다.
const
상수는 정의될 때 값이 결정되어야 한다.
Public const int MaxPasswordLength=20;
Public const int MaxPasswordLength; //not permitted!!
상수는 암시적으로 정적(static)이다. 명시적으로 static 선언은 허용안함
readonly
상수 보다 좀더 나은 유연성을 제공
컴파일 시에는 값을 결정할 수 없고 실행 시에 계산되는 어떤 결과값을 초기값으로 결정해야 하는 경우 사용한다.
클래스의 각 인스턴스 마다 다른 값을 가질 수 있으므로 정적이 아니고 정적으로 선언하고 싶으면 명시적으로 static 선언해야 함

public class Authenticator
{
public readonly DateTime CreationDate;
public static readonly uint MaxPasswordLength;
static Authenticator()
{
MaxPasswordLength=20;
}
public Authenticator()
{
// 클래스의 인스턴스에 따라 달라질 수 있다.
CreationDate = new DateTime(2001,1,1)
}
}


다른 생성자로부터 생성자를 호출하기

public Authenticator() : this(“lskdfdfd”)
{
} // 다른 생성자가 먼저 실행되어야 함을 명시한다.


계층에 매개변수를 가지지 않는 생성자 추가하기
아무 매개변수도 받아들이지 않는 생성자를 추가시켜서 기본 생성자를 교체

public GenericCustomer()
: base() //생략가능
{
name = “
”;
}

base 키워드와 this키워드는 다른 생성자를 호출하기 위한 유일한 키워드이다.

[정리하기 : 소멸자(Destructor)]
C#은 Dispose()나 Close(), Finalize() 메소드를 지원한다. 이 메소드들은 함께 작동하도록 디자인되었다.
Finalize()
리소스를 해지하는 데 사용되는 선택사항 중 하나인 Finalize()는 고전적인 소멸자와 가장 근접한 개념이다. Finalize() 라는 메소드를 클래스에 정의하면 이 메소드는 클래스 인스턴스가 소멸될 때 자동으로 호출된다.
Finalize()는 결정적이지 않다. 즉 일반적으로 언제 인스턴스가 소멸될지 모르기 때문에 언제 Finalize()가 호출될지 예측할 수 없다.
필요에 다라 System.GC.Collect()를 호출함으로써 어떤 시점에서 가비지 켈렉터를 강제로 작동시킬 수 있다.
일반적으로 꼭 필요한 경우가 아니면 이 메소드를 구현하지 않을 것을 권한다.

Dispose()와 Close()
C#은 Dispose() 메소드에 관한 아주 많은 지원을 하고 있다.
이것의 장점은 어떤 리소스가 더 이상 필요 없어진 즉시 해지된다는 것이지만 클라이언트 코드가 알아서 호출해 주어야 한다.

Public void Dispose()
{
//리소스 정리
GC.SuppressFinalize(this);
}
protected overrie void Finalize()
{
//리소스 정리
base.Finalize();
}

클라이언트 코드가 Dispose()를 호출할 것을 기억하고 있다면 리소스는 제때에 해지된다.
System.GC 클래스의 SuppressFinalize() 메소드는 매개변수로 전달된 객체가 더 이상 완료화될 필요가 없다는 것을 .NET 런타임에게 알리는 역할을 한다. 완료화(finalization)라는 것은 객체에 대한 가비지 컬렉션이 행해질 때 Finalize() 메서드는 호출되지 않고, 이것과 관련된 어떠한 성능 저하의 문제도 일어나지 않는다.

Close()대 Dispose()
Close()와 Dispose()의 차이점은 주로 규약상의 차이이다. Close()는 이 리소스가 나중에 다시 사용될 수 있음을 내포하고 있는 반면 Dispose()는 완료의 의미를 좀더 내포하고 있다.
즉 Dispose()를 호출하면 클라이언트가 이 특정 객체에 대한 사용을 완전히 종료함을 의미한다.

IDisposable
기본적으로 C#은 객체의 참조가 범위 밖으로 나갔을 때 자동으로 그 객체의 Dispose()(Close()는 해당되지 않는다.)가 호출되도록 하기 위한 문법을 제공한다.


Class ResourceGobbler : IDisposable
{

public void Dispose()
{
}
}
{
ResourceGobbler TheInstance = new ResourceGobbler();
// 처리
TheInstance.Dispose();
}
=
using (ResourceGobbler TheInstance = new ResourceGobbler())
{
//처리
}

using 구조는 사용하지 않는 것이 좋다.
IDisposable로부터 클래스를 파생시키면 반드시 Dispose() 메소드를 구현해야 한다.

Sample
Class DataStoreConnection : IDisposable
{
private int DataStoreHandle = 0;
private bool CanOpen = true;
private readonly string name;

public DataStoreConnection(string name)
{
this.name = name;
}
public void Open()
{
if (CanOpen == false)
Console.WriteLine(name + “: Error: Attempt to Open after calling Dispose()”);
If (DataStoreHandle ==0)
{
DataStoreHandle = 1;
Console.WriteLine(name + “: Connected to DataStore”);
}
else
Console.WriteLine(name + “: Error: Already connected to DataStore”);
}
public void Close()
{
DataStoreHandle = 0;
}
public void Dispose()
{
Console.WriteLine(“Disposing: “ + name );
CanOpen = false;
Close();
GC.SuppressFinalize(this);
}
~DataStoreConnection()
{
Close();
}
}

Close()메소드가 한번 이상 호출되어도 아무런 오류가 발생하지 않는데 이런 방식으로 코딩하는 것이 바람직하다.
Dispose()는 Close(0와 동일한 일을 하는데 Dispose()를 호출하는 것은 이 객체 사용의 완전한 긑을 맺었다는 것을 의미하므로 이것은 완료화를 수행하지 못하도록 SuppressFinalize()를 호출한다.(여기서 완료화란 Finalize() 메소드를 호출하는 것을 의미)
Dispose()는 또한 CanOpen 필드를 false로 설정하여 이 객체가 데이터저장소로 연결할 수 없도록 명시한다.
최종적으로 Finalize() 메소드(소멸자)는 연결을 닫는다.
Finalize() 메소드에서 콘솔에 메시지를 출력할 수 없다. 가비지 컬렉터는 콘솔 윈도우에 액세스할 수 없기 때문에 우리가 close() 메소드에서 콘솔에 메시지를 출력하려고 하면 실행시 오류가 발생한다.
[메모리]
Stack에 저장된 데이터(값 형식)는 scope를 벗어나면 소멸되고 다시 그 자리에 새로운 변수를 위한 공간으로 사용되는 중첩이 성립된다.
New 연산자에 의해 Heap에 저장된 데이터(참조 형식)는 수명이 가비지 컬렉터에 의해 소멸될때까지 유지된다.

가비지 컬렉터에 의한 압축은 관리 힘이 기존의 비관리 힘에 비해 가지는 차이점이다 페이지 스와핑이 적게 일어나므로 굉장히 빠르다.

만약 값 형식이 참조 형식의 일부분(예를 들어 배열의 element나 클래스의 멤버)으로 정의된다면 참조형식을 저장하고 있는 데이터 내부인 힙의 인라인으로 저장된다.

[구조체(Struct)]

구조체는 값 형식이다.
구조체는 상속을 지원하지 않는다.
구조체의 생성자는 동작하는 방법이 약간 다르다, 특히 컴파일러는 항상 매개변수를 받아들이지 않는 기본 생성자를 제공하는데, 개발자는 임의로 이것을 변경할 수 없다.

구조체를 메소드의 매개변수로 전달하거나 어떤 구조체를 다른 구조체에 대입하는 경우에는 성능 면에서 좋지 않은 결과를 초래한다. Ref 매개변수로 전달하면 이러한 성능저하를 막을수 있다.
구조체의 어떤 멤버를 가상으로 선언하는 것은 불가능
구조체는 암시직으로 sealed로 간주되므로 그렇게 선언할 필요 없다.
구조체에도 생성자를 선언할 수 있는데 아무런 매개변수도 받아들이지 않는 생성자는 선언할 수 없다.
구조체도 Close(), Dispose() 메소드를 가질수 있다. 하니반 Finalize()는 지원되지 않는다.

[인덱서]
객체를 마치 배열처럼 다룰 수 있게 한다.
인덱서는 프로퍼티와 매우 비슷한 방식으로 get함수와 set함수를 이용하여 정의된다. 인덱서의 이름은 this이다.

Struct Vector
{
public double x,y,z;
public double this[int i]
{
get
{
switch(i)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw new IndexOutOfRangeException(“Attempt to retrieve Vector element ” + i)
}
}
set
{
switch(i)
{
case 0:
x=value;
break;
case 1:
y=value;
break;
case 2:
z=value;
break;
default:
throw new IndexOutOfRangeException(“Attempt to retrieve Vector element ” + i)
}
}
}
}

foreach 루프에서는 인덱서를 사용할 수 없다. Foreach 명령문은 각 항목을 배열이 아닌 컬렉션을 간주하므로 다른 방식으로 작동한다.

[인터페이스]
인터페이스 멤버는 항상 public이고 가상이나 정적으로 선언될 수 없다.
인터페이스는 일종의 계약역할을 한다.
클래스가 컬렉션에 필요한 인터페이스를 구현한다고 선언을 해야(System.Collections.IEnmerable), 이것이 지정 컬렉션이라고 생각할 수 있는 것이다.
인터페이스를 상속하는 클래스에서 인터페이스의 모든 메소드를 구현하지 않으면 컴파일 오류이다.
반응형
Posted by blueasa
, |

Handling Application Events: On Idle

using System;
using System.Threading;
using System.Reflection;
using System.Windows.Forms;
   

public class HelloWorldForm : Form
{
    public HelloWorldForm()
    {
        Text = "Hello, WindowsForms!";
    }
}
   
public class ApplicationEventHandlerClass
{
    public void OnIdle(object sender, EventArgs e)
    {
        Console.WriteLine("The application is idle.");
    }
}
   
public class MainClass
{
    public static void Main()
    {
        HelloWorldForm FormObject = new HelloWorldForm();
        ApplicationEventHandlerClass AppEvents = new ApplicationEventHandlerClass();
   
        Application.Idle += new EventHandler(AppEvents.OnIdle);
        Application.Run(FormObject);
    }
}


출처 : http://www.java2s.com/Code/CSharp/Development-Class/HandlingApplicationEventsOnIdle.htm           

       
반응형
Posted by blueasa
, |

안녕하세요 : )

뭐라고 할 말이 없을만큼 오래간만입니다 ;;;

 

이제 프로젝트도 거의 종료가 되어가고, 개인적으로 준비하던 일도 어찌어찌 끝이 보이기 시작하는데다가, '아 그럼 예전에 그만뒀던 연재를 시작해볼까!'라고 열의를 불태워볼까 했더니!

 

...6사단으로 소집명령이 떨어졌습니다 orz

 

아직 시간은 좀 있습니다만, 뭔가 멍해져 버려서.. 짧은 아티클이라도 올리고 끌려가자는 마음에 끄적여 봅니다 ;

 

 

그리고 그려 그리고픈

 

어떤 언어를 배웠든 간에, 화면에 연속적으로 뭔가를 그려보려는 시도해 봤던 사람은 '어라 이거 왜 화면이 깜박거리냐..'라는 생각을 한 번쯤은 해 봤을 것이다. 이 아티클은 그런 현상을 해결하는 방법을 설명한다.

 

.Net에서는 GDI+라는 인터페이스를 제공, 그래픽과 관련된 장치를 제어하도록 하고 있다. 보통 이와 관련된 클래스와 기타 객체들은 System.Drawing 네임스페이스를 통해서 제공된다.

 

준비가 되었다면, 윈폼 기반의 프로젝트를 하나 생성하고 버튼 두 개를 추가한 뒤 다음과 같은 소스를 입력하여 보자 :

 

private void button1_Click(object sender, System.EventArgs e)

{

    Graphics graphic = this.CreateGraphics();

    SolidBrush brush = new SolidBrush(Color.DarkRed);

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

    {

        graphic.Clear(this.BackColor);

        graphic.FillEllipse(brush, i, 0, 200, 200);

    }

    brush.Dispose();

    graphic.Dispose();

}

 

private void button2_Click(object sender, System.EventArgs e)

{

    Graphics graphic = this.CreateGraphics();

    SolidBrush brush = new SolidBrush(Color.DarkRed);

    Bitmap bitmap = new Bitmap(

        this.Width, this.Height

        );

    Graphics memGraphic = Graphics.FromImage(bitmap);

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

    {

        memGraphic.Clear(this.BackColor);

        memGraphic.FillEllipse(brush, i, 0, 200, 200);

        graphic.DrawImageUnscaled(bitmap,0,0);

    }

    brush.Dispose();

    memGraphic.Dispose();

    bitmap.Dispose();

    graphic.Dispose();

}

 

둘 다 적색의 원을 오른쪽으로 이동시키며 그리는 코드이지만 버튼 1은 더블 버퍼링을 사용하지 않은 것이고, 버튼 2는 더블 버퍼링을 사용한 코드이다. 코드를 보면 알겠지만, 비트맵으로부터 얻은 Graphics 객체에 그리기와 관련된 모든 작업을 한 후에 비트맵을 폼의 Graphics 객체에 그리는 부분이 추가되어 있다. 이 경우 실제 폼에 대한 그리기 작업은 한 번만 이루어지기 때문에 깜박임이 없어지게 된다.

 

설명을 보기보다는 실행시켜보면 이 기법을 써야할 이유를 알게 될 것이다 : )

 

p.s:Dispose() 메서드는 사실 안 써도 별 상관 없지만, GC가 리소스를 빨리 해제해도록 하는데 도움이 되므로 쓰는 습관을 들이는 게 좋다.

 

 

정리

 

간단하지만 남들이 잘 알려주지 않는 코드였습니다.

그럼 : )


출처 : http://www.gosu.net/GosuWeb/Article-detail.aspx?ArticleCode=955

반응형
Posted by blueasa
, |

지금 키보드입력이 삽입상태인지 수정상태인지, Caps Lock 켜져 있는지 꺼져있는지를

GetKeyState API 이용 알아내는 방법입니다.

 

MFC 그랬듯이 .NET Library Windows API 완전히 표현하고 있지는 않는  같습니다.
그러나 C#에서 Unmanaged Code 사용할  있으니까 Windows API 직접 사용하면 되겠지요.    


 

using System.Runtime.InteropServices;
...

[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);


[DllImport("User32.dll")]
public static extern short GetKeyState(int nVirtualKey);

private void textBox1_TextChanged(object sender, System.EventArgs e)
{
     if ((GetKeyState(0x15) & 0x01) == 0x01) MessageBox(0, "Hangul Key", "Sunken", 0);
     if ((GetKeyState(0x14) & 0x01) == 0x01) MessageBox(0, "CapsLock Key", "Sunken", 0);
     if ((GetKeyState(0x90) & 0x01) == 0x01) MessageBox(0, "NumLock Key", "Sunken", 0);

}

 


 

자료출처 : http://www.devpia.com/

반응형
Posted by blueasa
, |

텍스트박스에 한글만 입력하기

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    if((Char.IsPunctuation(e.KeyChar) || Char.IsDigit(e.KeyChar) || Char.IsLetter(e.KeyChar) || Char.IsSymbol(e.KeyChar)) && e.KeyChar != 8)
    {
        e.Handled = true;
    }
}

 

텍스트박스에 영어만 입력하기

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    if(!(Char.IsLetter(e.KeyChar)) && e.KeyChar != 8)
    {
        e.Handled = true;
    }
}

 

private void textBox1_Leave(object sender, System.EventArgs e)
{
    Regex emailregex = new Regex(@"[a-zA-Z]");
    Boolean ismatch = emailregex.IsMatch(textBox1.Text);
    if (!ismatch)
    {
        MessageBox.Show("영문자만 입력해 주세요.");
    }
}

 

텍스트박스에 숫자만 입력하기

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    if(!(Char.IsDigit(e.KeyChar)) && e.KeyChar != 8)
    {
        e.Handled = true;
    }
}
private void textBox1_Leave(object sender, System.EventArgs e)
{
    Regex emailregex = new Regex(@"[0-9]");
    Boolean ismatch = emailregex.IsMatch(textBox1.Text);
    if (!ismatch)
    {
        MessageBox.Show("숫자만 입력해 주세요.");
    }
}

 

음.. 이렇게 두번에 걸쳐 체크한 이유는 한글은 ProcessKey이기 때문에 KeyPress 이벤트가 일어나지 않기 때문입니다. 그렇기 때문에 텍스트박스에서 포커스가 벗어날때 정규식을 이용해 한번더 체크해줘야 합니다. 키값 8번은 백스페이스 값입니다.

 

자료출처 : C#개발자싸이트

http://www.sky.ph/

 

 

반응형
Posted by blueasa
, |

C# 레퍼런스 모음.

C/C++ 을 하다가 C# 으로 추가 개발을 하려는 사람에게 꼭 필요한 것들을 모아봤음.
직접 해보면서 삽질한 내용임.

C# eBook
http://www.bestsoftware4download.com/software/t-free-c-school-ebook-download-llijghlw.html
http://www.pnasoft.com/archive/2008/01/11/pro-csharp-2008-and-the-net-3-5-platform-4th-edition.aspx

C++ / CLI, Managed C++ eBook
http://int6.net/ebook/Expert.Cpp.Cli.NET.pdf

C# memcpy (링크를 까먹어서 -_- 코드로 대체)


// copied from group.google.com 
public object raw_deserialize_ex(byte[] rawdatas, Type anytype) 
{ 
 int rawsize = Marshal.SizeOf(anytype); 
 if (rawsize > rawdatas.Length) 
   return null; 
 GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned); 
 IntPtr buffer = handle.AddrOfPinnedObject(); 
 object retobj = Marshal.PtrToStructure(buffer, anytype); 
 handle.Free(); 
 return retobj; 
} 
 
// copied from group.google.com 
public byte[] raw_serialize_ex(object anything) 
{ 
 int rawsize = Marshal.SizeOf(anything); 
 byte[] rawdatas = new byte[rawsize]; 
 GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned); 
 IntPtr buffer = handle.AddrOfPinnedObject(); 
 Marshal.StructureToPtr(anything, buffer, false); 
 handle.Free(); 
 return rawdatas; 
}


Block Copy
http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx

Byte[] to String
System.Text.Encoding.UTF8.GetString(...);

String to Byte[]
ASCIIEncoding.UTF8.GetBytes(...);

[Managed C++] System::String^ <-> std::string
http://www.codeguru.com/forum/showthread.php?p=1722705#post1722705

UI Invoke (다른 Thread 에서 ui 를 업데이트 하려면 invoke 를 거쳐가야함.)
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.invoke.aspx
i.e.) this.Invoke(new _set_btn_enable_delegate(_set_btn_enable));

Property Grid
http://msdn.microsoft.com/en-us/library/aa302326.aspx

XML Serializer
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

CRC32, MD5, SHA1
http://www.vbaccelerator.com/home/net/code/Libraries/CRC32/article.asp
http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1cryptoserviceprovider.aspx

Native C++ <-> Unmanaged C++ <-> C#
http://sj21.wo.to/tt/483
http://sj21.wo.to/tt/484
http://blogs.msdn.com/junfeng/archive/2006/05/20/599434.aspx

Application 정보는 System.Application
Environment 정보는 System.Environment

다른 Application 실행시키려면
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.aspx


일단 이정도.

위의 내용만 잘 숙지해도, 기본적인 개발은 할 수 있음.


출처 : http://eeodl.blogspot.com/2008/11/c-managed-c.html

반응형

'Programming > C++/CLI' 카테고리의 다른 글

C++/CLI Type  (2) 2010.09.13
Win32 API TYPE <-> C# TYPE  (0) 2010.07.20
C++/CLI 빌드 시, LNK2019 에러 #3  (0) 2010.06.07
C++/CLI 빌드 시, LNK2019 에러 #2  (0) 2010.06.07
C++/CLI 빌드 시, LNK2019 에러 #1  (0) 2010.06.07
Posted by blueasa
, |


http://blog.naver.com/choco1204/70088176542


자르는 각도가 자유자재군요.
어떻게 처리했을지 궁금..
그나저나..너무 숭덩숭덩 잘리니 타격감이 안느껴지네..
반응형
Posted by blueasa
, |

Visual Assist X 관련 링크~

Link / 2010. 6. 21. 22:14
반응형

'Link' 카테고리의 다른 글

CppCheck(소스 결함 예방 툴)  (0) 2010.10.06
C# 관련 블로그  (0) 2010.08.18
게임브리오 관련 사이트  (0) 2010.06.07
C++/CLI 참고 하는 사이트  (0) 2010.06.03
괜찮아보이는 자료실  (0) 2010.05.14
Posted by blueasa
, |



1) Attach 후 Detach 제대로 안했을 때 나는 에러..

2) 다른 경우도 있으면 추가해야지..
반응형

'Gamebryo > Bug Report' 카테고리의 다른 글

게임브리오 Do_RenderMesh() Warnning Error  (0) 2011.09.01
Posted by blueasa
, |