본문 바로가기

공부/윈도우api

[윈도우 api] 대화상자

반응형

대화상자

사용자와의 대화

간단한 컨트롤로느 사용자로부터 복잡한 정보를 입력받기 어려운데 많은 양의 정보를 효율적으로 입력받기 위해 주로 대화상자(컨트롤의 컨테이너)를 사용

대화상자는 프로그램과 사용자간의 대화, 곧 명령 및 정보 전달을 위한 특별한 윈도우

 

대화상자의 종류

1. 모달형

    : 대화상자를 닫기 전에 다른 윈도우로 전환할 수 없으며 반드시 확인버튼이나 취소버튼을 눌러

      대화상자를 닫아야 다른 윈도우로 전환할 수 있음

다른 프로그램으로는 전환 가능

MessageBox()함수에 의해 만들어지는 메세지 박스도 모달형 대화상자

2. 모델리스형

    : 대화상자를 열어 놓은 채로 다른 윈도우로 전환할 수 있는 대화상자

 

대화상자를 만들기 위해 필요한 것

1. 대화상자 템플릿

    : 대화상자의 모양과 대화상자 내의 컨트롤 배치 상태가 저장되는 이진정보이며 리소스로 저장

      차일드 윈도우에 대한 정보 데이터의 집합, 이 정보는 차후 CreateWindow로 차일드를 생성할 때 사용

2. 대화상자 프로시저

    : 대화상자 프로시저는 대화상자에서 발생하는 메세지를 처리

      대화상자 내에서 발생하는 메세지들을 처리하는 콜백함수

      Wndproc에서 이 함수를 참조하므로 WinMain과 WndProc사이에 작성해야 함

 

int DialogBox(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent,

                   DLGPROC lpDialogFunc);

대화상자의 출력, 운영 및 종료까지 대화상자에 관한 모든 처리를 다 책임

첫번째 인수 : 대화상자 리소스를 가진 인스턴스의 핸들

두번째 인수 : 대화상자 템플릿읭 리소스 ID

세번째 인수 : 대화상자를 소유할 부모 윈도우

네번째 인수 : 대화상자 프로시저의 이름

리턴 값 : 대화상자의 종료 함수인 EndDialog()함수가 지정하는 값

 

대화상자 프로시저 

대화상자 프로시저와 윈도우 프로시저의 차이점

1. 두 프로시저의 리턴값이 다름

   윈도우 프로시저는 LRESULT(long)형의 값을 리턴, 메세지를 처리했을 때 0을 리턴, 관심 없는 메세지

   는 DefWindowProc으로 보냄

   

   대화상자 프로시저는 BOOL형의 값 리턴, 메세지를 처리했을 때 TRUE를 리턴하고 처리하지 못하면

   FALSE를 리턴함

   FALSE를 리턴했다면 그 메세지에 대한 나머지 처리는 운영체제가 알아서 디폴트 처리

2. 대화상자 프로시저는 WM_CREATE메세지 대신 WM_INITDIALOG메세지를 받아들이며 이 메세지를

    받은 시점에서 대화상자에 필요한 초기화

 

대화상자 프로시저에서는 컨트롤들이 부모 윈도우인 대화상자로 보내는 통지메세지(WM_COMMAND)를 주로 처리

LWORD(wParam) = 메세지를 보낸 컨트롤의 ID

HIWORD(wParam) = 통지코드

 

BOOL EndDialog(HWND hDlg, int nResult);

모달 대화상자가 닫힘

두번째 인수 : 대화상자를 호출한 DialogBox 함수의 리턴값으로 전달됨

                   DialogBox를 호출한 곳에서는 이 함수의 리턴값을 보고 사용자가 대화상자에서 어떤 버튼을

                   눌럿는지 판별하고 다음 동작을 결정

 

IDOK는 1, IDCANCEL은 2로 헤더파일에 정의되어 있음

IDCANCEL은 Cancel버튼의 ID임과 동시에 대화상자의 닫기 버튼(X버튼)의 ID

Cancel버튼을 제거했다 하더라도 반드시 IDCANCEL에 대한 통지 메세지는 처리해야 함

 

대화상자 프로젝트

대화상자는 주로 사용자와의 대화를 위해 임시적으로 잠시 열리는 윈도우, 메인 윈도우의 기능을 보조하는 역할

 

별도의 메인 윈도우없이 대화상자만으로 프로그램을 구성할 수도 있다

 

대화상자가 메인 윈도우가 되는 형태의 프로그램을 대화상자 기반의 프로그램(Dialog Base)이라고 함

컨트롤을 많이 사용하는 프로그램들이 주로 대화상자 기반으로 만들어짐

 

별도의 메인 윈도우가 불필요, 윈도우 클래스를 등록할 필요가 없으며 메세지 루프도 필요없다

오로지 WinMain안에 DialogBox함수 호출문 하나로 대화상자만 띄우면 됨

이때 대화상자의 부모는 HWND_DESKTOP(NULL)로 지정하여 대화상자가 메인 윈도우가 되도록 함

 

컨트롤 편집

컨트롤을 복사하면 똑같은 크기의 동일한 속성으로 같은 종류의 컨트롤이 하나 더 만들어지되 단 ID는 중복되지 않도록 다른 ID가 발급

Caption 속성에 &문자를 삽입하면 &다음의 문자가 단축키로 사용됨

 

정렬

정렬을 할 때는 어떤 컨트롤이 기준인가에 따라 그 결과가 달라짐

가장 나중에 선택한 컨트롤이 기중 컨트롤이 되며 굵은 파란색의 핸들로 둘러싸여 있음

탭 순서를 변경하려면 서식/탭순서(6.0은 Layout/Tab Order)항목을 선택

탭순서는 Tab키에 의한 포커스 이동뿐만 아니라 컨트롤의 생성 순서를 결정

라디오 버튼들의 그룹 구성에서 다음번 순서 바로 탭 순서로 평가되며 화면상의 위치와 상관 없음

탭 순서를 ID순서에 맞게 조정해야 그룹이 제대로 구성됨

만약 라디오 버튼을 새로 그룹에 추가했다면 탭 순서도 다시 조정해야 그룹에 포함됨

 

컨트롤과의 통신

컨트롤의 값 읽기

대화상자 내의 컨트롤들은 ID라는 고유의 이름을 가지는데 CreateWindow함수로 직접 만들 때는 hMenu인수로 ID를 지정하며 리소스 편집기를 사용할 때는 속성 대화상자에서 지정

 

HWND GetDlgItem(HWND hDlg, int nlDDlgItem);

첫번째 인수 : 대화상자의 핸들을 줌

두번째 인수 : 컨트롤의 ID를 주면 이 컨트롤의 윈도우핸들을 리턴

 

int GetDlgCtrlID(HWND hwndCtl);

차일드 컨트롤의 윈도우 핸들로부터 ID를 구함

 

윈도우즈는 한 대상을 가리키는 데 왜 ID와 핸들이라는 이중의 식별자를 사용하는가?

핸들 : 그 특성상 운영체제가 일방적으로 발급, 번호의 연속성이 없으며 반복적인 처리에는 사용 불가

ID : 연속성을 가지며 사용자가 직접 번호를 지정할 수 있음

 

대화상자가 차일드 컨트롤을 프로그래밍 하는 주된 방법은 SendMessage함수로 메세지를 보내는 것

 

LONG SendDlgItemMessage(HWND hDlg, int nID, UINT Msg, WPARAM wParam, LPARAM lParam);

부모 대화상자의 핸들과 컨트롤의 ID만으로 편리하게 메세지를 보낼 수 있음

 

대화상자와 컨트롤간에 교환할 수 있는 정보의 종류는 크게 문자열과 정수형, BOOL형과 열거형이다

1. 문자열과 정수형

 

문자열 교환

UINT GetDlgItemText(HWND hDlg, int nID, LPTSTR lpString, int nMaxCount);

컨트롤로부터 문자열을 읽는 함수

BOOL SetDlgItemText(HWND hDlg, int nID, LPCTSTR lpString);

컨트롤로 문자열을 출력하는 함수

첫번째 인수는 대화상자의 윈도우 핸들이며 두번째 인수 nID는 값을 읽거나 쓸 컨트롤의 ID

lpString은 대입하고자 하는 문자열, 또는 문자열을 읽을 버퍼이며 문자열을 읽을 때는 버퍼의 길이를  nMaxCount로 명시

 

정수형 교환

UINT GetDlgItemInt(HWND hDlg, int nID, BOOL *lpTranslated, BOOL bSigned);

1번째, 2번째는 문자열의 경우와 동일

세번째 인수 : 지정된 BOOL형 포인터에 에러가 있었는지 없었는지를 대입, 에러 검사 필요 없으면 NULL대입

네번째 인수 : TRUE일 경우는 부호있는 정수값을 읽고 FALSE일 경우는 부호를 무시하고 무조건 양수로 읽음

BOOL SetDlgItemInt(HWND hDlg, int nID, UINT uValue, BOOL bSigned);

세번째 인수 : 지정한 컨트롤에 nValue 정수값을 대입

 

논리형 교환

BOOL형은 체크 박스로 표시하는 것이 적합

열거형은 라디오 버튼이나 리스트 박스를 사용

 

BOOL CheckDlgButton(HWND hDlg, int nIDButton, UINT uCheck);

체크 박스나 라디오 버튼 등에 값을 대입

첫번째 인수 : 부모 윈도우의 핸들

두번재 인수 : 버튼의 ID

세번째 인수 : 원하는 체크 상태(BST_UNCHECKED = 선택 안 함, BST_CHECKED = 선택함) 

 

UINT IsDlgButtonChecked(HWND hDlg, int nIDButton);

체크 박스나 라디오 버튼 등에 값을 읽어들임

 

모델리스형 대화상자

모델리스형은 대화상자를 열어놓은 채로 메인 윈도우를 조작할 수 있기 때문에 모달형 대화상자보다 더 복잡하며 사용하기도 어렵다

게다가 대화상자를 닫지 않은 채로 값을 변경하고 메인 윈도우가 변경된 값을 즉각 인지할 수 있어야 하는 부담까지 가지고 있음

 

모달형 대화상자와 다른점

CreateDialog함수는 대화상자를 만들기만 하며 만든 즉시 대화상자의 핸들을 리턴하고 대화상자를 운용하지 않음, 대화상자를 만든 후 곧바로 ShowWindow함수를 호출하여 대화상자가 화면으로 나타나게 함

대화상자는 WS_VISIBLE 스타일을 가지지 않으므로 ShowWindow함수를 호출해야 함

대화상자를 종료하는 EndDialog함수가 없어지고 변경된 값을 메인 윈도우에 즉각 반영하기 위해 InvalidateRect함수를 호출하여 메인 윈도우 전체를 무효화시킴

 

이에 비해 DialogBox 함수는 대화상자를 만드는 것은 물론 대화상자를 운용하는 모든 일을 주관하며 대화상자가 닫힐 때까지 리턴하지 않음

 

BOOL IsWindow(HWND hWnd);

hWnd가 유효한 윈도우 핸들인지 조사해 보고 윈도우가 존재하면 TRUE를 리턴하고 그렇지 않으면 FALSE를 리턴

 

IsDialogMessage()함수

메세지가 대화상자를 위한 메세지인지 검사해 보고 만약 그렇다면 대화상자로 이 메세지를 보내는 일

반응형