예전에 만들었던 블랙리스트 추출기의 업데이트 버전이다...(이전 자료 링크...)

게시판 소스를 붙이는 부분을 나름데로 자동으로도 할 수 있도록 변경을 해봤다...

딱히 새로운것 없이 "웹페이지 소스저장..." -> 이넘을 이용해서 기존에 해당게시판의 소스를 수동으로 복사했던것을 자동으로 처리할뿐이다...

현재 문제점은 해당게시판의 서버가 느릴 경우이다...이럴 때를 대비해서 우선 기존의 수동복사 기능은 남겨둔 상태이다.

그리고 대충 머리를 굴려서 소스에서 꼭 들어가는 내용이 있는지 확인을 하는것으로 에러처리를 했었는데 결과는 실패다;;;

서버에 아예 연결이 안되면 에러가 리턴되지만 연결은 되지만 그냥 느린상태면 죽어라 데이터를 가져오느라 뻗기 직전까지 간다...(가끔 뻗는다 ㅡㅡ;)

서버가 느릴때만 테스트가 가능해서 결국 딱히 해결 못했다...

아래는 스샷~~~

블랙리스트 추출기 (업데이트-1)


(사용언어 및 제작툴 : MFC / VS2005)

기본 버전 : 2007/02/15 - [프로그래밍.../Source] - 블랙리스트 추출기(?)
Posted by Gungume
,
//stdafx.h 파일에 #include  를 추가
BOOL GetSourceHtml(CString  theUrl)
{
	// this first block does the actual work
	CInternetSession session;
	CInternetFile* file = NULL;

	try
	{
		// try to connect to the URL
		file = (CInternetFile*) session.OpenURL(theUrl); 
	}
	catch (CInternetException* m_pException)
	{
		// set file to NULL if there's an error
		file = NULL; 
		m_pException->Delete();
	}

	// most of the following deals with storing the html to a file
	CStdioFile dataStore;

	if(file)
	{
		CString somecode;
		BOOL bIsOk = dataStore.Open(_T("C:\\rawHtml.txt"),
			CFile::modeCreate 
			| CFile::modeWrite 
			| CFile::shareDenyWrite 
			| CFile::typeText);

		if (!bIsOk)
			return FALSE;

		// continue fetching code until there is no more
		while (file->ReadString(somecode) != NULL) 
		{
			somecode += "\r\n";
			dataStore.WriteString(somecode);
		}

		file->Close();
		delete file;
	}
	else
	{
		dataStore.WriteString(_T("Could not establish a connection with the server..."));    
	}

	return 0;
}


필요에 의해서 찾아본 소스로 그냥 데브피아에서 퍼온 자료이다...

매개변수로 소스를 저장하고 싶은 웹페이지의 주소를 넘겨주면 된다...

저장되는 파일 위치 지정 등만 살짝 수정해서 쓰면 될듯함...

출처 : 데브피아 -> 질문&답변
Posted by Gungume
,



자주가는 사이트에서 블랙리스트를 체크할 때 매번 하나씩 확인하기 귀찮아서 만든 프로그램...

항상 그래왔듯이 역시 조잡하다;;;

과제로 했던 허접한 해쉬 넣고...기존에 코딩했던 프로그램에서 이것저것 C&P 스킬 발휘해주고;;;

단순히 TXT 파일에 저장된 블랙리스트 목록을 파일에서 읽어온 후에 해당 게시판의 목록에서 소스보기를 통해서 웹피이지 소스를 프로그램에 복사해주면 대충 파싱해서 블랙리스트 목록과 게시판 목록의 닉네임을 비교해서 블랙리스트 존재여부를 알려준다...

아래는 스샷~

블랙리스트 추출기

(사용언어 및 제작툴 : MFC / VS2003)
Posted by Gungume
,

TV 알리미...

MFC/Application 2007. 1. 22. 23:10

TVAlarm.exe




평소에 티비를 좀 보는 편인데...맨날 컴터하다가 보고 싶은 티비를 놓치는 경우가 많아서 순간 삘 받아서 만든 프로그램이다...

로직은 딱히 별거 없다...프로그램에서 대충 TV프로 시간과 채널 제목 등 넣으면 리스트 컨트롤에 자료 저장했다가...타이머를 이용 1분 간격으로 데이터를 체크해서 시간이 맞으면 그 정보를 알려준다...

정보를 알려주는 방식은 그냥 다이얼로그 테두리 다 없애고 윈도우 구석 부분에 팝업형태로 잠시 알려주는데...원래 버튼을 누르면 그냥 닫혀야 하는데 Sleep() 함수를 써서 Sleep() 끝날때까지는 그냥 화면에 표시된다 ㅡㅡ

파일저장도 그냥 대충해서 저장하면 실행파일과 같은 경로에 "Data.txt" 파일로 저장되고 프로그램 시작시에도 저 파일이 실행파일과 같은 경로에 있으면 저장된 정보를 읽어온다...

올만에 코딩한거라 역시 막코딩을 했고 생각보다 시간이 꽤 오래걸렸다;;;

트레이와 관련해서는 그냥 이것저것 갖다썼다...

아래는 프로그램 실행시 화면과 시간이 되었을때 팝업되는 화면이다...

TV 알리미TV 알리미



TV 알리미 트레이 알림



- 참고 자료 -
트레이 아이콘 : CodeGuru
MFC 모달 다이알로그를 숨김 상태로 시작 : Jiniya.net
트레이로 가는 애니메이션 출력하기 : Jiniya.net

(사용언어 및 제작툴 : MFC / VS2003)


Posted by Gungume
,

현재 윈도우 해상도 얻기

1. GetSystemMetrics()
int nWidth = GetSystemMetrics(SM_CXSCREEN);
int nHeight = GetSystemMetrics(SM_CYSCREEN);
(결과) nWidth : 1280, nHeight : 1024

2. GetWindowRect()
RECT rect;
::GetWindowRect(::GetDesktopWindow(), &rect);
(결과) Top : 0, Bottom : 1024, Left : 0, Right : 1280

3. EnumDisplaySettings()
DEVMODE mode;
::EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS, &mode);
UINT nWidth = mode.dmPelsWidth;
UINT nHeight = mode.dmPelsHeight;
(결과) nWidth : 1280, nHeight : 1024


작업 표시줄 제외한 윈도우 영역 크기 얻기

RECT rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
(결과) Top : 0, Bottom : 994, Left : 0, Right : 1278


트레이 영역 크기 얻기

HWND hTrayP = ::FindWindow("Shell_TrayWnd", NULL);   
HWND hTrayC = ::FindWindowEx(hTrayP, NULL, "TrayNotifyWnd", NULL);   
if(hTrayC)    
     ::GetWindowRect(hTrayC, &rect);

(결과) Top : 994, Bottom : 1024, Left : 1114, Right : 1280


※ 결과 : 1280*1024 해상도 기준
※ 자료 출처 : 데브피아1, 데브피아2, Jiniya.net
 

Posted by Gungume
,



폴더 & 파일 목록 만들기 프로그램

선택한 폴더에 대해 모든 하위폴더를 순회하면서 폴더와 파일의 목록을 간단히 html로 만들어주는 프로그램...

폴더를 선택하면 그 폴더내의 폴더와 파일의 목록을 모두 출력하고...폴더가 있을 경우에는 해당 폴더에 들어가서 같은 작업을 반복해서 출력해줌...

dir 명령어를 이용해서 목록을 얻는것과 결과물은 비슷함...

폴더 지정후 출력내용을 설정한 후 생성 버튼을 누르면 프로그램이 있는 폴더내에 list.html 파일로 결과물이 출력됨...

기본적인 알고리즘은 CFileFind 클래스를 이용해서 폴더를 순회하면서 목록을 얻어 출력해주고...출력과 동시에 폴더인 경우에는 CStringList에 데이터를 추가해 놓은 후에 한차례 출력이 끝나면 CStringList에 있는 데이터를 꺼내서 재귀함수를 이용 해당폴더에 대해서 데이터를 출력...

아래는 결과물 스샷...

폴더 & 파일 목록 만들기 출력결과

(사용언어 및 제작툴 : MFC / VS2003)

Posted by Gungume
,
ShellExecute() 함수는 프로그램을 실행시킬 수 있는 함수이다.

"shellapi.h" 헤더와 "shell32.lib"를 사용한다...

함수의 원형은 아래와 같다.
HINSTANCE ShellExecute(    
     HWND hwnd,
     LPCTSTR lpOperation,
     LPCTSTR lpFile,
     LPCTSTR lpParameters,
     LPCTSTR lpDirectory,
     INT nShowCmd
);

각 인자를 대략적으로 설명하면 아래와 같다...
hwnd : 핸들...보통 NULL로 두면 된다...
lpOperation : 수행할 동작으로 프로그램 실행시에는 "open"을 사용...
lpFile : 수행할 프로그램의 파일명을 적는다...보통 절대경로와 함께 지정...
lpParameters : 프로그램 수행시 지정되는 인자가 있는 경우 적어주고 없으면 NULL로 지정...
lpDirectory : "lpFile"이 존재하는 파일의 경로를 적어준다...보통 "lpFile"에 경로를 같이 적어주므로 NULL로 지정...
nShowCmd : 프로그램 수행시 윈도우 크기 등 지정...

- 사용예 -

프로그램 실행
ShellExecute(NULL, "open", "C:/Program Files/NATEON/BIN/NATEON.exe", NULL, NULL, NULL);

웹사이트 접속
ShellExecute(NULL, "open", "http://www.naver.com", NULL, NULL, SW_SHOWNORMAL );

메일 보내기
ShellExecute(NULL, "open", "mailto:메일주소", NULL, NULL, SWP_SHOWWINDOW);

MSDN 원문 보기...
Posted by Gungume
,

[펌] 포인터 얻기

MFC/TIP 2006. 10. 14. 10:49
임의의 클래스의 포인터 얻기

Visual C++로 프로그램을 작성하고자 할 때, 가장 먼저 막히는 부분 중의 하나가 어떤 클래스 인스턴스의 포인
터를 얻는 것이죠. 일반적으로 뷰 클래스를 가장 많이 다루게 되고, 그 다음이 도큐먼트 클래스, 그 다음이 메인
프레임 클래스 순일 것입니다. 그리고 거의 변경할 필요가 없는 애플리케이션 클래스도 있구요.
물론 사용자가 만든 클래스나 버튼 같은 컨트롤에 관련된 클래스에 접근해야 할 경우도 있는데, 그럴 때 초보자
는 막막해 질 수밖에 없습니다. 경험담이기도 하죠.
여기서는 그러한 경우의 각 클래스의 포인터를 얻는 경우에 관해 알아봅니다.여기서는 프로젝트 이름이 Test라
고 가정하죠. 사용자에 따라 프로젝트의 이름이 다르겠죠?
그리고 중간에 참조되는 모든 클래스의 헤더파일이 인클루드 되어야 하구요. 뷰의 헤더가 인클루드 된다면 반드
시 그 앞에 도큐먼트의 헤더가 인클루드 되어야 합니다.


일반적인 SDI 프로그램에서.


1.애플리케이션 클래스의 포인터를 얻을 때
CWinApp* AfxGetApp()
함수를 사용합니다.


2.메인 프레임 클래스의 포인터를 얻을 때
CWnd* AfxGetMainWnd()
함수를 사용합니다.

이들 두 함수는 MFC의 전역함수로써 프로그램을 작성하는 도중 어디에서나 사용할 수 있습니다. MFC에서는 Afx~
로 시작하는 함수들은 모두 전역함수를 의미합니다.
물론 타입 캐스팅을 해야 하구요. 사용법은 다음과 같습니다.

CTestApp *pApp = (CTestApp *)AfxGetApp();
CMainFrame *pFr = (CMainFrame *)AfxGetMainWnd();

이렇게 써준 다음에는 pApp와 pFr은 각각 애플리케이션 클래스와 메인 프레임 클래스의 인스턴스 포인터를 가리키
게 됩니다.

이 외에 뷰 클래스에서 그 뷰를 둘러싸고 있는 프레임 윈도우를 참조할 때는

CFrameWnd* GetParentFrame() const

함수를 사용할 수 있습니다. 물론 뷰 클래스뿐만이 아니라 일반적인 윈도우를 둘러싸는 틀로써 프레임 윈도우가
사용될 수 있기 때문에 GetParentFrame() 함수는 CWnd() 클래스의 멤버함수로 되어있습니다.

이 함수와 AfxGetMainWnd() 함수는 SDI에서는 같은 기능을 하지만, MDI에서는 메인 프레임 윈도우와 뷰를 둘러
싸고 있는 프레임 윈도우가 다르기 때문에 그 각각을 구하는 역할을 합니다.


3.도큐먼트 클래스의 포인터를 얻을 때는 몇 가지 경우가 있습니다.

(a) 뷰 클래스에서 도큐먼트 클래스에 접근할 때.

이때는 말할 필요도 없이 GetDocument() 함수를 쓰면 됩니다. 뷰에 이미 정의되어 있는 함수죠. 하지만 사용자
가 임의로 뷰를 추가한 경우에는 이 GetDocument() 함수가 포함되어 있지 않습니다. 이럴 경우 기존에 있는 뷰에
서 GetDocument() 함수 부분을 복사해다가 넣으면 됩니다. 이 부분은 Debug 모드와 Release 모드 두 가지의 함
수가 있으므로 모두 복사해 넣아야 합니다.

(b) 임의의 클래스에서 도큐먼트 클래스에 접근할 때.

CMainFrame *pFr = (CMainFrame *)AfxGetMainWnd();
CTestDoc *pDoc = (CTestDoc *)pFr->GetActiveDocument();

위와 같이 두 줄에 걸쳐 써도 되고 다음처럼 한 줄로 줄여써도 됩니다.

CTestDoc *pDoc = (CTestDoc *) ((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();


4. 뷰 클래스의 포인터를 얻을 경우.

(a) 임의의 클래스에서 뷰 클래스에 접근할 때

뷰 클래스의 포인터를 얻어야 하는 경우는 대부분 다이얼로그에서 뷰에 접근하거나, 스플릿을 사용한 경우 다른
뷰 클래스에서 접근하는 경우가 대부분일 겁니다. 뭐 어떻든 상관없이 다음과 같이 하면 어디서든 뷰에 접근할
수 있습니다.

CTestView *pView = (CTestView *) ((CMainWnd *)AfxGetMainWnd())->GetActiveView();
물론 위의 3번의 경우처럼 두 줄로 나누어 써도 상관이 없습니다.

(b) 도큐먼트 클래스에서 뷰 클래스에 접근을 할 때

도큐먼트 클래스에서 뷰 클래스의 인스턴스 포인터를 얻으려면 GetFirstViewPosition() 함수와 GetNextView()
함수를 조합하여 사용해야 합니다. 이렇게 복잡해지는 이유는 도큐먼트 하나에 여러개의 뷰가 연결될 수 있기 때
문입니다.

도큐먼트에는 이에 연결된 뷰가 연결 리스트 형태로 관리되고 있기 때문에 몇 번째 뷰를 얻을 것인지 선택하고 나
서 위의 함수를 조합하여 사용하면 됩니다.

다음은 도큐먼트와 연결된 모든 뷰 클래스를 차례로 얻어 뷰 클래스의 멤버함수인 UpdateWindow() 함수를 호출하
는 예제입니다.

POSITION pos = GetFirstViewPosition();

while(pos != NULL) {
CView *pView = GetNextView(pos);
pView->UpdateWindow();
}

물론 이와 같은 효과를 내기 위해서 도큐먼트 클래스의 멤버함수인 UpdateAllViews(NULL) 함수를 호출해도 됩니
다. 여기서 쓰이는 인자인 NULL 은 모든 뷰를 업데이트하는 것이고, NULL 대신, 신호를 보내는 뷰의 포인터를 넣
어주면 신호를 보내는 뷰는 빼고 나머지 뷰만 업데이트를 합니다.

도큐먼트에 뷰가 오직 하나만 연결되어 있는 경우에는 다음과 같이 간단하게 뷰 클래스의 인슽턴스 포인터를 얻
어낼 수도 있습니다. m_viewList 는 CDocument 클래스의 멤버변수로서, 뷰를 관리하는 연결 리스트입니다. 이것
을 이용하여 GetHead() 함수를 호출하면 리스트에 들어있는 첫 번째 뷰가 얻어집니다.

void CTestDoc::OnRepaintViews()
{
CView *pView = m_viewList.GetHead();
pView->UpdateWindows();
}

(c) 스플리트 윈도우에서의 각 뷰 클래스에 접근할 때

동적 스플리트 윈도우라면 모든 페인에서 같은 뷰를 사용하므로 별 문제가 되지 않는데, 정적 스플리트 윈도우라
면 각 페인마다 다른 뷰를 사용할 수 있으므로 각 페인별로 뷰의 인스턴스 포인터를 얻는 것이 문제가 되는 경우
가 생길 수 있습니다.

이렇때는 메인 프레임 클래스에서 정의한 CSplitterWnd 클래스의 변수인 m_wndSplitter 의 멤버함수 GetPane()
을 사용하면 각 페인의 뷰에 접근할 수 있습니다.

우선 메인 프레임에서 정의된 m_wndSplitter 변수를 public: 속성으로 바꾸고(외부에서 접근해야 하므로) 메인
클래스의 인스턴스 포인터를 얻은 다음, 다시 여기서 m_wndSplitter 변수에 접근하여 이 멤버변수의 멤버함수
GetPane()을 이용하면 됩니다. 다음은 GetPane()의 함수 원형입니다. 리턴값은 대부분의 경우 CView에서 파생
된 클래스의 인스턴스 포인터가 됩니다.

CWnd* GetPane( int row, int col );

임의의 클래스에서 다음과 같이 사용하면 페인에 연결된 뷰의 포인터를 얻을 수 있습니다.

CTestView *pView = (CTestView *)((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,1);




임의의 클래스의 포인터 얻기


앞에서 SDI에서 각 클래스의 포인터를 얻는 것은 해 보았습니다. 이번엔 MDI에서 이런 작업을 해 보도록 하죠.

먼저 SDI에서의 작업을 참조하시기 바랍니다. SDI와 MDI는 관련되는 부분이 많으니까요.


일반적인 MDI 프로그램에서.


1.애플리케이션 클래스의 포인터를 얻을 때

CWinApp* AfxGetApp()

함수를 사용합니다. 이것은 SDI에서와 동일합니다. App 클래스는 MDI든 SDI든 프로그램 내에서는 하나뿐이니까
요. 다음처럼 사용하면 pApp는 애플리케이션 클래스의 인스턴스 포인터를 가리키게 됩니다.

CTestApp *pApp = (CTestApp *)AfxGetApp();


2. CMDIFrameWnd의 파생클래스인 메인 프레임 클래스의 포인터를 얻을 때

CWnd* AfxGetMainWnd()

함수를 사용합니다. 사용법은 SDI에서와 동일합니다.

CMainFrame *pFr = (CMainFrame *)AfxGetMainWnd();

이렇게 써준 다음에는 pFr은 메인 프레임 클래스의 인스턴스 포인터를 가리키게 됩니다.


3. CMDIChildWnd의 파생클래스인 자식 프레임 윈도우의 포인터를 얻을 때

(a) 활성화된 자식 프레임 윈도우의 포인터를 얻을 때

virtual CFrameWnd* GetActiveFrame( );

함수를 사용합니다. MSDN에 실려있는 이 함수의 리턴값에 대한 설명을 보면, 애플리케이션이 SDI이거나 MDI 프레
임 윈도우에 활성화된 도큐먼트가 없을 때, 리턴값은 묵시적인 this 포인터가 된다고 하네요.

사용법은 다음과 같습니다.

CMDIChildWnd* pChild = (CMDIChildWnd *)AfxGetMainWnd()->GetActiveFrame();


4. 뷰 / 도큐먼트 클래스의 포인터를 얻을 때

SDI에서 구한 것과 마찬가지 방법을 사용한다. SDI에서는 메인 프레임의 포인터를 얻어 GetActiveView() 또는
GetActiveDocument() 함수를 사용했지만, MDI에서는 차일드 프레임의 포인터를 얻어 거기서 GetActiveView
() / GetActiveDocument() 함수를 사용하면 된다. 사용법은 거의 동일하다.

MDI에서도 SDI와 마찬가지로 도큐먼트나 뷰가 여러 개가 연결될 수 있으므로 그점만 주의해 주면 된다.

사용법은 다음과 같다.

CMDIChildWnd* pChild = (CMDIChildWnd *)AfxGetMainWnd()->GetActiveFrame();

// 뷰 클래스의 포인터 얻기
CTestView *pView = (CTestView *)pChild->GetActiveView();

// 도큐먼트 클래스의 포인터 얻기
CTestDoc *pDoc = (CTestDoc *)pChild->GetActiveDocument();


출처 : zextors personal website
Posted by Gungume
,
CTestApp, CMainFrame, CTestDoc, CTestView

◎ CTestApp에서
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CTestDoc* pDoc = (CTestDoc*)((CMainFrame*)AfxGetMainWnd())->GetActiveDocument();
CTestView* pView = (CTestView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView();

◎ CMainFrame에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CTestDoc* pDoc = (CTestDoc*)GetActiveDocument();
CTestView* pView = (CTestView*)GetActiveView();

◎ CTestDoc에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CTestView* pView = (CTestView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView();

◎ CTestView에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
or (CMainFrame*)GetParent();
CTestDoc* pDoc = (CTestDoc*)((CMainFrame*)AfxGetMainWnd())->GetActiveDocument();
or (CTestDoc*)GetDocument();

출처 : zextors personal website
Posted by Gungume
,




컨트롤 묶어서 제어하기

계산기의 숫자버튼 등은 수치만 바뀌고, 하는 역할은 동일하다.

이런것을 단순히 BN_CLICKED 메시지를 이용 각각의 버튼에 대해 핸들러 함수를 만들어 줄수는 있지만 코드도 길어지고 비효율적이다.

이럴때 "ON_CONTROL_RANGE" 매크로를 이용하면 리소스ID를 이용해서 함수 한곳에서 여러개의 컨트롤을 제어할 수 있다...

예제 프로그램을 보면 버튼이 총 9개 있는데 "Resource.h" 파일에서 각 버튼의 리소스ID를 보면 아래와 같다.

#define IDC_BUTTON1                     1001
#define IDC_BUTTON2                     1002
#define IDC_BUTTON3                     1003
#define IDC_BUTTON4                     1004
#define IDC_BUTTON5                     1005
#define IDC_BUTTON6                     1006
#define IDC_BUTTON7                     1007
#define IDC_BUTTON8                     1008
#define IDC_BUTTON9                     1009
위의 예제를 보면 ID값이 순서데로 나온것을 알수 있는데 이것은 컨트롤을 만든 순서와 같다...중복을 피해서 임의로 수정이 가능하지만 쉽게 사용하기 위해서 컨트롤을 배치할 때 부터 사용할 순서데로 만드는게 좋은듯하다...

다음으로는 각 컨트롤을 제어할 함수를 만들어야 한다...

일단 헤더파일에 다음과 같이 코딩을 한다...함수명은 임의로 정하고 인자값으로 UINT형 값이 하나 들어가는데 이곳에 리소스 ID가 들어간다...
//{{AFX_MSG(CRangeDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void ControlRange(UINT ID);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

다음으로 가장 중요한것으로 메시지맵에 "ON_CONTROL_RANGE" 매크로를 삽입해준다...
BEGIN_MESSAGE_MAP(CRangeDlg, CDialog)
//{{AFX_MSG_MAP(CRangeDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON1, IDC_BUTTON9, ControlRange)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
"ON_CONTROL_RANGE" 매크로의 각 인자를 대략적으로 설명하면 "IDC_BUTTON1~IDC_BUTTON9" 사이의 리소스ID에 대해서 "BN_CLICKED" 즉 버튼 클릭에 대한 이벤트가 발생하면 "ControlRange" 함수를 호출하라는 의미이다...

마지막으로 소스파일로 가서 아래와 같이 각 컨트롤을 제어할 함수를 작성한후, 함수내에서 매개변수로 넘어온 리소스ID를 if문이나 switch~case등을 이용해서 실제적인 코딩을 한다...
void CRangeDlg::ControlRange(UINT ID)
{
    // 실제적인 코딩...
}

아래는 이 매크로의 원형과 매개변수에 대한 MSDN의 문서이다.
- 원형 -
ON_CONTROL_RANGE(
wNotifyCode
, id1, id2, memberFxn )

- 매개변수 -
wNotifyCode : The notification code to which your handler is responding.

id1 : Command ID at the beginning of a contiguous range of control IDs.

id2 :
Command ID at the end of a contiguous range of control IDs.

memberFxn :
The name of the message-handler function to which the controls are mapped.
(사용언어 및 제작툴 : MFC / VC++ 6.0)
Posted by Gungume
,