본문 바로가기

윈도우프로그래밍

[윈도우 프로그래밍] 대화상자

  • 대화상자는 사용자와 윈도우 간의 인터페이스 기능을 합니다.
  • 단일문사=마우스, 키보드 메시지 / 다이얼로그 = 컨트롤 메시지

CDialogEx 클래스

  • 대화상자는 CDialogEx 클래스로 정의합니다.
  • CDiaglogEx 클래스는 CDialog 클래스로부터 파생된 파생클래스입니다.
  • CDialogEx 클래스의 모든 기능 + 배경색과 배경그림 바꾸는 기능까지 추가되었습니다.

대화상자 기반의 프로그램

  • 대화상자 기반의 프로그램은 애플리케이션 클래스와 다이얼로그 클래스(대화상자 클래스)로 구성됩니다.
  • 대화상자 클래스는 대화상자의 기능을 구현하는 실제적인 클래스입니다.
  • 애플리케이션 클래스는 프로젝트 전체를 관리하는 클래스입니다.
  • MDI, SDI 프로그램과 클래스 구조가 다릅니다.

1. 대화상자 프로그램의 동작

  • 대화상자 프로그램 실행하면 !! 우선 생성자 함수 호출
  • -> OnCreate() 함수 호출 = CWnd 객체가 제대로 생성된다면 0 반환, 프로그램이 종료되면 OnDestroy() 함수 호출되어서 -1 반환
  • -> OnInitDialog() 함수 호출 = 대화상자가 화면에 보이기 바로 전에 실행되므로 여기에서 초기화 기능 부여, 대화상자에서 사용된 컨트롤들의 초깃값 부여하는 작업 실행
  • ->OnPaint() 함수 = OnDraw() 함수와 같은 기능
  • DoDataExchange() 함수 = 컨트롤을 어떤 방식으로 이용할 것인지 결정-VALUE와 CONTROL이 존재

 

MFC 기본 컨트롤

  • 컨트롤: 사용자와 인터페이스를 이루는 도구입니다. 
  • 프로그램은 실행 중에 끊임없이 사용자와 통신하는데 컨트롤을 통해 명령, 정보 받아들이고, 컨트롤을 통해 결과를 사용자에게 보고합니다.

(1) Static Text

  • 화면에 문자열 배치할 때 사용하며, 사용자로부터 명령을 받아들이지도 않고, 출력을 내보내지도 않는다. 레이블 용도

(2) Edit Control

  • 문자열 입력하고 편집 가능한 컨트롤
  • 사용자가 값 입력 가능
  • 변수와 연결해서 사용함 -> 변수 연결 방식 두 가지

(3) Gruop Box

  • 서로 연관된 컨트롤들을 시각적으로 그룹을 지어 다른 컨트롤과 구분하는 용도로 사용합니다. 그룹 박스로 묶는다고 기능이 변경되지는 x

(4) Button Control

  • 마우스로 클릭하여 어떤 동작을 수행하는 용도로 사용합니다.

(5) Check Box

  • 버튼 컨트롤의 일종으로 독립적인 옵션을 선택할 때 사용합니다. 마우스로 클릭하면 체크표시가 on/off. 여러 옵션 중 임의의 개수를 선택할 때 사용합니다. (2~3개 ㄱㄴ)

(6) Radio Button

  • 버튼 컨트롤의 일종으로 상호 배타적인 옵션을 선택할 때 사용합니다. 마우스로 클릭하면 라디오 표시가 on/off. 여러 옵션 중 하나만 선택할 때 사용합니다. (2~3개 ㄱㄴ)

(7) List Box

  • 여러 개의 선택 항목을 나열하고 선택할 수 있도록 해주는 컨트롤입니다. 하나 또는 여러 개 선택 ㄱㄴ

(8) Combo Box(리스트 박스+에디트 컨트롤)

  • 리스트 박스의 단점을 해결. 리스트 박스+에디트 컨트롤 합쳐놓은 모양입니다.
  • 기존의 항목을 선택할 때는 아래쪽의 리스트 박스에서 선택하고 직접 입력해야 할 항목은 에디트 컨트롤에서 입력할 수 있으며, 콤보 박스는 리스트 박스를 평소에 닫아두므로 화면 면적 차지 적습니다.

1. 실습 4-1 MFC 기본 컨트롤 사용법 익히기 ok

updateCombo() 함수는 리스트박스에 아이템이 들어가거나 없어질때마다 호출되어야 함

에디트 컨트롤에 문자열 입력 후 "데이터 추가" 버튼을 클릭하면 리스트 박스에 바로 보여줘야 함

리스트박스 화면에 출력되어있는 순서의 인덱스와 콤보 박스의 인덱스 동일

리스트 멤버변수.AddString() 과 콤보박스 멤버변수.AddString() 하면 그냥 바로 넣어줌 문자열 !

에디트박스의 멤버변수는 IsEmpty()와 Empty() 멤버함수만 있음

 

  • 폼 만들기
  • 리스트 박스, 에디트 컨트롤, 콤보 박스와 매개변수 연결하기
  • updateComboBox 함수 만들기(void형)-> 리스트박스의 수만큼 콤보박스 매개변수에 문자열 추가하기
  • radio 버튼 1, 2 메시지 헨들러 함수 작성->클릭하면 리스트박스에 문자열 추가->updateCombo() 함수 호출
  • check 버튼 bool 변수 추가 ( bool[2] m_bChecked; 복수 허용하므로 배열형태로 만들고 체크박스1, 체크박스2의 체크상태를 확인/인덱스0, 1 사용 -> 변수 초기화(생성자함수))->체크박스 메시지 헨들러 함수 추가
  • 에디트박스 "데이터 추가" 버튼 메시지 헨들러 함수 추가(문자열 입력 후 "데이터 추가" 버튼 누르면 리스트 박스에 바로 보임 / 입력한 문자열 없는데 "데이터 추가" 버튼 눌렀으면 오류난다는 메시지 박스 보여주기)
  • 콤보 박스 옆의 "삽입" 버튼
  • 콤보 박스 옆의 "삭제" 버튼

 

폼 구성 -> DDX(값이나 컨트롤 형식으로 매개변수와 연결) -> 클래스 마법사에서 컨트롤에 메시지 핸들러 함수 적용 -> 실행하면 그 컨트롤에 메시지 가해지면 핸들러 함수 안의 내용이 실행
  • 폼 구성 -> 멤버변수로 컨트롤을 다루기 위해서 컨트롤들과 멤버변수를 연결해야 합니다.
  • 컨트롤을 멤버 변수와 연결하는 방법 두 가지가 있습니다.
  • 변수 연결한 뒤에(값이나 컨트롤로 ddx) 각 컨트롤에 대한 메시지 핸들러 함수를 만듭니다.(각 컨트롤을 사용자가 선택했을 때의 이벤트 처리-우리가 각 컨트롤마다 연결했던 매개변수 위주로 코딩)

컨트롤(대화상자)을 멤버 변수와 연결하는 방법

(1) DDX(값/컨트롤)을 이용한 방법 - 우리가 거의 사용하는 방법 -

-> Value: 컨트롤에 설정되어 있는 값만 연결, DDX_Text 계열 함수를 이용하여 자원을 연결 / 해당 컨트롤에서 값만 가져오겠다. updateData() 함수를 통해서 매개변수에 t/f 넣으면서 값을 컨트롤에 보내고 가져오고 함

-> Control: 해당 컨트롤을 제어할 수 있는 컨트롤 클래스와 연결, DDX_Control 계열의 함수를 이용하여 자원 연결 / 해당 컨트롤의 클래스와 연결되니깐 클래스의 멤버 함수 사용 가능

(2) 컨트롤의 핸들을 가져와서 클래스와 연결하는 방법

  • 컨트롤의 핸들을 얻기 위해 컨트롤의 포인터를 받을 포인터 변수 선언
  • GetDlgItem() 함수를 이용해서 컨트롤의 포인터를 선언된 포인터 변수에  치환
  • 클래스의 멤버를 이용해서 컨트롤을 다룹니다.(핸들과 클래스 연결)
CListBox *pList; //리스트박스 컨트롤 가르키는 포인터 생성
//GetDlgItem() 함수를 사용하여 해당 리스트 박스 컨트롤의 핸들을 얻어와 pList에 대입, 명시적 형변환
pList = (CListBox *) GetDlgItem(IDC_LIST); // IDC_LIST은 리스트박스 컨트롤의 ID
//클래스의 멤버(함수)를 이용해서 컨트롤을 다룬다.
pList->AddString("데이터");

visual c++에서 DDX로 연결하는 방법

1. 클래스 마법사에서 [멤버 변수] 탭에서 컨트롤 ID 선택 -> [변수 추가]

2. ctrl 키 누른 상태에서 대화 상자 내의 해당 컨트롤 더블클릭

 

DoDataExchage() 함수: 매개변수와 컨트롤 연결

  • DoDataExchange() 함수는 주로 대화상자나 폼뷰에서 사용되며, 데이터와 UI 요소 간의 일관성을 유지하고 데이터 입력에 대한 유효성 검사를 수행하는 등의 역할을 수행합니다.
  • 대화상자의 여러 자원을 연결하는 기능을 하는 함수입니다.(컨트롤을 값이나 컨트롤 형식으로 연결)
  • 이 함수 안에는 DDX_Text와 DDX_Control 함수를 이용하여 자원과 연결할 수 있습니다. -매개변수 OR 클래스
  • DDX_Control 형태로 연결되었을 경우는 변수가 클래스로부터 상속 받았으므로 클래스의 멤버 함수를 마음대로 사용 가능

UpdatData() 함수: 매개변수와 컨트롤의 값을 업데이트

 

  • DDX_Value 형태로 연결돼었을 경우는 UpdateData() 함수를 사용해서 자원을 update 합니다.
  • 방향을 잘 확인해야 합니다.
  • UpdateData(TRUE) - 버튼 클릭 시에 컨트롤에 있는 데이터를 변수에 가져오는 것
  • UpdateData(FALSE) - 변수에 특정 값을 주고 그 값을 컨트롤에 보내기, 화면갱신
BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 다이얼로그 상의 컨트롤 값을 멤버 변수에 읽어옴
    UpdateData(FALSE);

    return TRUE;
}

void CMyDialog::OnBtnClicked()
{
    // 사용자가 버튼을 클릭하였을 때, 컨트롤의 값을 멤버 변수에 읽어옴
    UpdateData(TRUE);

    // 멤버 변수의 값을 이용하여 작업 수행

    // ...
}

void CMyDialog::OnOK()
{
    // 다이얼로그의 OK 버튼을 클릭하였을 때, 컨트롤의 값을 멤버 변수에 저장
    UpdateData(TRUE);

    // 멤버 변수의 값을 이용하여 작업 수행

    // ...

    CDialog::OnOK();
}

 

 

CListBox 클래스의 주요 멤버 함수-CONTROL로 연결

  • 왜 알아야 되나? 우리가 컨트롤과 매개변수를  DDX 함수로 연결을 할 수 있었어. 그 형식은 값만 가져오는 Value(DDX_Text() 함수)하고, 컨트롤의 클래스 연결(DDX_Control() 함수)가 있었지?
  • 근데 여기서 DDX_Control 함수는 클래스와 연결되기때문에 컨트롤과 연결된 매개변수가 그 컨트롤 클래스의 멤버함수까지 사용할 수 있어. 따라서 멤버 함수를 쓰기 위해선 알아둬야 해 ~~
  • MFC(Microsoft Foundation Classes)에서 제공하는 리스트 박스 컨트롤을 다루는 클래스
함수명 기능
GetCount() 함수 리스트박스의 아이템 수를 알기 위해 사용하는 함수
int GetCount() const;
반환값으로는 현재 리스트 박스에 있는 아이템의 개수를 반환합니다.

이 함수를 사용하면 CListBox 클래스를 통해 현재 리스트 박스에 추가된 아이템의 개수를 알 수 있습니다. 예를 들어, 리스트 박스에 목록을 추가하고 삭제하는 동작을 수행할 때, GetCount() 함수를 사용하여 현재 목록의 개수를 확인하고 이를 기반으로 추가적인 동작을 수행할 수 있습니다.

AddString() 함수 리스트박스의 맨 뒤에 문자열을 추가할 때 사용하는 함수
int AddString(LPCTSTR lpszItem);
인자로는 추가할 문자열의 포인터를 전달합니다. 반환값은 리스트 박스에 추가된 문자열의 인덱스를 반환합니다.
그냥 바로 문자열 추가해보림
GetText() 함수 리스트박스로부터 문자열을 얻어올 때 사용되는 함수
vint GetText(int nIndex, LPTSTR lpszBuffer) const;
-> 몇번째 인덱스에 있는 문자열을 버퍼에 저장해
인자로는 가져올 문자열의 인덱스와 문자열을 저장할 버퍼의 포인터를 전달합니다. 반환값은 가져온 문자열의 길이를 반환합니다.
DeleteString() 함수 리스트박스의 아이템을 삭제할 때 사용하는 함수
int DeleteString(UINT nIndex);
인자로는 삭제할 문자열의 인덱스를 전달합니다. 반환값은 삭제된 문자열의 인덱스를 반환합니다.

 

CComboBox 클래스의 주요 멤버 함수

  • MFC(Microsoft Foundation Classes)에서 제공하는 콤보 박스 컨트롤을 다루는 클래스
함수 기능
AddString() 함수 콤보 박스의 맨 뒤에 새로운 문자열을 추가하는 함수
int AddString(LPCTSTR lpszString);
인자로는 추가할 문자열의 포인터를 전달합니다. 반환값은 콤보 박스에 추가된 문자열의 인덱스를 반환합니다. 그냥 바로 문자열 추가해보림
GetCurSel() 함수 현재 선택된 아이템의 인덱스를 가져오는 함수
int GetCurSel() const;
반환값으로는 현재 선택된 아이템의 인덱스를 반환합니다.
ResetContent() 함수 콤보박스의 모든 아이템을 제거할 때 사용하는 함수
void ResetContent()

 

CString 클래스의 주요 멤버 함수

함수 기능
IsEmpty() 함수 문자열 버퍼가 비어 있는지 체크하는 함수
BOOL IsEmpty() const
버퍼가 비어있으면 true, 비어있지 않으면 false 반환
Empty() 함수 문자열을 삭제하여 버퍼를 비우는데 사용하는 함수
void Empty()

 

모달 대화상자와 모덜리스 대화상자(부모 뷰에서 작업 가능 여부)

모달 대화상자

  • 모달 대화상자는 출력되면 애플리케이션 내의 다른 윈도우에서 작업을 할 수 없습니다.
  • -> 모달 대화상자를 닫아야 애플리케이션 내의 다른 윈도우에 포커스를 둘 수 있습니다. 
  • -> DoMadal() 함수를 이용해서 출력

모달리스 대화상자

  • 모달리스 대화상자는 종료시키지 않아도 다른 윈도우에서 사용자가 작업을 계속 할 수 있습니다.
  • 추가적인 정보 띄어두고 동시에 작업 ㄱㄴ
  • 출력방식이 모달 대화상자보다 좀 더 복잡..
  • 첫 째로 출력할 대화상자 클래스에 대한 변수 선언(객체 생성)-아무것도 구성 X
  • Create() 함수를 이용해서 대화상자 만들기 인수는 대화상자 id=리소스에서 부여되는 ID, 부모 윈도우의 포인터(cwnd)-
  • 두 번째로는 생성한 대화상자를 화면에 보여줘야하므로 ShowWindow(SW_SHOW) 

대화상자 클래스의 객체 생성-> CREATE로 리소스에 부여된 ID(대화상자 ID)와 호출할 부모(보여줄 창)->SHOW로 윈도우에 실제로 객체인 대화상자 보옂무

공용 대화상자(모달 대화상자,DoMadal() 함수 사용)

  • MFC에서 대부분 애플리케이션에 들어가는 공통적인 대화상자들을 클래스로 만들어 놓은 것이 공용 대화상자
  • 파일 대화상자, 폰트 대화상자, 색상 대화상자 등이 있다.

1. 파일 대화상자

  • 파일의 열기, 저장, 다른 이름으로 저장 동작할 때 사용되는 대화상자
  • CFileDialog 클래스에 정의
//생성자 함수의 인수가 true일 때는 Open 대화상자 지젇, false일 때는 SaveAs 대화상자로 지정
//파일 대화상자의 객체 생성. 매개변수가 T이면 대화상자 열고, F이면 저장
CFileDialog pDlg(TRUE); //생성자 함수 호출
pDlg.DoMadal(); //대화상자 출력ㅊ


◼ CFileDialog의 생성자 함수
CFileDialog( //클래스
BOOL bOpenFileDialog, //오픈할지 세이브할지
LPCTSTR lpszDefExt = NULL, //확장자
LPCTSTR lpszFileName = NULL, //디폴트에 해당하는 파일명
DWORD dwFlags = OFN_HIDEREADONLY | //속성 정의하는 플래그
OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL, //검색에 사용할 필터
CWnd* pParentWnd = NULL //부모 윈도우 지정
);


//=이 있다는 것은 굳이 지정하지 않아도 된다는 것임.

//Open 대화상자 출력 예
char Filter[ ] = _T("Text File(*.txt) | *.txt| 모든 파일(*.*)|*.*|“);
//파일 대화상자 객체 생성 OPEN 파일 저장형태 =TXT
CFileDialog pDlg(TRUE, _T("text file(*.txt)", "*.txt“),
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, Filter, NULL);
if(pDlg.DoModal() == IDOK) //대화상자 출력
{
data = pDlg.GetPathName(); //실제 파일의 경로 얻어와서 그때 가지고 있는 데이타 얻어옴
…
…
…
}

//Save 대화상자 출력 예
2023-04-17 S23-1/ Windows Programming 9
char Filter[ ] = _T("Text File(*.txt) | *.txt| 모든 파일(*.*)|*.*|“);
//파일 대화상자 객체 생성 SAVE 파일 저장형태 =TXT
CFileDialog pDlg(FALSE, _T("text file(*.txt)", "*.txt“),
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, Filter, NULL);
if(pDlg.DoModal() == IDOK)
{
data = pDlg.GetPathName();
…
…
…
}

2. 폰트 대화상자

  • 애플리케이션에서 사용되지만 주로 텍스트 기반의 애플리케이션에서 사용
  • 텍스트의 글꼴이나 크기, 쿤자 속성 등을 지정할 수 있는 대화상자
  • 해당 클래스는 CFontDialog
//폰트 대화상자 출력
//클래스로부터 객체 생성
CFontDialog fontDlg;
fontDlg.DoMadal(); //실제 오픈!

//목적은 지정한 폰트 읽어오는 것 -> 폰트 구조체로 받음
//폰트 대화상자는 파일 대화상자보다 훨씬 쉽게 동작
//사용자가 폰트 선택 -> 확인 버튼 누그면 폰트 받음

// 글꼴 설정
CFont font;
font.CreateFontIndirect(&logfont);

//DC의 글꼴 선택함으로써 글꼴 사용 ㄱㄴ

3. 색상 대화상자

  • 사용자에 의해 색을 선택하는 공용 대화상자
  • 해당 클래스는 CColorDialog
//DoModal() 함수를 통해 불러온 두 GetColor() 함수를 통해 선택된 색상 값 저장해서 사용

CColorDialog colorDlg; //객체 생성
if(colorDlg.DoMadal() ==IDOK) //
COLORREF m_color = colorDlg.GetColor(); //칼라를 선택했으면 그 색상을 실제로 받아옴

4. 실습 4-2 단위 변환 프로그램 만들기

모달 대화상자 + 모달리스 대화상자(단위 변환한 것 확인)

단위변환표는 모달리스 대화상자.

 

  • 폼 구성
  • 매개변수와 컨트롤 연결하기 (DDX 함수 사용)
  • radio 버튼에 대한 메세지 핸들러 함수 추가하기-> 길이, 무게 비교할수 있는 변수 하나 만들고, 각각에 대해서 대화상자 화면 값들 초기화하고 UpdateData(FALSE)를 통해서 화면 갱신
  • 값 변환하기 위한 함수 추가하기(//현재유닛, 변환될 유닛 클릿 후 현재 값 입력하면 변환된 값이 눈에 보이도록 해줌)
  • EDIT CONTROL에 대한 명령 추가 ComputeUnitValue(); 넣어서 변환된 값으로 업데이트되도록 !!! -> 현재 값 입력하면 단위마다 변환된 값으로 출력됨
  • 현재 값 입력 에디트 텍스트 ( ) -> 변한 값 에디트 텍스트 ( )  ( ) 바꿔주기 + 리스트 박스 위에 ( 리스트의 text) -> (리스트의 text ) 까지 !! 리스트 박스 선택된 것에 따라서 !! -> 원래 list 컨트롤에 (list box)에 대한 메시지 핸들러 함수 생성
  • 왼쪽 리스트 박스와 오른쪽 리스트 박스 모두 해줘야 함 !

 

  • 변하지 않는 부분은 static으로
  • 변하는 부분은 edit control=사용자에 입력을 받거나 / 사용자에게 계속적으로 다른 부분을 보여줘야할 때(단위 선택하면 계속 다른 값 보여줌 = 읽기전용을 true로 !!
  • 리스트와 에디트 컨트롤 모두 멤버 변수와 연결해야 됨
  • 변환 부분만 숫자, 나머지는 문자형태의 변수와 ddx로 연결하기
  • 라디오버튼은 사용자의 선택
  • UPDATEDATA(FALSE):변수의 값-> 화면(컨트롤)
  • updatedate(true):화면(컨트롤 ..에디트 컨트롤 등등)->변수의값
  • 줄맞추기 기능도 있다.
  • 라디오버튼 처음 그룹 true, 마지막은 false로 하면 하나의 묶음이라고 생각함.(같은 그룹으로 인식)

라디오 버튼에 따라 길이인지 무게인지 변경