<Dialog Box 생성자를 통해 데이터를 전달하는 방법>
대화상자는 사용자와 프로그램간의 상호 의사전달을 용이하게 하는 도구이다. 사용자의 명령을 처리하기 위해 적당한 정보를 알려주고 또 필요한 정보를 입력받는다. 이 과정에서 대화상자는 모든 정보를 스스로 생성하여 제시하지는 않는다. 대화상자 자체가 프로그램의 부수적인 기능일 뿐이므로 대부분의 정보는 메인 프로그램이 갖게된다. 따라서 대화상자를 호출하기 전에 대화상자에서 필요한 데이터를 전달해 주어야 한다. (물론 그 데이터가 전역변수라면 상관이 없겠지만...)
여기서 하려는 얘기는 바로 그 전달 방법이다.
- 가장 일반적인 방법
참고서적의 가장 흔한 주제가 대화상자이고 거기서 빈번하게 사용하는 방법되는 코드는 다음과 같다.
CMyDlg dlg;
dlg.m_data = myData1; // dialog box의 멤버변수에 직접 전달하는 경우.
dlg.SetData( myData2 ); // dialog box의 멤버함수를 사용하는 경우.
dlg.DoModal();
- 생성자를 통해 전달하는 방법
이렇게 하면 더 간단하지 않을까?
CMyDlg dlg( myData1, myData2 ); // dialog box의 생성자에 데이터 전달.
dlg.DoModal();
그러자면 클래스위저드가 생성해준 대화상자 클래스를 조금 수정해야 한다.
먼저 헤더파일의 클래스 선언중 생성자 원형을 다음과 같이 수정한다. 원래의 생성자는 지워도 되고 그대로 둔 채 새로운 생성자를 추가해도 된다.
class CMyDlg : public CDialog
{
public:
CMyDlg( CWnd* pParent = NULL ); // 표준 생성자
CMyDlg( MYDATA1 myData1, MYDATA2 myData2 ); // 새로운 생성자
...
};
다음에 cpp 파일의 정의부분을 수정한다. 마찬가지로 기존의 생성자는 지워도 되고 그대로 둔 채 새로운 생성자함수를 추개해도 된다. 그대로 둘 경우엔 어떤 생성자를 사용해서 대화상자를 호출할 것인가는 프로그래머 맘대로다.
CMyDlg::CMyDlg( CWnd* pParent /*=NULL*/ ) : CDialog( CDbNewDlg::IDD, pParent )
{
... // 기존의 생성자
}
CMyDlg::CMyDlg( MYDATA1 myData1, MYDATA2 myData2 ) : CDialog(CMyDlg::IDD, NULL)
{
... // 새로운 생성자
}
위에서 MYDATA1, MYDATA2는 임의의 데이터형이다. 원래의 형태와 수정된 형태를 잘 비교해 보라.
생성자에 전달하는 인자의 데이터형과 갯수는 제한이 없다.
참, 생성자를 통해 전달된 인수는 생성자 함수 내에서만 유효하므로 생성자에서 대화상자의 적당한 멤버변수에 대입하여 저장해두어야 한다.
콘솔에 문자열을 출력하기 위해 다음과 같은 코드를 사용한다.
void CConsoleTest::OnButton1()
{
CString str;
GetDlgItemText(IDC_EDIT1, str);
AllocConsole(); // 새로운 콘솔 프로세스 할당
DWORD dwWrite;
// 콘솔 프로세스의 핸들을 얻는다.
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(hOut, str, str.GetLength(), &dwWrite, NULL); // 데이터 출력
AfxMessageBox("콘솔 화면에 출력하기"); // 콘솔을 잠시 유지하기 위해 사용
FreeConsole(); // 할당된 콘솔 해제
SetDlgItemText(IDC_EDIT1, ""); // 에디트 박스 내용 삭제
}
여기서는 새로운 다이얼로그를 하나 만들고, 거기에 에디트 박스와 버튼을 하나씩 추가한 후 그 ID를 각각 IDC_EDIT1, IDC_BUTTON1 으로 하고, 뷰에서 마우스 왼쪽 버튼을 더블 클릭하면 그 다이얼로그가 뜨도록 작성해 보았다. 물론 필요한 대로 다르게 작성해도 된다.
단, 만약 위의 AfxMessageBox() 가 없다면 출력되자마자 콘솔이 사라져 버리므로 FreeConsole()을 적당한 장소에서 사용해야 할 것이다.
- the end of this article -
보통 MDI에서 파일을 열 때, 하나씩밖에 선택이 되지 않는데, 다음과 같이 onFileOpen() 함수를 오버라이드 하면 여러개의 파일을 선택할 수 있습니다. SDI에서 이거 쓸 필요 없겠죠??
void CMultiSelApp::OnFileOpen()
{
// TODO: Add your command handler code here
static char BASED_CODE szFilter[] = "Image Files (*.bmp,*.dib)|*.bmp;*.dib||";
PSZ pszFile=new char[32767];
CFileDialog cfd(TRUE,".bmp",NULL,
OFN_HIDEREADONLY|
OFN_OVERWRITEPROMPT|
OFN_FILEMUSTEXIST |
OFN_EXPLORER|
OFN_ALLOWMULTISELECT|
OFN_LONGNAMES,
szFilter);
ZeroMemory(pszFile,32767);
cfd.m_ofn.lpstrFile=pszFile;
cfd.m_ofn.nMaxFile=32767;
cfd.m_ofn.nFileOffset=0;
if(cfd.DoModal()==IDOK) {
POSITION pos=cfd.GetStartPosition();
while(pos!=NULL) {
CString csFile=cfd.GetNextPathName(pos);
OpenDocumentFile(csFile);
}
}
}
- SDI
CWinApp : AfxGetApp()
CMainFrame : AfxGetMainWnd()
CView 계열 : AfxGetMainWnd()->GetActiveView()
CDocument : AfxGetMainWnd()->GetActiveDocument()
- MDI
CWinApp : AfxGetApp()
CMDIFrameWnd : AfxGetMainWnd()
CMDIChildWnd : AfxGetMainWnd()->GetActiveFrame()
CView 계열 : AfxGetMainWnd()->GetActiveFrame()->GetActiveView()
CDocument : AfxGetMainWnd()->GetActiveFrame()->GetActiveDocument()
프로그램을 작성하다 보면 CD-ROM 타이틀처럼 메뉴도 없고, 툴바도 없고, 상태바도 없고, 캡션바도 없는 말 그대로 틀이 전혀 없는 그런 윈도우가 필요할 때가 있다. SDK에선 간단하지만 MFC에선 좀 까다로운 문제가 될 수 있다.
MFC에서는 기본적으로 메뉴가 내장되기 때문에 이 메뉴를 해제하지 않고 크기와 스타일을 바꾸면 실행에러가 발생한다. 이 메뉴를 없애기 위해 새로운 메뉴를 만들고 이 메뉴를 메인프레임에 설정된 메뉴와 연결한다. 이때 Attach 함수를 이용한다. 이렇게 연결된 후 pMenu를 삭제하면 메인프레임의 메뉴 또한 삭제된다. 이렇게 한 후 메인프레임의 메뉴를 NULL로 설정하고, pMenu를 메모리에서 해제한다.
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style = WS_VISIBLE|WS_POPUP|WS_BORDER;
int cx = GetSystemMetrics(SM_CXFULLSCREEN);
int cy = GetSystemMetrics(SM_CYFULLSCREEN);
cs.cx = 640; // 윈도우의 가로크기
cs.cy = 480; // 윈도우의 세로크기
cs.x = (cx-640)/2; // 윈도우의 좌상단 x 좌표
cs.y = (cy-480)/2; // 윈도우의 좌상단 y 좌표
CMenu *pMenu = new CMenu; // 새로운 메뉴를 만든다.
pMenu->Attach(cs.hMenu); // 메인프레임에 설정된 메뉴와 연결
pMenu->DestroyMenu(); // 메뉴삭제
cs.hMenu = NULL;
delete pMenu; // 메모리에서 해제
return CFrameWnd::PreCreateWindow(cs);
//return TRUE;
}
이러한 윈도우를 종료하기 위해서 View에 약간 처리를 해주었다.
void CNoFrameView::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
((CMainFrame *)AfxGetMainWnd())->SendMessage(WM_CLOSE, 0, 0);
//CView::OnRButtonDown(nFlags, point);
}
[↓Click! Dialog Box 생성자를 통해 데이터를 전달하는 방법 / 콘솔에 문자열 출력하기 ]
'IT_Programming > MFC · API' 카테고리의 다른 글
윈도우 접기 / 상태바에 그림 출력 / 시스템 강제로 다운시키기 (0) | 2007.12.25 |
---|---|
객체에 툴팁달기 / 하드에서 특정파일찾기 / 단 한개의 프로그램만 실행 (0) | 2007.12.25 |
캡션바가 없는 윈도우의 이동 / 예외처리란? / 다이얼로그 키값 메시지 처리 (0) | 2007.12.25 |
Create 함수와 OnCreate 함수의 차이점 / 동영상 반복 기능 (0) | 2007.12.25 |
방패 모양 윈도우 만들기 / 투명한 윈도우를 만들려면 (0) | 2007.12.25 |