Form1와 Form2를 만들었거든요.

Form1에 값을 Form2에 넘겨서 Form2에 있는 다이얼로그박스에있는 버튼을 누르면 Form1에서 넘겨준

값을 뿌려주는 간단한 프로그램입니다.

 

Form2안에 get,set 코드를 심어주면 잘 되는데.그렇게 하지않구 Data.cs라는 클래스를 하나 만들어서

거기에 get_set을 넣었습니다.어떻게 호출하면 되는지요?

아래와같이 작성했는데 왜 값이 Form2에 안넘어가는지 모르겠네요.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";          
            Frm2.ShowDialog();
         
        }

/***********************************************/

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            Data Dt =new Data();          
            MessageBox.Show(Dt.Ct.ToString());
          
        }

 

/************************************************/

 

/************Data.cs*******************************/

class Data
    {
        string caption;
        public string Ct
        {
            get
            {
                return caption;
            }
            set

            {

               caption = value;

            }
        }
    }

 

/***************************************************/

 

왜 그런지 답을 알려드릴게요.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";          
            Frm2.ShowDialog();
         
        }

/***********************************************/

 

Form1 클래스의 button1_Click 이벤트 핸들러에서 하는 작업은 다음과 같네요.

 

1) Form2 클래스의 인스턴스를 생성

 

2) Data 클래스의 인스턴스를 생성 후 초기화 작업

 

3) 생성된 Form2 클래스의 인스턴스를 화면에 출력. ShowDialog() 메소드 사용.

 

 

자~~ 여기서..

 

1) 2) 과정을 보면,

 

Form2 클래스의 인스턴스와

 

Data 클래스의 인스턴스는

 

아무런 연관 관계가 없다는 거죠.

 

관련점을 찾자면, 이벤트 핸들러의 지역 변수로 설정되었다는 거죠.

 

Form2 클래스의 인스턴스는  Data 클래스의 인스턴스의 참조를 갖고 있지 않으므로,

 

여기서 생성된 Data 클래스의 인스턴스에 절대로 접근할 수 없답니다.

 

 

즉, 지역변수로 인스턴스를 생성했든간에, 뭔가 클래스에 참조로 넘겨주든지 하는게 있어야 하는데,

 

그런게 없으니, 클래스의 인스턴스가 무슨 수로 지역 변수에 접근할 수 있겠냐구요?

 

지역변수를 소개시켜주지도 않았으니 알 턱이 없죠.

 

 

****************************************

예를 들어, 최소한 다음과 같은 코드는 있어야 겠죠.

 

            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";  

 

            frm2.CustomData = a;        // 뭐, 이렇게 설정하는게 있다면야, frm2 에서 CustomData        

                                                     // 프로퍼티로, 데이터를 전달받고 이를 출력할 수 있겠죠.

                                                     // 연관고리가 있어야 한다는 거죠.


            Frm2.ShowDialog();
 

****************************************

 

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            Data Dt =new Data();          
            MessageBox.Show(Dt.Ct.ToString());
          
        }

 

/************************************************/

 

 

Form2 클래스의 button1_Click 이벤트 핸들러에서 하는 작업은 다음과 같네요.

 

 

1) Data 클래스의 인스턴스를 생성.

 

2) 이 인스턴스의 내용을 메시지 박스에 출력

 

 

자~~ 여기서..

 

1) 과정에서 생성한 인스턴스는 완전히

 

별도의 메모리 개체로써,

 

Form1 클래스의 이벤트 핸들러에서

 

생성한 Data 개체와는 하나도 관련이 없죠.

 

무슨 말인지 아시겠죠?

 

각각 Form1, Form2 클래스의 이벤트 핸들러에 있는

 

지역 변수일 뿐이란 말입니다.

 

이벤트 핸들러가 끝나면, 그냥 가비지 컬렉터로 이동되는 변수죠.

 

 

 

자~~ 해결책은 여러가지가 있는데, 매우 간단하게 방법을 알려드리죠.

 

Data 클래스를 매개로 Form1 과 Form2 를 연결하고 싶다고 했죠?

 

그러면, Data 클래스를 static 으로 만들어 볼 수도 있어요.

 

클래스를 static 으로 만들었으면, 그 내부에는 멤버도 모두 static 이 되어야 하죠.

 

이렇게 되면, 일종의 전역 변수 형태가 되죠.

 

Form1 클래스에서도 참조가능하고,

 

Form2 클래스에서도 참조가능하죠.

 

static class Data
{
        static string caption;

        static public string Ct
        {
            get
            {
                  return caption;
            }
            set

            {

                 caption = value;

            }
       }
}

 

 

이제, 이벤트 핸들러를 고쳐봅시다.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
 

           // Data a = new Data();

           // a.Ct = "안녕하세요";          
          

           Data.Ct = "안녕하세요";
            Frm2.ShowDialog();         
        }

 

/***********************************************/

 

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            //Data Dt =new Data();          
            MessageBox.Show(Data.Ct.ToString());
          
        }

 

/************************************************/

'예전것 > .NET Compact Framework' 카테고리의 다른 글

C# : How to Loop PlayList in media player  (0) 2010.01.29
C#에서의 using  (0) 2009.11.06
About Thread (C#) - .net compact framework  (0) 2009.11.02

Application.DoEvent   .. 매니지드 API를 이용한 DoEvents를 모두 처리하는 메소드이다. DoEvents가 호출됐을때, 주 스레드큐에 쌓여 있는 메시지를 모두 처리하는 메소드이다.
DoEvents는 단순한 환경에서는 매우 매력적이다. 특히 코드를 복잡하게하는 스레드의 사용을 피하려는 개발자라면 말이다.
But 매우 위험하다 DoEvents는 메시지큐에 있는 모든 메시지를 처리한 후에 그 다음 코드를 수행하기 때문이다.

윈도우는 매니지드건 네이티브건 컨트롤을 생성한 스레드만이 컨트롤 속성을 변경할 수 있다. (즉, 핸들을 이용한 직접적인 API 호출가능) 다시 말해 윈도우 객체는 스레드 친화성을 가지고있다. 컨트롤의 속성을 읽고 쓰거나 메소드를 호출 하는것도 모두 생성한 스레드 안에서 수행해야 하는것이다. 실질적으로 주 스레드에서만 컨트롤을 터치할 수 있고 작업자 스레드에서는 그렇지 못하다. 그럼 작업자 Invoke(또는 BeginInvoke) 메소드를 호출해서 유저인터페이스를 업데이트 할 수 있다.

Invoke
Invoke 메소드는 전달 받은 대리 함수를 큐에 저장한 후 애플리케이션 메시지큐에 사용자 윈도우 메시지를 보낸다. 메시지가 처리되면서 수행되는 메소드는 내부 함수를 호출 하면서 컨트롤에 이를 알려준다. Thread Method(물론 주 스레드에서 실행되는)의 컨트롤은 내부큐에 존재하는 대리함수 들을 실행한다.


.net framework 에서는 BackgroundWorker 라는 편리한 것을 제공
위는 .net compact framework에 기초한것임

'예전것 > .NET Compact Framework' 카테고리의 다른 글

C# : How to Loop PlayList in media player  (0) 2010.01.29
C#에서의 using  (0) 2009.11.06
C# 전역변수 사용법 (폼 간에)  (0) 2009.11.04
예전것/SmartPhone2009. 10. 29. 01:04
설치중 장치를 찾지 못한다면 이렇게해보자

ㅇ 일단 옴냐를 끄세요
ㅇ End를 누른채 켜시면 데이터모드로 뜹니다.
ㅇ 이떄 미츠업그레이드를 실행하면 CDMA 드라이버가 깔립니다.
ㅇ 다시 리부팅 하시고 업그레이드 하시면 됩니다

 

'예전것 > SmartPhone' 카테고리의 다른 글

iphone touch event  (0) 2010.06.24
Device Emulator Manager 가 없을때  (0) 2009.11.14
카테고리 없음2009. 10. 19. 00:15
예전것/프로그래밍2009. 10. 16. 18:22

virtual은 3가지 정도로 사용됩니다. OOP에 대한 개념이 잡혀있어야 설명을 제대로 이해하실 수 있을텐데.. 최대한 쉽게 설명 해보도록 하죠. 

일단 OOP 개념 중 클래스 상속에 대한 것은 잘 아실겁니다. 이마저도 모르신다면 virtual에 대해서는 전혀 궁금해하실 필요가 없으니 그냥 넘어가시면 되구요.. 진도를 앞서나가는 호기심은 해롭습니다! :-) 

class Bird {

    // 중략

}; 

class Chicken : public Bird {

    // 중략

}; 

class Eagle : public Bird {

    // 중략

};

 

와 같은 구조가 있다고 합시다.

C++에서 public 상속은 is-a 관계로 설명할 수 있는데 쉽게 말하자면 Chicken is a Bird. 입니다. 

따라서 Bird *pBird = new Chicken; 과 같이 Chicken 인스턴스(클래스가 실체화된 것)를 Bird 객체에 대입할 수 있습니다.  이를 다형성(polymorphism)이라고 하고요. 

이런 지식을 깔아놓고 시작하죠.

1. 순수 추상(pure abstract, 혹은 순수 가상pure virtual) 함수 선언으로서의 virtual

순수 가상 함수란 함수 바디를 가지지 않은 함수를 말하며 그러한 함수를 가지고 있는 클래스를 추상 클래스(abstract class)라고 합니다. 

그럼 abstact 시리즈는 어디서 쓰는가? 에 대한 예를 하나 들어보죠. 

모든 Bird를 상속받은 객체는 bool canFly(); 란 멤버함수를 가지고 있다고 합시다. 이름만 봐도 알겠지만, 날 수 있으면 true, 못날면 false를 리턴합니다. 

그럼 canFly() 멤버함수는 Chicken에서도 쓸 수 있어야 하고 Eagle 객체에서도 쓸 수 있어야 합니다. 하지만 이걸 Bird 클래스에 정의할 수는 없습니다. 당연하잖아요? Chicken은 false고 Eagle은 true인데요. 아, 여기서 Overriding을 생각하셨다면 아주 깊은 이야기까지 꺼내야 해서 좀 난감해지는데요. 순수 가상 함수를 정의하는 것과 단순히 Overriding하는 것은 객체 지향 설계상의 미묘한 차이가 있고, 뒤에서 설명할 virtual의 쓰임새 2.와도 관련이 있는데, 그냥 간단하게 생각해서 지금 이 경우는 Bird 객체에서 canFly() 함수가 할 일은 없으므로 순수 가상 함수로 선언하는 것이 맞습니다.  

또 한가지 더, 그렇다면 그냥  Bird 클래스에 canFly()를 선언할 필요없이 Chicken 클래스랑 Eagle 클래스에 따로 만들어주면 될 것 아닌가? 라는 생각을 하실 수도 있습니다. 이렇게 되면 다형성을 이용해 Bird 객체에 Chicken이나 Eagle 객체를 담았을 때 canFly() 함수를 호출할 수 없게 됩니다. 즉, 다음의 코드가 불가능합니다. 

Bird* pBird = new Chicken();

pBird->canFly(); // Bird 클래스 선언에는 canFly() 함수가 없습니다! 

따라서 반드시 Bird 클래스는 canFly()에 대한 정의를 가져야 합니다. (사실 여기에도 다른 문제가 존재하는데, 이건 virtual 사용 용도 2. 번에서 살펴봅니다.) 

즉, Bird를 상속받는 모든 클래스들은 canFly() 함수를 구현할 의무를 지닌다.. 정도가 되겠습니다. 물론 구현 안할 수도 있습니다. 그렇다면 그 클래스도 결국 추상 클래스가 되죠. 어쨌든, 이런 함수가 필요는 한데, 실제 구현은 자신을 상속받는 클래스들에게로 미루는 것이 바로 순수 가상 함수입니다. 선언은 아래와 같이 됩니다.

 

class Bird {

    public:

        virtual bool canFly() = 0;

        // 이렇게 하면 순수 가상 함수로 선언되고

        // Bird는 인스턴스화가 불가능한 추상 클래스가 됩니다.  

};

 

class Chicken : public Bird {

    public:
        // 여기서 실제로 구현해줍니다.
        bool canFly()
        {
             return false;
         }
};

 

class Eagle : public Bird {

   public:
        // 여기서 실제로 구현해줍니다.
        bool canFly()
        {
             return true;
         }
};

 

이렇게 선언해놓으면, 다형성을 이용하여 Bird 객체(라는 용어가 맞지는 않습니다. 실제로 생성되는건 Bird 객체가 아니라 Chicken이나 Eagle 객체이기 때문입니다. 하지만 그냥 이렇게 이야기하도록 하죠) 에서 canFly() 함수를 호출하게 되는겁니다. 물론, 실제 호출되는 함수는 Bird 객체가 실제로 어떤 객체를 담고 있었느냐에 따라 C++이 자동으로 호출하게 됩니다. Bird에서 canFly()는 순수 가상 함수이기 때문에 자동으로 2. 에서 설명하는 동적 바인딩을 사용하게 됩니다.

 

그리고 앞서도 말했지만 순수 가상 함수를 가진 추상 클래스인 Bird는 실제로 객체를 생성(인스턴스화)할 수 없고 오직 포인터나 레퍼런스등의 용도로만 사용할 수 있습니다. 이게 무슨 필요냐.. 하실 분도 계시겠지만, 객체 지향 개념에서 가장 요긴하고 중요한 개념 중 하나입니다. 내공이 깊어지면 이해되실겁니다. 

2. 상속, Overriding과 관련하여 동적 바인딩을 지시하기 위한 virtual

C++은 기본적으로 함수 호출에 정적 바인딩을 사용합니다. JAVA는 기본이 동적 바인딩이죠. 그렇다면 정적 바인딩과 동적 바인딩은 어떤 것인가? 에 대해 알아봅시다.

 예를 들어 우리가 아래와 같은 함수 호출을 한다고 합시다.

 

void doSomething(int a, int b)
{
    printf("%d, %d\n", a, b);

이 경우 컴파일러가 컴파일(일반적으로 말하듯이, 링킹 과정도 포함하는 것으로 합시다. 정확한 용어는 빌드죠)할 때 printf가 무엇인지는 명확합니다. 즉, 프로그램이 실행되면서 저 코드에서 호출하는 printf() 함수가 다른 것으로 바뀔 리는 없다는거죠. 

 

class Bird {

    public:

        string getName { return string("Bird"); }

};

 

class Chicken : public Bird {

    public:

        string getName { return string("Chicken"); }

};

 

class Eagle : public Bird {

   public:

        string getName { return string("Eagle"); }

};

 

void doSomething (Bird* pBird)

{

    cout << pBird->getName() << endl;

}

 

우리가 doSomething() 함수를 호출할 때는 다음 3가지 정도의 경우를 생각해볼 수 있습니다.

 

1) Bird 객체로 호출하는 경우

Bird bird;

doSomething(&bird);

 

2) Chicken 객체로 호출하는 경우(다형성)

Chicken chicken;

doSomething(&chicken);

 

3) Eagle 객체로 호출하는 경우(다형성)

Eagle eagle;

doSomething(&eagle);

 

그렇다면 우리가 원하는 doSomething() 호출 결과는 어떤 것일까요? 당연히 1)의 경우 "Bird"이고 2)는 "Chicken" 3)은 "Eagle" 이겠죠. 하지만 앞서 말했듯이 C++은 기본적으로 정적 바인딩을 사용합니다. 즉, 컴파일할 때 doSomething() 함수의 pBird는 Bird 객체이고, 따라서 무조건 Bird 클래스의 getName() 메서드를 호출하도록 만들어버립니다. 따라서, 실제로는 1)이던 2)던 3)이던 무조건 "Bird"가 출력됩니다. 이는 우리가 원하는 결과가 아닙니다. 따라서, "프로그램 실행 중 pBird가 실제로 가지고 있는 객체의 타입에 맞는 메서드 - 멤버 함수 - 를 호출" 해야할 필요가 있습니다. 이를 동적(실행 시간에 결정한다고 하여) 바인딩이라고 부르고, 이를 사용하기 위해서 virtual 키워드를 씁니다. 즉, 아래처럼 합니다.

 

class Bird {

    public:

        // 기반 클래스에만 virtual 키워드를 써주면 됩니다.

        virtual string getName { return string("Bird"); }

};

 

class Chicken : public Bird {

    public:

        string getName { return string("Chicken"); }

};

 

class Eagle : public Bird {

   public:

        string getName { return string("Eagle"); }

};

 

void doSomething (Bird* pBird)

{

    cout << pBird->getName() << endl;

}

 

이렇게 하면, 컴파일러는 실행 시간에 pBird가 어떤 객체의 포인터를 가지고 있는지를 판단하여 적절한 함수를 호출해주게 됩니다.

 

얼핏 보면 동적 바인딩이 더 좋아보이는 것 같지만, 실제로 동적 바인딩을 위해 컴파일러는 여러가지 정보를 추가적으로 유지해야 해서, 메모리 사용량과 수행 속도 면에서 약간의 손해를 보게 됩니다. JAVA가 대체적으로(대체적으로 입니다. 네이티브 컴파일링하면 이렇고 저렇고 태클 사양합니다) C++보다 느린 이유 중 하나가 기본적으로 동적 바인딩을 사용하기 때문입니다.

 

3. 다이아몬드형 상속에서 가상 기반 클래스 선언을 위한 virtual

다이아몬드 상속이란, 같은 기반 클래스를 가진 두 클래스를 동시에 상속받는 것을 이야기합니다. C++은 다중 상속이 가능하기 때문에 이런 문제가 발생하죠. 이러한 다중 상속은 득보다 실이 많다 하여 최근의 OOP 언어인 JAVA나 C#등에서는 지원하지 않습니다. 대신 interface 같은 것을 사용하죠.

 

어쨌든, 다이아몬드 상속의 예를 들어보겠습니다.

 

class A {

    // ...

};

 

class B : public A {

    // ...

};

 

class C : public A {

    // ...

};

 

class D : public B, public C {

    // ...

};

 

이런 형태의 상속은 기반 클래스 A가 B와 C에 각각 존재하므로 공간 낭비, 함수 호출 대상 모호 등의 문제점을 지니게 됩니다. 이를 해결하기 위해 가상 기반 클래스(virtual base class)를 사용하는데, virtual 키워드는 바로 이 가상 기반 클래스를 나타내기 위해 쓰입니다. 위 코드에서 가상 기반 클래스를 사용하면,

 

class A {

    // ...

};

 

class B : virtual public A {

    // ...

};

 

class C : virtual public A {

    // ...

};

 

class D : public B, public C {
    // ...

};

이렇게 됩니다. 

이 설명이 부족하다면, MSDN http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_pluslang_Virtual_Base_Classes.asp 을 참고하세요.

참고:
http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10104&docid=1355919&qb=YyMgdmlydHVhbA==&enc=utf8&pid=fWlG3loi5UhsssUA5c8sss--225492&sid=Stg43iY22EoAADYhI9k

여기서 긁었음

예전것/프로그래밍2009. 10. 2. 02:28

int WINAPI WinMain(...) 이것이 원래는  [ == int APIENTRY WinMain(...) ]

int FAR PASCAL WinMain(...) 이거였다고 하네요

WinMain() 함수는 프로그램 내에서 누가 호출하는 것이 아니고
윈도우 시스템에서 호출하는 함수인데

윈도우 시스템은
1. 64KByte를 넘는 포인터를 쓸 수 있는 시스템이고 : FAR
2. 함수 호출 방식이 PASCAL 방식입니다. : PASCAL

 

초기에는 FAR PASCAL WinMain(...) 이랬다가
FAR PASCAL 을 WINAPI로 바꿔쓰자 해서
요즘에는 WINAPI WinMain(....) 이라고 하네요. . --;; 복잡혀. .

결론 :
WINAPI == FAR PASCAL == APIENTRY

(Windef.h <-- 여기에 정의 되어 있습니다.)

 

' PASCAL 이란' __cdecl의 반대란 뜻인데
PASCAL이나 __cdecl은 에.... 일단은 함수 호출할 때'
함수의 인자가 호출되는 순서를 정하는 거라고 보시면 됩니다.

즉' __cdecl은 함수의 인자가 오른쪽에서 왼쪽으로 호출되고
PASCAL(__pascal)은 거꾸로 왼쪽에서 오른쪽으로 호출되고

원래 C 언어는 함수 호출할 때' 예를들어'
funcA(10' 20' 30) 이런식이다 하면....
funcA를 호출하면서' 30을 먼저 메모리에 넣어 주고'
다음으로 20' 마지막으로 10을 메모리에 넣어 주죠...

이 C언어와 같은 방식을 __cdecl이라 하고....

반대로 funcA(10' 20' 30)을 호출할때'
메모리에 10' 20' 마지막으로 30을 넣어주는 방식을
파스칼 방식이다... 해서 PASCAL(__pascal)이라고 하죠.

 

PASCAL 방식은 첫번째 목적은 다른 언어로 짜여진 obj 파일과 링크를 하기

위해서 존재하는 표현식이라고 할 수 있습니다.

그렇지만 VC++ 에서 많은 API 들이 이 PASCAL 방식의 호출을 사용한다고

알고 있습니다.

사실인지는 모르겠지만. . 이 방식이 표준 C 방식보다 호출이 빠르다고 하네요.

예전것/프로그래밍2009. 10. 1. 01:21

http://www.winapi.co.kr/project/library/gdiplus/1-1.htm

http://www.winapi.co.kr/

direct mobile 이란것도 생각해보자

http://xenostudy.tistory.com/27

===============전체 화면하기 ==========
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=7083&MAEULNo=911&no=42261&ref=42250
이곳 참조 ..
데브피아가 답이다.

        case WM_ACTIVATE:
            SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
   MoveWindow(hWnd, 0, 0, 240, 320, TRUE);
   SHFullScreen(hWnd, SHFS_HIDETASKBAR);
            break;
        case WM_SETTINGCHANGE:
            SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
   MoveWindow(hWnd, 0, 0, 240, 320, TRUE);
   SHFullScreen(hWnd, SHFS_HIDETASKBAR);
            break;

예전것/프로그래밍2009. 9. 12. 21:03

http://windowsmobile7.tistory.com/2
여기에 자세히 나와있다.
예전것/프로그래밍2009. 9. 12. 20:36

C:\Program Files\Microsoft Device Emulator\1.0
요기 경로에있다... 후 힘들었다.
카테고리 없음2009. 9. 12. 10:11

MIP 맵핑의 기본 개념은 여러가지 크기의 밉맵(MIP MAP-동일한 그림의 다양한 사이즈의 그림) 을 만들어 놓고 맵핑하고자 하는 폴리곤에 가장 근사한 크기를 갖는 밉맵을 이용하여 텍스쳐맵핑을 수행하는 것을 MIP 맵핑이라한다. 

더 자세히 표현하면, 텍스쳐를 일단 각기 다른 크기로 세 개 또는 그이상의 개수를 제작한다. 그리고 원하는 폴리곤의 크기와 가장 비슷한 크기의 텍스쳐를 우선적으로 이용하여 텍스쳐 맵핑을 하는 방식이며, 이때 가장 가까운 정도에 따라 가중치를 두며 이 값을 MIP Level이라고 한다.

그림이 확대 될 때에는 interpolation 기법이 이용되지만 축소에 의해서는 그림의 화질 저하가 심하게 이루어 지며 또한 세밀한 그림의 경우에 실시간 계산에 의한 처리는 그림 자체의 모양이 변해버리기 때문에 상당히 고민이 되는 부분이다.

실제로 이 방식을 이용할때는 별도의 하드웨어적 지원없이, 프로그램을 만드는 사람이 미리 고해상도용과 저해상도용으로 별도의 텍스쳐를 만들어 놓고 이 텍스쳐를 사이즈에 맞게 필요에 따라 이용하면 된다.

이렇게 하는 작업은 실시간으로 하지 않고 미리 해도 되는 작업이다. 대부분의 2D용 게임에서 보면 고해상도용과 저해상도용의 두가지의 스프라이트를 모두 가지고 있는 경우가 많다. 

그럼 MIP-MAP을 왜 사용하느냐? 텍스쳐를 축소할때 기계식 축소의 화질변화 를 막기 위해여 만들어진 것이다. 즉, 확대시에는 Linear 필터링을 이용하여 적절히 처리할 수 있지만 축소는 적절한 방법이 마땅치가 않다. 따라서 의외로 MIP-MAP을 사용하는 주요 이유는 이미지의 '확대'에서 일어나는 문제보다는 '축소'에서 일어나는 문제 때문에 대두 되었다고 봐야한다. 

그럼 일단 이러한 밉맵을 사용하고 위해서는 여러벌(?)의 밉맵이 준비되어야 한다.

보통 밉맵은 5~8가지 정도의 동일한 그림, 다른 사이즈의 밉맵을 준비하게 되는데 밉맵 레벌 0번의 크기가 1이라고 하면 밉맵레벨 1번의 경우는 0번의 1/4의 크기가 되며 밉맵레벌 2는 다시 1번의 1/4크기의 형식으로 한변이 1/2 크기씩 계속 감소하게 되는 방식으로 미리 밉맵을 제작하게 된다. 또한 MIP Mapping을 위해서는 일반 경우보다 1.5배 이상의 텍스쳐 메모리를 사용하게 된다. 허나 단순하게 밉맵의 크기를 최대 8개까지 준비한다고 해도 모든 크기의 오브젝트에 대응할 수는 없다.

실제로 게임중의 오브젝트는 관찰자의 거리에 따라 거의 연속적으로 변하며 8벌이 아니라 80벌이 되어도 일일히 미세하게 변화하는 오브젝트에 자신이 100% 원하는 텍스쳐를 입히는 것이 원리적으로 불가능하다. 따라서 적절한 크기의 밉맵을 준비하고 그 나머지 부분은 일종의 이미지 보간 작업을 수행하게 되는데 그것이 Filtering인 것이다. 사실 요즘에 와서는 filtering이 MIP MAPPING과 다소 혼동되어서 쓰이기는 한다.