[MFC] 태스크 대화상자(Task Dialog) - (2/3) : 사용하기

MFC 2010. 2. 15. 09:00 Posted by 알 수 없는 사용자

Intro
안녕하세요. MFC 카테고리의 꽃집총각 입니다. 이번에는 지난번 포스팅 [MFC] 태스크 대화상자(Task Dialog) - (1/3) : 기능 소개 편에 이어서, 사용하기 편을 준비했습니다.
이번 포스팅에서 다룰 내용은

  1. 비스타 이전 OS에서 태스크 대화상자 이용에 대한 이슈
  2. 태스크 대화상자의 기본적인 구성
  3. 소스코드 한 줄로 태스크 대화상자 사용하기 - ShowDialog 함수.

이렇게 세 가지 내용을 알아보도록 하겠습니다. 3번 ShowDialog 함수의 소개가 이번 포스팅의 주된 내용입니다. 태스크 대화상자를 사용하기 위해서는 CTaskDialog의 객체를 생성해 DoModal() 함수를 실행하는 방법과, 객체를 생성하지 않고 간단히 CTaskDialog::ShowDialog(...) 함수를 이용하는 방법이 있습니다. 후자는 간편하게 함수호출 한번으로 태스크 대화상자를 이용할 수 있는 장점이 있고, 전자는 보다 디테일한 설정 및 활용이 가능하다는 장점이 있습니다. 오늘은 간단한 사용법인 ShowDialog 함수에 대해 알아보고, CTaskDialog의 객체를 선언하는 방법은 다음 포스팅에서 별도로 다루도록 하겠습니다.



CTaskDialog::IsSupported() - 비스타 이전 OS들을 위한 대비
본격적인 CTaskDialog의 기능들을 알아보기 전에, 먼저 한가지 정리해야 할 점이 있습니다. 이전 포스팅에서 짧게 언급한 바 있지만, 태스크 대화상자는 비스타 이전 OS에서는 제공되지 않습니다. 그래서 만약 개발한 응용프로그램이 윈도우 XP 등에서 실행된다면 태스크 대화상자 출력 시점에 오류를 일으킵니다.  

(그림 1) 윈도우 XP에서 태스크 대화상자 출력을 시도할 때 나오는 오류 화면.


그렇기 때문에 개발한 프로그램이 비스타 이전 OS에서도 실행되어야 한다면 이런 경우를 위한 별도의 처리를 직접 해주어야만 합니다. 이럴 땐 어쩔 수 없이 기존의 메세지 박스나, CDialog를 상속받은 클래스를 직접 제작해 주어야 겠지요.
이런 처리를 찾아볼 수 있는 좋은 예가 바로 인터넷 익스플로러 8.0의 '세션 복구 기능' 입니다. 익스플로러 8.0은 비정상 종료되었다가 실행되는 경우 이전에 열려있던 페이지를 자동 복구할 것인지를 물어보는 창을 띄우는데, 실행중인 윈도우가 비스타 이전 버전이라면 일반 대화상자를, 비스타 이후 버전이라면 태스크 대화상자를 출력합니다.

(그림 2) 인터넷 익스플로러 8.0의 세션복구 기능에서 쓰인 태스크 대화상자.


(그림 3) 비스타 이전 OS에서는 태스크 대화상자 대신 기존의 대화상자를 출력합니다.


이런 식으로 OS 차원의 태스크 대화상자 사용 가능여부를 확인하고자 할 때에는, 직접 OS의 버전을 얻어와서 기능 지원 여부를 판별할 수도 있겠지만 CTaskDialog::IsSupported() 정적 함수를 이용해서 쉽게 확인할 수 있습니다.

if( CTaskDialog::IsSupported() ) // 태스크 대화상자 사용 가능 여부를 확인
{
    // 태스크 대화상자 호출.
    CTaskDialog::ShowDialog(message, emptyString, title, 0, 0, TDCBF_OK_BUTTON);
}
else
{
    // 지원하지 않는 OS인 경우는 예전 방식으로 처리.
    AfxMessageBox(message);
}
(코드 1) CTaskDialog::IsSupported() 함수를 통해 태스크 대화상자 사용 가능 여부를 확인.

참고로 윈도우 서버 2008은 비스타 이전에 나온 OS이므로 태스크 대화상자를 사용할 수 있습니다. 물론 비스타나 윈도우 7 처럼 예쁜 모양은 아니지만요 ^^;

(그림 4) 윈도우 서버 2008에서 출력되는 태스크 대화상자의 모습. 출처 : http://mariusbancila.ro/blog/2009/03/10/task-dialog-in-mfc/

 


태스크 대화상자의 기본적인 구성
태스크 대화상자는 기본적인 구성은 MSDN에 있는 아래의 샘플 스크린샷에 아주 잘 나타나 있습니다.

(그림 5) 태스크 대화상자의 기본적인 구성. (출처 : MSDN)


(그림 5)에서 알 수 있듯이 태스크 대화상자는 다양한 컨트롤들과 기능들을 제공합니다. 오늘은 우선 예전 AfxMessageBox() 수준의 심플한 사용방법을 알아보겠습니다. 간단한 메세지를 사용자에게 노출하거나, 기본적인 버튼을 통해 사용자 입력을 받아오고자 할 때는 오늘 소개하는 ShowDialog 함수를 이용하는 것이 좋습니다.


첫 번째 예제 : 일단 한 번 띄워봅시다
자, 이제 정말로 태스크 대화상자를 사용하기 위한 방법을 알아보죠. 가장 간단하게 태스크 대화상자를 출력하는 방법은 정적 함수인 CTaskDialog::ShowDialog() 를 사용하는 방법입니다. 이 함수를 사용하면 CTaskDialog의 객체를 만들지 않고도 바로 태스크 대화상자를 띄울 수 있습니다.
일단 속 시원하게 코드부터 보겠습니다! ShowDialog 정적 함수를 이용한 코드와, 실제 출력된 태스크 대화상자의 모양입니다.

INT_PTR ret = CTaskDialog::ShowDialog( L"본문 들어가는 곳", L"제목 들어가는 곳", L"타이틀 적는 곳", IDS_STRING102, // 첫 번째 커맨드 버튼. IDS_STRING104 ); // 마지막 커맨드 버튼. if( ret == IDYES ) { // blah blah... }

(코드 2) 드디어 등장했습니다! 태스크 대화상자를 띄우는 첫 번째 코드입니다!

(그림 6) (코드 2)를 통해 출력한 태스크 대화상자의 모습.


태스크 대화상자의 설명을 위해 두 차례나 걸친 포스팅에서 수없이 떠들었던 것에 비해, 너무나도 단순합니다. 그냥 함수 호출 하나 했더니 뜨는군요. 제목, 본문, 타이틀을 설정하는 것은 인자로 직접 문자열을 넣어주고 있으므로 추가 설명이 없이도 쉽게 확인하실 수 있습니다.
스크린샷을 보면 우리의 첫 번째 태스크 대화상자에서는 세 개의 커맨드 버튼을 가지고 있습니다. 커맨드 버튼은 예, 아니요, 확인, 취소 등과 같은 기존 대화상자의 기본적인 버튼 이외에 자유로운 출력 문자열을 설정할 수 있는 의사 입력 버튼 입니다. 태스크 대화상자의 가장 중앙부에 위치하며, 사실상 태스크 대화상자에서 가장 중요한 컨트롤이라고 할 수 있습니다. ShowDialog 함수를 이용할 때 커맨트 버튼을 넣기 위해서는 응용 프로그램의 리소스 파일에 있는 스트링 테이블을 참조합니다. 스트링 테이블에 커맨드 버튼의 설명으로 사용할 문자열들을 차례로 입력하고, 해당 스트링 아이디의 처음과 마지막 값을 ShowDialog의 네 번째, 다섯 번째 인자로 넣어줍니다.

(그림 7) 커맨드 버튼을 추가하기 위해 스트링 테이블을 사용하는 예시.


(그림 6)이 우리의 첫 번째 대화상자 예시에 쓰인 스트링 테이블 입니다. 태스크 대화상자에는 스트링 테이블의 문자열이 출력되고, 사용자가 해당 커맨드 버튼을 선택한 경우 ShowDialog의 리턴값으로 스트링 ID가 반환됩니다. 예제의 세 번째 커맨드 버튼처럼 화면에 여러 줄의 텍스트를 출력하고 싶다면 문자열 안에 개행문자를 이용해 여러 줄의 텍스트를 넣어주면 됩니다.



CTaskDialog::ShowDialog(...) 함수를 좀 더 자세히 알아봅시다.
ShowDialog 함수의 인자는 모두 8개 입니다. 예제에서는 다섯개의 인자만을 사용했고 나머지 인자들은 기본값이 쓰였습니다. 함수의 전체적인 기본형은 아래와 같습니다.  

static INT_PTR CTaskDialog::ShowDialog(
   const CString& strContent,
   const CString& strMainInstruction,
   const CString& strTitle,
   int nIDCommandControlsFirst,
   int nIDCommandControlsLast,
   int nCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON,
   int nTaskDialogOptions = TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS,
   const CString& strFooter = _T("")
);

다섯 번째 인자까지는 설명이 되었으니 나머지 인자를 보자면,
  • nCommonButtons : 태스크 대화상자 오른쪽 하단에 출력되는 기본 버튼들을 설정합니다. 기본값으로 '예', '아니오' 두 개의 버튼이 출력됩니다.
  • nTaskDialogOptions : 태스크 대화상자의 여러가지 옵션을 조절할 수 있는 인자입니다. 옵션에 대한 플래그 값은 아래에서 보다 자세히 설명합니다.
  • strFooter : 태스크 대화상자의 가장 아래쪽에 출력되는 꼬릿말 부분입니다.
기본 버튼으로 설정할 수 있는 플래그는 총 여섯가지이고, CommCtrl.h에 정의되어 있습니다.
  • TDCBF_OK_BUTTON - 확인
  • TDCBF_CANCEL_BUTTON - 취소
  • TDCBF_YES_BUTTON - 예
  • TDCBF_NO_BUTTON - 아니오
  • TDCBF_RETRY_BUTTON - 재시도
  • TDCBF_CLOSE_BUTTON - 닫기
태스크 대화상자의 옵션을 조절할 수 있는 플래그는 총 열 여섯가지이고, 역시 CommCtrl.h 파일에 정의되어 있습니다. 이 중에서, ShowDialog() 함수와 함께 쓰일 수 있을 만한 플래그 몇 가지만을 정리해 보면 아래와 같습니다.
  • TDF_ENABLE_HYPERLINKS
    하이퍼 링크를 활성화 합니다. 텍스트에 하이퍼 링크를 넣고 싶을 때에는 문자열에서 <a href=\"http://vsts2010.net\">하이퍼 링크</a>처럼 HTML 문법으로 설정할 수 있습니다.
  • TDF_ALLOW_DIALOG_CANCELLATION
    태스크 대화상자의 오른쪽 상단에 창 닫기 버튼이 생기고, Esc키나 Alt + F4로도 창을 끌 수 있게 됩니다. 닫기버튼이나 키보드 조작으로 창을 닫은 경우는 IDCANCEL이 리턴됩니다.
  • TDF_USE_COMMAND_LINKS
    커맨드 버튼을 사용하도록 설정합니다. 이 플래그가 설정되지 않으면 커맨드 버튼으로 설정한 버튼들도 기본 버튼들처럼 출력됩니다.
  • TDF_USE_COMMAND_LINKS_NO_ICON
    커맨드 버튼에 아이콘을 출력하지 않고 텍스트만 표시하게 설정합니다.
  • TDF_SHOW_PROGRESS_BAR
    프로그레스바 컨트롤을 표시합니다.
  • TDF_SHOW_MARQUEE_PROGRESS_BAR
    프로그레스바 컨트롤을 Marquee 형식으로 출력합니다.
  • TDF_POSITION_RELATIVE_TO_WINDOW
    태스크 대화상자를 부모 윈도우의 중앙 위치에 나타나도록 합니다. 이 플래그가 설정되지 않으면 바탕화을 기준으로 중앙 위치에 출력됩니다.
  • TDF_RTL_LAYOUT
    태스크 대화상자에 출력되는 텍스트들을 오른쪽에서 왼쪽으로 출력합니다.
  • TDF_CAN_BE_MINIMIZED
    태스크 대화상자의 오른쪽 상단에 최소화 버튼이 생기고, 버튼을 누르면 창이 최소화 됩니다.
위의 아홉가지 플래그 정도가 ShowDialog 함수를 이용한 간단한 사용시에도 유용하게 쓰일만한 기능들 입니다. 이 중에 프로그레스바와 관련된 플래그 같은 경우, TDF_SHOW_PROGRESS_BAR를 넣어주면 실제로 프로그레스바가 표시되지만, 프로그레스바의 값을 조절한다거나, 오류상태를 표시하는 등의 세밀한 처리를 하는 것은 어렵습니다. 이런 경우는 ShowDialog 함수를 통한 호출보다는 직접적으로 CTaskDialog 의 객체 혹은 CTaskDialog 파생클래스의 객체를 만들어서 처리해야 합니다. TDF_SHOW_MARQUEE_PROGRESS_BAR 플래그로 Marquee 형식을 출력할 수도 있지만 이런 경우도 대게는 타이머를 설정하고 자체적으로 동작이 진행중임을 표시하기 위해 주로 사용하므로, 이또한 ShowDialog를 통한 출력에는 생뚱맞습니다.

(그림 8) 예제 대화상자에 꼬릿말과 프로그레스바를 추가한 모습.


위의 (그림 8) 스크린샷을 봅시다. 꼬릿말은 그럭저럭 쓸만 하다고 하지만, 텅 빈 프로그레스바는 보는 이의 마음까지 황량하게 만듭니다. 아무래도 좀 더 추가적인 처리가 필요해 보입니다. ShowDialog 함수를 통해서도 프로그레스바 컨트롤을 출력할 수는 있지만, 이를 세밀하게 제어하는 것은 무리입니다. 이를 포함해 여러가지 컨트롤의 처리에 대한 내용은 다음 포스팅에 설명하도록 하겠습니다.



Outro
이번 포스팅 에서는 태스크 대화상자 미지원 OS를 식별하는 방법과, 태스크 대화상자의 기본적인 구성, 그리고 메시지 박스 수준의 간단한 태스크 대화상자 출력방법을 알아보았습니다. 정적 함수 ShowDialog()를 사용하면 AfxMessageBox()를 이용하는 것보다 좀 더 다양하게 머릿말, 본문, 꼬릿말 등으로 구분에 메세지를 설정할 수 있고, 모던한 디자인의 레이아웃을 갖춘 태스크 대화상자를 출력할 수 있습니다.
다음 포스팅에서는 태스크 대화상자가 제공하는 다양한 컨트롤 들을 활용할 수 있는 방법을 알아보도록 하겠습니다. 리소스 에디터로 직접 다이얼로그를 디자인하던 불편함에서 벗어나 함수호출 몇 줄만으로 다양한 기능을 추가하는 방법들을 정리할 예정입니다. 보다 미리 관련 내용을 확인하고 싶으신 분들은 MSDN(http://msdn.microsoft.com/en-us/library/bb760441(VS.85).aspx)과 다음의 페이지( http://www.nuonsoft.com/blog/2009/06/10/ctaskdialog-in-mfc-in-visual-c-2010/ )를 참고하시기 바랍니다.
그럼 다음 포스팅에서 뵙겠습니다.
감사합니다 ^^*


Reference