2010년 4월 15일 목요일

전처리 구문에 대해

#define, #ifndef, #ifdef, #endif... 등등이 쓰이는 이유는

컴파일 하기 처리한다는 뜻이죠.

저 구문들을 먼저 처리한 뒤 컴파일이 이루어집니다.

 

이해를 돕도록 한 가지 예를 들겠습니다.

 

//  먼저 아무 의미 없어보이는 HELLO를 define했습니다.

#define HELLO

 

//  여기서 의미가 생기죠. 이 구문을 해석하면 "HELLO가 define이 되었다면.."입니다. 일반 if와 다르지 않습니다.

#ifdef HELLO

printf("Hello\n");

#else                 // 이건 HELLO가 define되지 않았다면..이 되겠죠

printf("Bye\n");

#endif                // end if 즉 if를 끝낸다...뭐 그런 뜻이죠

 

그럼 이 코드가 어떻게 되냐면..

printf("Hello\n");

이거 하나만 컴파일 됩니다.

 

만약에 printf("Bye\n");를 prif"Bye\n"); 이 따위로 써도 컴파일 시 에러가 안납니다.

 

그럼 왜 printf("Bye\n"); 같이 쓰지도 않을 코드를 써서 낭비하는가...

 

프로그램을 많이 짜다가 보면

어쩔 때는 printf("Hello\n");로 컴파일 해야하고

어쩔때는 printf("Bye\n");로 컴파일 해야할 때가 있습니다.

이게 한 줄이면 모르겠지만...

100줄 1000줄..이러면 일일이 컴파일 할 때마다 주석처리하기 엄청 짜증나겠죠.

이럴 때 #define HELLO만 살짝 손보면 컴파일 결과가 사사삭 바뀌니 엄청 편리합니다.

 

 

그럼 질문하신 부분중에

#ifndef TURBOC_HEADER

#define TURBOC_HEADER

 

ifndef는 if no define...if not define??? 뭐 그런겁니다.

그래서 TURBOC_HEADER가 define되지 않았다면 TURBOC_HEADER를 define해라...

뭐 그런겁니다.

 

이게 왜 필요하냐면..

프로젝트가 커질 수록 헤더파일을 여기 저기서 가져다 쓰게 됩니다.

그럼 컴파일시 같은 내용을 반복해서 컴파일 하게 되고 에러가 발생할 수도 있습니다.

질문하신 코드의 경우 #include문이 여러개 있는데 한번만 하면 될 일을 여러번 할 수도 있다는 겁니다.

분명히 에러의 소지도 있고요. (아주 쉬운 예로 전역변수를 헤더에 선언했다면 바로 에러나겠죠)

 

그래서 TURBOC_HEADER가 define되지 않았다면 define하고 헤더를 컴파일하고..

또 다른 곳에서 헤더를 컴파일 하려고 하면 이미 TURBOC_HEADER가 define 되었으니까

그냥 넘어가겠죠.

MFC같은 것을 할 때는 이런 구조가 기본적으로 생성됩니다. 그만큼 꼭 필요한 구조입니다.

 

#endif는 #ifndef와 쌍이고요..

 

출처: http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040101&docId=68987639&qb=YysrIOunpO2BrOuhnOqwgCDrqLzqsIDsmpQ=&enc=utf8&section=kin&rank=1&sort=0&spq=0

2010년 4월 6일 화요일

[MFC] DoModal() 이란??

비주얼 C++에 다이얼로그는 두가지 종류가 있습니다.

 

한가지가 모달리스 다이얼로그이고...

또 다른 한가지가 모달 다이얼로그입니다.

 

이 두 다이얼로그의 차이는

모달 다이얼로그의 경우는 다이얼로그가 생성되면

자신을 생성시킨 다이얼로그가 활성화되지 않습니다.

 

하지만 모달리스 다이얼로그는 다이얼로그가 생성되더라도

자신을 생성시킨 다이얼로그로 마음대로 왔다 갔다 할 수 있습니다.

 

사실 이게 정확한 설명은 아니지만 대략의 차이점이라고 생각하시면 될 것 같고..^^;;

 

 

DoModal 함수에 대한 간단한 예제를 들면...

 

일단 모달 다이얼로그로 클래스가 생성되어 있다고 하죠...

그 클래스 이름을 "TestClassModal" 이라고 했을 때...

 

다이얼로그를 생성시킬 곳에서는

일단 해당 다이얼로그 클래스의 해더 파일을 포함시켜야 할 거구요..

 

그 다음에는 그 클래스를 선언해 주어야 겠지요~^^

 

TestClassModal   dlg;

 

if (dlg.DoModal == IDOK)   // 다이얼로그가 종료될 때 반환되는 값을 검사, OK 버튼으로 종료되었을 경우 IDOK를 반환

{

      // OK 로 다이얼로그가 종료되었을 경우의 작업 코딩

}

else

{

       // 그렇지 않을 경우의 작업 코딩..

}

 

 

DoModal 함수는 보통 위와 같은 형태로 사용됩니다.

[MFC] CDialog::EndDialog

1. 함수의 원형
 
    void EndDialog(int nResult);
 
 
2. 함수의 기능
 
    CDialog 대화상자를 이용해서 프로그램 하는 경우, 대화상자를 종료시킬 때, 어떤 함수를
    사용해야하는지 고민하는 경우가 종종있습니다. 일반적으로는 OnOK, OnCancel 을 호출해서
    많이 종료시키는데, EndDialog 함수도 대화상자를 종료시킬 때 사용합니다.
 
 
3. 함수의 매개변수에 대한 설명
 
    3.1 nResult
 
        대화상자는 보통 DoModal 이라는 함수를 이용해서 대화상자를 출력하게 됩니다. 그리고
        대화상자가 종료될때 DoModal 함수를 빠져나오게 됩니다. DoModal 이라는 함수는 종료될 때,
        정수형 값을 반환하는데 그 값을 이 변수를 이용해서 지정할 수 있습니다.
 
        일반적으로 대화상자가 종료되었을때, 확인 버튼을 눌러서 종료했는지 또는 취소버튼을 눌러서
        종료했는지를 구분하려면 아래와 같이 코드를 작성하시면 됩니다.
 
        MyTestDlg ins_dlg;
        int return_value = ins_dlg.DoModal();
        if(IDOK == return_value){
            // 확인을 눌러서 대화상자가 종료된 경우를 처리 한다.
        } else if(IDCANCEL == return_value){
            // 취소를 눌러서 대화상자가 종료된 경우를 처리 한다.
        }
 
        위 코드에서 보시는것과 같이 DoModal 함수는 IDOK 또는 IDCANCEL 값을 반환하게 됩니다.
        왜냐하면, 대부분 OnOK, OnCancel 함수로 종료시키기 때문입니다. 하지만, 좀더 효과적으로
        프로그램을 하려고 하다보면 DoModal 함수가 또다른 값을 반환해야 하는 경우도 있습니다.
        이럴때, EndDialog 함수를 호출하고 이 매개변수에 DoModal 이 반환할 값을 명시하면 됩니다.
 
        EndDialog(5);
 
        이렇게 종료하면 DoModal 함수는 5의 값을 반환하게 됩니다.
 
 
4. 함수의 주의사항
 
    EndDialog 함수는 즉각적으로 대화상자를 닫는 함수는 아닙니다. 따라서 EndDialog 함수 아래에
    코드가 있다면 그 코드를 수행합니다. 그리고 EndDialog 함수를 사용한 함수가 종료되는 시점에
    대화상자를 종료 시킵니다.
 
    // m_member_data는 MyTestDlg 클래스의 멤버 변수이고 1의 값을 가진다고 가정하겠습니다.
    void MyTestDlg::CloseMyDlg()
    {
        EndDialog(5);         // 대화상자가 종료되어야 한다는 값을 내부적으로 설정.
                                    // 하지만 이 순간에 종료되지는 않는다.
 
        m_member_data++; // 값을 2로 증가시킨다.
    }  // CloseMyDlg 함수가 종료되면서, CDialog 클래스는 종료상황이 체크된것을 인지하고
       // 대화상자를 종료합니다.