Dll은 Dynamic Link Library의 약자로 완성된 여러개의 CPP파일을 하나로 묶어서 라이브러리로 만들어 사용을 쉽게 하는데 사용합니다.
물론 라이브러리 파일은 확장자 lib파일로 만들어도 되나 DLL로 만들면 여러 가지 장점이 있습니다.
필자의 경우 모든내용을 DLL로 만들지는 않고(DLL파일을 만드는데도 노력이 들어가고 또한 DLL내부에 버그가 있는 경우 따로 컴파일을 해야하므로 관리에도 신경써야합니다) 대화 상자를 여러 프로그램에서 사용하는 경우 많이 사용합니다.
하나의 프로그램에서 대화 상자를 만들어서 사용하고 같은 대화 상자이어도 다른 프로그램에서 사용하기 위해서는 거의 새로 작성하는 것과 같은 노력이 들어 갑니다.
이 문제를 해결하는 방법으로 DLL을 만들어 사용하면 여러 프로그램에서 그냥 사용하면 됩니다.
그러나 DLL에 대화 상자를 넣기 위해서는 몇가지 세팅을 해야하는데 여기에서 DLL 제작법과 함께 설명합니다.
Visual Studio를 설치한 후 실행하면 다음 그림과 같습니다.
File 메뉴의 부메뉴 New의 Project(Ctrl+Shift+N)를 선택하면 다음과 같은 대화 상자가 생성됩니다.
MFC Dll을 선택하고 Name에 CommonDlg를 입력한 후 OK버튼 선택하면 다음과 같은 대화상자가 생성됩니다.
Next를 선택하면 다음과 같은 대화 상자가 생성됩니다.
DLL type 항목의 세가지는 조금씩 다르게 프로젝트가 생성되는데 여기서는 가장 쉽게 DLL을 만들 수 있는 세 번째 확장 DLL의 형태로 제작합니다.
MFC Extension DLL을 설정하고 Finish버튼을 선택하면 프로젝트가 생성되고 Visual Studio는 다음과 같이 바뀌어 화면에 표시됩니다.
실제 DLL을 만들 경우 대부분 만들고자 하는 .cpp와 .h파일이 있을 것입니다. 만들고자 하는 .cpp파일들을 프로젝트에 추가하고 .h파일들을 하나로 합쳐서 class 선언문에 설정을 좀해주고 컴파일을 하면됩니다.
그러나 여기서는 새로 클래스를 추가하여 대화 상자 호출을 위한 제작을 해보도록 하겠습니다. class 선언문에 설정하는 부분 또한 추가한 class에서 설명할 것이니 참조하기 바랍니다(새로 클래스 추가하는 내용은 DLL과 관계없고 모든 프로그램에서 사용하는 내용입니다).
우선 위 그림과 같이 프로젝트 트리에서 오른쪽 마우스를 클릭하여 생성된 팝업 메뉴에서 Add의 부메뉴 Class를 선택하면 다음과 같은 대화 상자가 생성됩니다.
C++ Class를 선택한 후 Add를 선택하면 대화 상자는 다음과 같이 변경됩니다.
Class name에 생성하고자 하는 Class를 입력(여기서는 CExeDlg를 입력)하면 Class가 추가됩니다.
추가된 ExeDlg.h를 열어보면 다음과 같이 들어 있을 것입니다.
#pragma once class CExeDlg { public: CExeDlg(); ~CExeDlg(); }; |
여기에서 class 선언부인 class CExeDlg의 class와 CExeDlg사이에 AFX_EXT_CLASS를 입력하여 class AFX_EXT_CLASS CExeDlg로 바꾸어 주면 앞에서 이야기한 class에 세팅은 끝이납니다.
일반적으로 DLL을 제작하면 .lib파일이 같이 생성됩니다. 실제 사용시 .lib파일을 프로젝트에 추가해서 사용하도록 하는데 이 부분을 자동(프로젝트 트리에는 나타나지 않고 내부적으로 추가)으로 하는 코드가 다음과 같습니다.
#ifndef _COMMONDLG_DLL_MAKER #ifdef _DEBUG #pragma comment(lib, "CommonDlgD.lib") #else #pragma comment(lib, "CommonDlg.lib") #endif // _DEBUG #endif |
#pragma comment(lib, "CommonDlg.lib")가 실제 위에서 설명한 .lib파일을 프로젝트에 추가가는 기능과 같은 기능을 수행하고 나머지는 몇가지 부가 기능을 수행합니다.
우선 #ifndef _COMMONDLG_DLL_MAKER의 경우 _COMMONDLG_DLL_MAKER라는 것이 #define되어 있는 경우에만 실행하라는 내용인데, 이것은 DLL을 만드는 본 프로그램에서는 #pragma comment(lib, "CommonDlg.lib")가 실행되지 않도록 해줍니다.
물론 DLL을 만드는 프로젝트에 _COMMONDLG_DLL_MAKER라는 것을 #define해주어야 합니다.
#pragma comment(lib, "CommonDlgD.lib")는 Debug 모드에서는 CommonDlgD.lib를 추가하도록 하라는 것입니다. 물론 DLL을 만들 때 Debug모드 파일 생성은 CommonDlgD로 생성되도록 해야합니다.
수정한 소스를 보면 다음과 같습니다.
// CommonDlg1.h: interface for the CCommonDlg class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_COMMONDLG1_H__15D47F43_73B7_41A9_81FA_AF49C68AE99B__INCLUDED_) #define AFX_COMMONDLG1_H__15D47F43_73B7_41A9_81FA_AF49C68AE99B__INCLUDED_ #ifndef _COMMONDLG_DLL_MAKER #ifdef _DEBUG #pragma comment(lib, "CommonDlgD.lib") #else #pragma comment(lib, "CommonDlg.lib") #endif // _DEBUG #endif #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 class AFX_EXT_CLASS CCommonDlg { public: CCommonDlg(); virtual ~CCommonDlg(); }; #endif // !defined(AFX_COMMONDLG1_H__15D47F43_73B7_41A9_81FA_AF49C68AE99B__INCLUDED_) |
이제 두가지 세팅만 더하면 됩니다.
프로젝트 Tree에서 CommonDlg에서 마우스 오른쪽 버튼을 클릭하여 생성된 팝업 메뉴에서 Properties를 선택하며 다음과 같은 대화 상자가 생성됩니다.
C/C++탭을 선택하여 Preprocessor Definitions에 _COMMONDLG_DLL_MAKER를 추가해 줍니다.
물론 Settings For을 Win32 Release로 선택하여 Release 모드에서도 똑같이 해주어야 합니다.
Link탭을 선택하여 Output file name의 Debug/CommonDlg.dll을 Debug/CommonDlgD.dll로 수정해 줍니다.
이제 DLL에서 대화 상자 호출법에 대해서만 설명하면 됩니다.
CCommonDlg에 ExecuteSetCommDlg()라는 함수를 만들어 CSetCommDlg라는 대화 상자(대화상자 참조)를 호출한다고 가정하면 일반적으로 다음과 같이 구성할 것입니다.
BOOL CCommonDlg::ExecuteSetCommDlg() { CSetCommDlg dlg; BOOL bStatus = FALSE; if(dlg.DoModal()==IDOK){ ... bStatus = TRUE; } return bStatus; } |
이 경우 대화 상자 호출이 제대로 되는 경우가 있고 그렇지 않은 경우가 있습니다.
그것은 실행파일에서 사용한 리소스 ID에 따라서 다른데, 만약 DLL과 중복되는 리소스 ID를 사용하는 실행파일에서는 제대로 대화 상자가 호출되지 않을 것입니다. 이 것을 수정하여 실행파일의 리소스와 관계없이 독립적으로 수행되도록 구성하려면 다음과 같이 Source를 수정하면 됩니다.
BOOL CCommonDlg::ExecuteSetCommDlg() { HINSTANCE hInstResourceClient = AfxGetResourceHandle(); #ifdef _DEBUG AfxSetResourceHandle(::GetModuleHandle("CommonDlgD.dll")); #else AfxSetResourceHandle(::GetModuleHandle("CommonDlg.dll")); #endif CSetCommDlg dlg; BOOL bStatus = FALSE; if(dlg.DoModal()==IDOK){ ... bStatus = TRUE; } AfxSetResourceHandle(hInstResourceClient); return bStatus; } |
생성한 DLL을 사용하기 위해서는 생성된 CommonDlg.lib, CommonDlgD.lib, CommonDlg.h를 실행하고자 하는 프로젝트 디렉토리에 복사해주고, CommonDlg.dll파일을 Release디렉토리에, CommonDlgD.dll을 Debug디렉토리에 복사한 후 CommonDlg.h를 #include하고 그냥 일반 클레스 사용하듯이 사용하면됩니다.
데모용 프로그램
데모용 프로그램은 Serial통신 세팅 대화 상자와 LAN통신 세팅 대화 상자를 DLL로 제작해 보았습니다. 참고로 루틴 보는 편의를 위해 위에서 설명한 CommonDlg1.cpp의 내용을 CommonDlg.cpp에 수동으로 복사하고 CommonDlg1.cpp를 삭제하여 한 파일로 구성하여 제작하였습니다.
실제 DLL호출은 Serial 통신 프로그램 제작에서 호출하였으므로 참조하기 바랍니다.
예제 프로그램 다운로드
'Visual C++(MFC)' 카테고리의 다른 글
MFC13. ADO (0) | 2022.03.07 |
---|---|
MFC12. Thread (0) | 2022.03.07 |
MFC10. 메모리 (0) | 2022.03.07 |
MFC09. 인쇄하기 (0) | 2022.03.07 |
MFC08. View에서 깜박임 문제 해결 (0) | 2022.03.07 |