<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="http://rss.egloos.com/style/blog.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
	<title>Programmer greenfrog !!</title>
	<link>http://greenfrog7.egloos.com</link>
	<description>새로운 도전을 위해 약 1년간 자리를 비웁니다. 그 동안 블로그에 방문해 주신 분들께 진심으로 감사드립니다. 1년 뒤 .NET 관련 양질의 정보를 가지고 돌아오겠습니다. </description>
	<language>ko</language>
	<pubDate>Sun, 01 Mar 2009 06:34:41 GMT</pubDate>
	<generator>Egloos</generator>
	<image>
		<title>Programmer greenfrog !!</title>
		<url>http://pds12.egloos.com/logo/200809/11/64/f0055064.jpg</url>
		<link>http://greenfrog7.egloos.com</link>
		<width>80</width>
		<height>61</height>
		<description>새로운 도전을 위해 약 1년간 자리를 비웁니다. 그 동안 블로그에 방문해 주신 분들께 진심으로 감사드립니다. 1년 뒤 .NET 관련 양질의 정보를 가지고 돌아오겠습니다. </description>
	</image>
  	<item>
		<title><![CDATA[ namespace를 사용 시 전방선언 할 때 error C2872에 대해서 ]]> </title>
		<link>http://greenfrog7.egloos.com/1389586</link>
		<guid>http://greenfrog7.egloos.com/1389586</guid>
		<description>
			<![CDATA[ 
  <p>namespace로 쌓여 있는 클래스에서 쌓여있지 않은 클래스를 전방선언해서 사용할 때 <strong>error C2872</strong>가 발생하였습니다. <br>아래는 output 창에 나타난 빌드내용입니다. <br><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>------ Build started: Project: CompilerErrorC2872, Configuration: Debug Win32 ------<p></p><p>Compiling...<br>NamespaceOuterClass.cpp<br>d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceOuterClass.cpp(8) : error C2872: 'CCommonClass' : ambiguous symbol<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; could be 'd:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\CommonClass.h(7) : CCommonClass'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'd:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceInnerClass.h(15) : Namespace::CCommonClass'<br>d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceOuterClass.cpp(9) : error C2664: 'Namespace::CNamespaceInnerClass::CNamespaceInnerClass(Namespace::CCommonClass *)' : cannot convert parameter 1 from 'CCommonClass *' to 'Namespace::CCommonClass *'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast<br>Generating Code...<br>Compiling...<br>NamespaceInnerClass.cpp<br>d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceInnerClass.cpp(8) : error C2872: 'CCommonClass' : ambiguous symbol<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; could be 'd:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\CommonClass.h(7) : CCommonClass'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'd:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceInnerClass.h(15) : Namespace::CCommonClass'<br>d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceInnerClass.cpp(9) : error C2511: 'Namespace::CNamespaceInnerClass::CNamespaceInnerClass(CCommonClass *)' : overloaded member function not found in 'Namespace::CNamespaceInnerClass'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\NamespaceInnerClass.h(18) : see declaration of 'Namespace::CNamespaceInnerClass'<br>Generating Code...</p><p>Build log was saved at "<a href="file:///d:/Programming/cpp/study/CompilerErrorC2872/CompilerErrorC2872/Debug/BuildLog.htm">file://d:\Programming\cpp\study\CompilerErrorC2872\CompilerErrorC2872\Debug\BuildLog.htm</a>"<br>CompilerErrorC2872 - 4 error(s), 0 warning(s)</p><p><br>---------------------- Done ----------------------</p><p>&nbsp;&nbsp;&nbsp; Build: 0 succeeded, 1 failed, 0 skipped</p><p></p></div><p><br><br>빌드 내용을 살펴 보면 CCommomClass의 선언이 모호해서 compiler가 어떤 CCommonClass를 선택하여 빌드를 해야 할 지 모른다는 내용입니다. NamespaceOuterClass와 NamespaceInnerClass에서 에러 발생하고 있지만 NamespaceOuterClass의 소스 내용을 분석해 보니 이 클래스에는 문제의 소지가 전혀 없어 보입니다. 그래서 CNamespaceInnerClass를 살펴보니 문제의 소지가 다분해 보이는 코드를 발견하였습니다.<br><br>그럼, 어디가 문제였을까요? 일단 클래스 다이어그램과 문제의 코드를 보여드릴테니까 한 번 고민해보세요 ~~<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa290a661df.png" width="500" height="217.281879195" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa290a661df.png');" /></div><div style="BACKGROUND-COLOR: rgb(239,239,239)"><br>// CNamespaceInnerClass.h<br><br>namespace Namespace<br>{<p></p><p>class CCommonClass;</p><p>class CNamespaceInnerClass<br>{<br>public:<br>&nbsp;CNamespaceInnerClass(CCommonClass* arg_pCommonClass);<br>&nbsp;~CNamespaceInnerClass(void);</p><p>protected:<br>&nbsp;CCommonClass* m_pCommonClass;</p><p>};</p><p>}<br></p></div><br>답을 찾으셨나요?? 정답은 class CCommonClass의 선언 위치였습니다. 위 클래스 다이어그램을 살펴보시면 CCommonClass는 Namespace라는 namespace에 속해 있는 클래스가 아닙니다. 그런데 이 클래스를 namesapce Namespace 내부에 선언을 해뒀기 때문에 <strong>error C2872</strong>가 발생한 것이었습니다.<br><br>아래는 이 문제를 해결 한 코드입니다.<br><br><div style="BACKGROUND-COLOR: rgb(239,239,239)"><br>// CNamespaceInnerClass.h<br><br><strong>class CCommonClass;&nbsp;&nbsp;&nbsp;&nbsp;// namespace Namespace 밖으로 선언을 옮겼습니다.<br></strong><br>namespace Namespace<br>{<p>&nbsp;</p><p>class CNamespaceInnerClass<br>{<br>public:<br>&nbsp;CNamespaceInnerClass(CCommonClass* arg_pCommonClass);<br>&nbsp;~CNamespaceInnerClass(void);</p><p>protected:<br>&nbsp;CCommonClass* m_pCommonClass;</p><p>};</p><p>}<br><br></p></div><br><br><strong>* 예제 프로젝트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds11.egloos.com/pds/200903/01/64/CompilerErrorC2872.zip"><strong>CompilerErrorC2872.zip</strong></a><p></p>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1389586#comments</comments>
		<pubDate>Sun, 01 Mar 2009 06:34:10 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ STL 맵을 이용하여 벡터의 중복 된 데이터 제거하기 ]]> </title>
		<link>http://greenfrog7.egloos.com/1389475</link>
		<guid>http://greenfrog7.egloos.com/1389475</guid>
		<description>
			<![CDATA[ 
  <p>데이터를 다루다 보면 벡터에 중복 된 데이터를 제거해야 할 경우가 발생합니다. 중복 된 데이터를 제거하는 방법이야 여러가지가 있겠지만 STL 맵을 이용하여 중복 된 데이터를 제거하는 방법에 대해서 알아보겠습니다.<br><br>먼저, 상황을 아래와 같이 만들어 보았습니다. 아래 배열 x1과 x2의 각 인덱스의 값은&nbsp;서로 쌍으로 이용됩니다. 즉, x1[0]과 x2[0]의 값이 서로 쌍으로 이용됩니다. 이 경우 (x1[0], x2[0])의 값과 (x1[1], x2[1])의 값은 서로 중복 되므로 (x1[0], x2[0])의 값만 남기고 (x1[1], x2[1])의 값은 버리려고 합니다. 이때, STL &nbsp;맵을 이용하여 중복 된 데이터를 제거한 후 남긴 데이터를 벡터에 담아 보도록 하겠습니다.<br><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>double x1[] = {-1.00, -1.00, -1.00, -1.00, -0.33, -0.33, 0.33, 0.33, 1.00, 1.00, 1.00, 1.00};<br>double x2[] = {-0.89, -0.89, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.89, 0.89};<br><br></div><br>STL 맵 중 멀티 맵이 아닌 일반 맵은 중복 Key를 허용하지 않습니다. 즉, 같은 Key의 데이터를 삽입하려고 하면 삽입이 되지 않지요. 이 원리를 이용하면 위 배열의 중복 된 값을 쉽게 제거할 수 있습니다. (x1[0], x2[0])의 데이터를 문자열로 변환 후 이 값을 키로 만듭니다. 예를 들어 "-1.00#-0.89" 처럼 말이죠. 이때, 반드시 중간에 '#'과 같은 구분자를 주도록 합니다. 이렇게 구분자를 넣어주는 이유는 0.0이란 값과 10이란 값을 위의 방법으로 문자열로 변환 하는 경우 "0.010"이란 값이 나옵니다. 그런데 0.01이란 값과 0이란 값 또한 위 방법으로 문자열로 변환하면 "0.010"이 됩니다. 이럴 경우를 대비하여 각 값 간 사이에 구분자를 꼭 붙여주도록 합니다. 이렇게 Key를 만들었으면 값으로 현재 배열의 index를 줍니다. 그럼 중복 되는 값의 배열 index는 제외한 체 map에 삽입이 되게 됩니다. 그 후 맵을 순회 하면서 map의 저장 된 value 즉, 배열의 index를 각 배열에 적용하여 중복 된 데이터의 첫번째 값만 빼내어 vector에 담습니다.<br><br>위 설명을 그림으로 표현하면 아래와 같습니다.<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa1d88184e6.png" width="459" height="320" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa1d88184e6.png');" /></div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa1d8cde137.png" width="388" height="309" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200903/01/64/f0055064_49aa1d8cde137.png');" /></div><p></p><p><br>위 설명을 소스로 구현해 보았습니다.<br><br><div style="BACKGROUND-COLOR: rgb(239,239,239)"><br>// RepeatDataFilter.cpp : Defines the entry point for the console application.<br>//<p></p><p>#include "stdafx.h"</p><p>#include &lt;map&gt;<br>#include &lt;vector&gt;<br>#include &lt;string&gt;</p><p>using namespace std;</p><p>template&lt;typename T&gt;<br>void RepeatDataFilter(const vector&lt;T&gt;&amp; arg_refVtrInX1, const vector&lt;T&gt;&amp; arg_refVtrInX2, vector&lt;T&gt;&amp; arg_refVtrOutX1, vector&lt;T&gt;&amp; arg_refVtrOutX2)<br>{<br>&nbsp;map&lt;string, int&gt; mFilter;<br>&nbsp;TCHAR szBuf[100];</p><p>&nbsp;int nSize = (int) arg_refVtrInX1.size();<br>&nbsp;for(int i=0; i&lt;nSize; i++)<br>&nbsp;{<br>&nbsp;&nbsp;memset(szBuf, 0, sizeof(TCHAR));</p><p>&nbsp;&nbsp;_stprintf(szBuf, _T("%f#%f"), arg_refVtrInX1[i], arg_refVtrInX2[i]);<br>&nbsp;&nbsp;pair&lt;string, int&gt; item(szBuf, i);<br>&nbsp;<br>&nbsp;&nbsp;mFilter.insert(item);<br>&nbsp;}</p><p>&nbsp;map&lt;string, int&gt;::iterator it;<br>&nbsp;for(it = mFilter.begin(); it != mFilter.end(); it++)<br>&nbsp;{<br>&nbsp;&nbsp;arg_refVtrOutX1.push_back(arg_refVtrInX1[it-&gt;second]);<br>&nbsp;&nbsp;arg_refVtrOutX2.push_back(arg_refVtrInX2[it-&gt;second]);<br>&nbsp;}<br>}</p><p>int _tmain(int argc, _TCHAR* argv[])<br>{<br>&nbsp;double x1[] = {-1.00, -1.00, -1.00, -1.00, -0.33, -0.33, 0.33, 0.33, 1.00, 1.00, 1.00, 1.00};<br>&nbsp;double x2[] = {-0.89, -0.89, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.89, 0.89};</p><p>&nbsp;vector&lt;double&gt; vtrInitX1, vtrInitX2;<br>&nbsp;vector&lt;double&gt; vtrX1, vtrX2;</p><p>&nbsp;int nArr = (int) (sizeof(x1) / sizeof(double));</p><p>&nbsp;for(int i=0; i&lt;nArr; i++)<br>&nbsp;{<br>&nbsp;&nbsp;vtrInitX1.push_back(x1[i]);<br>&nbsp;&nbsp;vtrInitX2.push_back(x2[i]);<br>&nbsp;}</p><p>&nbsp;RepeatDataFilter&lt;double&gt;(vtrInitX1, vtrInitX2, vtrX1, vtrX2);</p><p>&nbsp;TRACE(_T("\n\n=========================================================\n\n"));<br>&nbsp;size_t nSize = vtrX1.size();<br>&nbsp;for(size_t i=0; i&lt;nSize; i++)<br>&nbsp;{<br>&nbsp;&nbsp;TRACE(_T("\n%5.2f\t%5.2f"), vtrX1[i], vtrX2[i]);<br>&nbsp;}<br>&nbsp;TRACE(_T("\n\n=========================================================\n\n"));</p><p>&nbsp;return 0;<br>}</p><p></p></div><br><strong><br>*결과</strong> <br><br><div style="BACKGROUND-COLOR: #f0f8ff"><br>=========================================================<p></p><p><br>-0.33&nbsp; 0.00<br>-1.00&nbsp;-0.89<br>-1.00&nbsp; 0.00<br>&nbsp;0.33&nbsp; 0.00<br>&nbsp;1.00&nbsp; 0.00<br>&nbsp;1.00&nbsp; 0.89</p><p>=========================================================<br><br></p></div><br><strong>* 예제 프로젝트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds13.egloos.com/pds/200903/01/64/RepeatDataFilter.zip"><strong>RepeatDataFilter.zip</strong></a><br>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1389475#comments</comments>
		<pubDate>Sun, 01 Mar 2009 05:33:55 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ MFC ActiveX Control in IE Doesn't Detect Keystrokes ]]> </title>
		<link>http://greenfrog7.egloos.com/1378219</link>
		<guid>http://greenfrog7.egloos.com/1378219</guid>
		<description>
			<![CDATA[ 
  <p>예전에 ActiveX Control을 이용해서 차트 컨트롤을 개발한 적이 있었습니다. ActiveX control에 올라간 Edit control에 키보드 입력을 통해 좌표를 입력하면 차트가 입력한 좌표에 따라 변화 하는 기능을 추가할때였는데 도통 키보드 메시지가 받아지지&nbsp;않았습니다.&nbsp;당근, 문제를 해결하기는 했으나 그 문제에 대해 문서화를 시켜 놓지 않았더니 같은 문제가 최근에 발생했을때&nbsp;다시&nbsp;삽질을 해댔지 뭡니까!! 문서화의 중요성 다시 한 번 마음에 새기게 됩니다. ㅡㅡ;;<br><br>제가 만든 ActiveX Control의 클래스 다이어그램을 소개하면 아래의 그림과 같습니다. CMyAcitveXView에는 Edit control이 있고 이에 차트 좌표를 입력하고 Enter 또는 Tab 키를 입력하면 좌표값이 차트 Control로 입력되어 차트가 변화하도록 되어있습니다. 하지만 키보드 메세지를 CMyAcitveXView의 CEdit Control은 받지 못합니다.<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200902/22/64/f0055064_49a0af124c6b8.png" width="500" height="145.01510574" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200902/22/64/f0055064_49a0af124c6b8.png');" /></div><br>아래는 이 문제에 대한 Microsoft 고객지원 사이트의 기술문서 링크입니다.<br><br><a href="http://support.microsoft.com/default.aspx?scid=KB;en-us;Q168777#appliesto%20-%20PRB:%20MFC%20ActiveX%20Control%20in%20IE%20Doesn't%20Detect%20Keystrokes"><span style="FONT-SIZE: 130%"><strong>MFC ActiveX Control in IE Doesn't Detect Keystrokes</strong></span></a><br><br>그럼, 위 기술문서를 통해 이 문제를 해결하는 방법에 대해서 하나씩 알아보도록 하겠습니다.<br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br><strong>SYMPTOMS<br></strong><br>Accelerator keys, such as ARROW keys, are first received by the message pump of the ActiveX control's container. Even if the control has the focus, it does not receive messages for keystrokes that have special meaning to control containers, such as ARROW and TAB keys. MFC ActiveX controls have a chance to intercept these messages by overriding their PreTranslateMessage function. <br><br>However, PreTranslateMessage is not always called for an MFC ActiveX control. <br><br></div><br><div style="BACKGROUND-COLOR: #f0f8ff"><br><strong>증상<br></strong><br>화살표키와 같은 엑셀레이터 키들은 ActiveX control's container의 메시지 펌프로 처음 전달 됩니다. 비록 control이 포커스를 받고 있다고 하더라도 키보드 메시지는 control로 전달되어지지 않습니다. MFC ActiveX control들은 이러한 키보드 메시지를PreTranslateMessage 함수를 오버라이딩 하므로써 키보드 메시지를 가로챌 수 있습니다. <br><br>그러나, PreTranslateMessage는 MFC ActiveX control에서는 항상 호출 되지 않습니다.<br><br></div><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br><strong>CAUSE</strong><br><br>PreTranslateMessage in an MFC ActiveX control is called by the TranslateAccelerator method of the IOleInPlaceActiveObject interface of the control. Internet Explorer only calls this method for the control that is currently UI-Active. Only one control can be UI-Active at a time. <br><br>Internet Explorer does not automatically UI-Activate any controls when a page is first loaded. Internet Explorer waits until the user tabs to an ActiveX control on the page to UI-Activate it. Also, MFC ActiveX controls UI-Activate themselves when they are clicked with the mouse. In an MFC ActiveX control, this is done in COleControl::OnLButtonUp. <br><br>If you have a child control inside your COleControl, mouse-click messages on the child control are not sent to the COleControl and MFC does not UI- Activate the ActiveX control, even though the child control has just been given the keyboard focus. Internet Explorer intercepts the keystrokes and does not give the control a chance to filter them in PreTranslateMessage. <br><br></div><br><div style="BACKGROUND-COLOR: #f0f8ff"><br><strong>원인<br><br></strong><strong></strong>MFC ActiveX control의 PreTranslateMessage 함수는 control의 IOleInPlaceActiveObject interface의 TranslateAccelerator method에 의해서 호출 됩니다. Internet Explorer는 오직 현재 활성화 된 control을 위해 이 method를 호출합니다. 한 번에 오직 하나의 control만이 활성화 될 수 있습니다.<br><br>Internet Explorer는 웹 페이지가 처음으로 로드되었을 때 어떠한 control들도 자동으로 활성화 시키지 않습니다. Internet Explorer는 사용자가 user tabs(이게 사용자가 탭키를 누르는것을 이야기하는건지 아니면 다른 의미가 있는건지 모르겠네요 ㅡㅡ??) 웹 페이지의 ActiveX control을 활성화 시킬때 까지 대기합니다. 또한, MFC ActiveX controls 마우스 클릭을 통해서도 활성화가 됩니다.<br>MFC ActiveX control은 COleControl::OnLButtonUp 메시지가 완료되었을때 활성화 됩니다.<br><br>만약 당신의 COleControl이 내부에 child control (제가 소개한 클래스 다이어그램에서 CMyActiveXView에 해당합니다.)을 가지고 있고 마우스 이벤트가 child control에서 발생한다면 이 메시지는 COleControl에게 보내지지 않으며 MFC는 child control이 키보드 포커스를 가지고 있다고 하더라도 ActiveX control을 활성화 시키지 않습니다. Internet Explorer가 키보드 메시지를 가로채서 control이 PreTranslateMessage함수가 메시지를 가져올 기회를 주지 않기 때문입니다.<br><br></div><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br><strong>RESOLUTION</strong><br><br>Here is a typical PreTranslateMessage. This code forwards ARROW, HOME, and END keys back to the control so that they can be received using a MESSAGE_MAP entry:&nbsp;<br><br>&nbsp;&nbsp;&nbsp;// trap keys and forward on to the control<br>&nbsp;&nbsp; BOOL CMyActiveXCtrl::PreTranslateMessage(MSG* pMsg)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (pMsg-&gt;message)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_KEYDOWN:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_KEYUP:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (pMsg-&gt;wParam)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_UP:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_DOWN:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_LEFT:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_RIGHT:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_HOME:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_END:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SendMessage (pMsg-&gt;message, pMsg-&gt;wParam, pMsg-&gt;lParam);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Windowless controls won't be able to call SendMessage.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Instead, just respond to the message here.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return COleControl::PreTranslateMessage(pMsg);<br>&nbsp;&nbsp; }<br><br></div><br><div style="BACKGROUND-COLOR: #f0f8ff"><br><strong>해결</strong><br><br>아래 코드는&nbsp;일반적인 PreTranslateMessage함수 입니다.&nbsp;이 코드는 화살표, HOME, 및 END&nbsp;키들을 control의 MESSAGE_MAP 항목을 사용하여 받아 사용할 수 있도록 전달합니다.<br><br>저 같은 경우는&nbsp;Enter키와 Tab키에서&nbsp;CEdit control의 값을 얻어와야 하므로 위 MS 기술문서의 코드를 아래와 같이&nbsp;고쳐서 사용하였습니다.<br><br>&nbsp;&nbsp;&nbsp;// trap keys and forward on to the control<br>&nbsp;&nbsp; BOOL CMyActiveXCtrl::PreTranslateMessage(MSG* pMsg)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (pMsg-&gt;message)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_KEYDOWN:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_KEYUP:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (pMsg-&gt;wParam)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_TAB:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case VK_RETURN:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pView-&gt;GetPoint();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return COleControl::PreTranslateMessage(pMsg);<br>&nbsp;&nbsp; }<br><br></div><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>If you have a child control within your ActiveX control, you need to UI-Activate the whole control whenever that child control is activated. For example, if you have an edit control inside your ActiveX control, add a handler as follows to your ActiveX control class: <br><br>int CMyActiveXCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (!m_bUIActive)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnActivateInPlace (TRUE, NULL); // == UI-Activate the control<br>&nbsp;&nbsp;&nbsp;&nbsp;return COleControl::OnMouseActivate(pDesktopWnd, nHitTest, message);<br>}<br><br></div><br><div style="BACKGROUND-COLOR: #f0f8ff"><br>만약 당신의 ActiveX control이 child control을 가지고 있다면, 모든 control이 활성화 될 때는 언제나 child control도 활성화 될 필요가 있습니다. 예를 들어 만약 당신의 ActiveX control 내부에 edit control이 있다면, 아래 핸들러를 당신의 ActiveX control 클래스에 추가합니다.<br><br></div><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>Because Internet Explorer may not immediately UI-Activate a control, even if that is the only control on the page, it may be desirable to automatically request a UI-Activation when the control is created. This can be done during the COleControl::OnCreate (WM_CREATE) handler. Windowless controls do not get WM_CREATE or any windows messages; therefore, this code won't work in a windowless control. Also note that this does not guarantee that a control will remain UI-Activated. If there are other controls on a page that request UI-Activation in a similar manner, only one will eventually be UI-Activated and receive keystroke messages as described. And if the user TABs away from an ActiveX Control, Internet Explorer will automatically UI-deactivate the control. <br>int CMyActiveXCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) <br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (COleControl::OnCreate(lpCreateStruct) == -1) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1; <br>&nbsp;&nbsp;&nbsp;&nbsp;OnActivateInPlace (TRUE, NULL); // == UI-Activate the control <br>&nbsp;&nbsp;&nbsp;&nbsp;return 0; <br>}<br><br></div><br><div style="BACKGROUND-COLOR: #f0f8ff"><br>Internet Explorer는 웹 페이지에 오직 control 뿐이라고 해도 즉시 control을 활성화 시키지 않기 때문에 control이 생성되자 마자 활성화 시키는 것이 바람직하다고 할 수 있겠습니다. 이 방법은 COleControl::OnCreate (WM_CREATE) handler를 통해서 구현 될 수 있습니다. 윈도우가 없는 control들은 WM_CREATE 또는 어떠한 윈도우 메시지도 받을 수 없기 때문에 윈도우가 없는 control의 경우 아래의 코드는 무의미합니다. 또한 이 코드가 control이 활성화를 유지하도록 보장하지는 않습니다. 만약 다른 control들이 웹 페이지 상에서 같은 방법으로 활성화 되었다면, 오직 하나만 마지막으로 활성화 될 것이고, 키보드 메시지를 받을 수 있을 것입니다. And if the user TABs away from an ActiveX Control, (해석이 안되네요 ㅡㅡ;;) Internet Explorer 자동으로 control을 활성화 시킬 것입니다.<br><br></div><br>위 방법대로 소스코드를 수정하고 테스트해 본 결과 아주 잘 동작을 합니다. 굳!!<br>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1378219#comments</comments>
		<pubDate>Sun, 22 Feb 2009 05:43:32 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 전방 선언에 대해서 ]]> </title>
		<link>http://greenfrog7.egloos.com/1363680</link>
		<guid>http://greenfrog7.egloos.com/1363680</guid>
		<description>
			<![CDATA[ 
  <p>전방 선언에 대해서 알아보았습니다. 웹에 게시 된 글들을 여러개 살펴 보았는데 아래의 이유에 의해서 사용된다는 결론을 내리게 되었습니다.<br><br><div style="BACKGROUND-COLOR: #f0f8ff"><br><strong>불필요한 헤더 파일이 복잡하게 포함되는 것을 방지하며, Compile 속도를 향상 시켜줍니다.<br></strong><br></div><p><br>그럼, 위의 결론을 아래와 같은 클래스 구조를 가정하여 설명하도록 하겠습니다.<br><br></p><p><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200902/13/64/f0055064_49957687021de.png" width="386" height="155" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200902/13/64/f0055064_49957687021de.png');" /></div>위 클래스 구조를 보면 CUser클래스가 CManager 클래스를 사용하고 있고 CManager 클래스는 CModuleOne과 CModuleTwo 클래스를 사용하고 있습니다. 이 경우 CUser클래스는 CManager클래스를 사용하는 동시에 이 클래스를 통해서 CModuleOne과 CModuleTwo의 기능을 사용할 것입니다. 결국 CUser 클래스는 CManager 클래스만 알면 되는 것이지요.&nbsp;만약, CManager 클래스가 CModuleOne과 CModuleTwo 클래스를 멤버변수로 관리하고 있다고&nbsp;가정할때 전방선언을 하지 않고 헤더파일을 직접&nbsp;포함하고 있다면&nbsp;어떻게 될까요? CUser는 굳이 포함할 필요가 없는 CModuleOne 클래스와 CModuleTwo 클래스의 헤더파일들을 포함하게 되어버립니다. 즉, 아래 코드와 같이 되어버리는 것이지요. <br><br>아래는 CManager클래스의 헤더파일 내용입니다.<br><br><div style="BACKGROUND-COLOR: rgb(239,239,239)"><br>#pragma once<br><br>#include "ModuleOne.h"<br>#include "ModuleTwo.h"<br><p></p><p>class CManager<br>{<br>public:<br>&nbsp;CManager(void);<br>&nbsp;~CManager(void);<br>};<br><br>아래는 CManager클래스의 헤더파일을 포함하고 있는 CUser클래스의 cpp 내용입니다.<br><br>#include ".\user.h"<br>#include "Manager.h"<br></p><p>CUser::CUser(void)<br>{<br>}</p><p>CUser::~CUser(void)<br>{<br>}<br><br></p></div><br>이는 곧 <strong><span style="COLOR: #990000">컴파일 속도를 저해하는 원인</span></strong>이 됩니다. 이유에 대해서 예를 들면, CModuleTwo 클래스를 수정했을 경우 이를 직접적으로 사용하고 있는 CManager 클래스만 함께 컴파일 되면 되는데&nbsp;이를 직접적으로 사용하고 있지 않음에도 불구하고 CManager클래스의 헤더에 CModuleTwo클래스의 헤더가 포함되어 있기 때문에 CUser 클래스까지 함께 컴파일이 되어버리기 때문입니다.<br><br>아래는 위 코드를&nbsp;컴파일 한 후, CModuleTwo 클래스를 수정하여 다시&nbsp;컴파일 한 결과 입니다. ModuleTwo.cpp와 Manager.cpp와 함께 User.cpp도&nbsp;컴파일 되는 것을 확인 하실수 있습니다. <br><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>------ Build started: Project: ForwardDeclaration, Configuration: Debug Win32 ------<p></p><p>Compiling...<br><span style="COLOR: #990000"><strong>User.cpp</strong></span><br>Generating Code...<br>Skipping... (no relevant changes detected)<br><strong><span style="COLOR: #000099">ModuleTwo.cpp<br>Manager.cpp</span></strong><br>Linking...<br><br></p></div><br>그럼 위의 문제의 코드를 전방선언으로 고쳐주면 어떻게 될까요?&nbsp;아래의 코드를 보면 전방선언을 통해 CModuleOne클래스와 CModuleTwo클래스의 헤더를 CManager 클래스의 cpp파일에 숨겼기 때문에 CUser클래스에서는 불필요하게 CModuleOne클래스와 CModuleTwo클래스의 헤더파일이 포함 되는 것을 방지하고 있는 것을 알 수 있습니다. <br><br><div style="BACKGROUND-COLOR: rgb(239,239,239)"><br>아래는 CManager클래스의 헤더파일 내용입니다.<br><br>#pragma once<br><p></p><p>class CModuleOne;<br>class CModuleTwo;</p><p><br>class CManager<br>{<br>public:<br>&nbsp;CManager(void);<br>&nbsp;~CManager(void);<br>};<br><br>아래는 CManager클래스의 헤더파일을 포함하고 있는 CUser클래스의 cpp 내용입니다.<br><br>#include ".\user.h"<br>#include "Manager.h"</p><p><br>CUser::CUser(void)<br>{<br>}</p><p>CUser::~CUser(void)<br>{<br>}<br><br></p></div><br>이는 <span style="COLOR: #990000"><strong>컴파일 속도의 향상</strong></span>으로 이어집니다. 전방선언을 하지 않고 헤더파일을 직접 포함하고 CModuleTwo 클래스를 수정한 후 컴파일 할 때와 동일하게 전방선언을&nbsp;하고 CModuleTwo 클래스를 수정한 후 컴파일을 해 보았습니다. 결과는 아래와 같습니다. 헤더파일을 직접 포함한 경우는 User.cpp도 함께 컴파일 되었었지만 이번에는 컴파일에서 제외 되었습니다.<br><br><div style="BACKGROUND-COLOR: rgb(249,249,212)"><br>------ Build started: Project: ForwardDeclaration, Configuration: Debug Win32 ------<p></p><p>Compiling...<br><strong><span style="COLOR: #000099">ModuleTwo.cpp</span></strong><br>Generating Code...<br>Skipping... (no relevant changes detected)<br><strong><span style="COLOR: #000099">Manager.cpp</span></strong><br>Linking...<br><br></p></div><br>위 예제는 간단한 클래스로만 이루어졌기 때문에 헤더파일이 복잡하게 얽히는 문제와 컴파일 속도의 향상에 대한 논점이 크게 부각이 되지 않겠지만 이를 실제 프로젝트에 연결지어 생각해 보면 전방선언의 효율성에 대해서 알 수 있습니다.<br><br><strong>* 참고 사이트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://crazytazo.com/"><strong>김재호의 디지털보단 아날로그</strong></a><strong> - </strong><a href="http://www.crazytazo.com/25" rel="bookmark"><font size="+0"><strong>전방선언과 컴파일 의존성</strong></font></a><p></p>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1363680#comments</comments>
		<pubDate>Fri, 13 Feb 2009 14:16:32 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Buffer overflow에 의해 프로그램이 죽는 현상 ]]> </title>
		<link>http://greenfrog7.egloos.com/1363522</link>
		<guid>http://greenfrog7.egloos.com/1363522</guid>
		<description>
			<![CDATA[ 
  <p>다음은 <strong><span style="COLOR: #660000">Buffer overflow</span></strong>를 일으킬 수 있는 코드의 일부 입니다. 물론 개발자의 실수로 만든 코드입니다. 일단 한 번 보실까요 ~<br />
<br />
<div style="BACKGROUND-COLOR: rgb(239,239,239)"><br />
#define BUF&nbsp;&nbsp;4<br />
#define _BUF&nbsp;6<p></p><p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nArray[BUF];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ZeroMemory(nArray, sizeof(int) * _BUF);<br />
<br />
</p></div><br />
<br />
위 코드를 잠깐만 보시더라도 금방 문제점을 찾아 내실 수 있으실 것 입니다. nArray 배열은 int형 4개의 메모리 공간을 할당받았지만 메모리를 초기화 시켜줄때 그만 6개의 공간을 초기화 해버리고 말았습니다. 즉, <strong><span style="COLOR: #660000">Buffer overflow</span></strong>가 일어난 것입니다. <span style="COLOR: #660000"><strong>Buffer overflow</strong></span>의 위험성에 대해서는 두번 세번 강조해도 전혀 지나치지 않을 정도로 심각한 문제를 야기 합니다.&nbsp;예를 든다면, <span style="COLOR: #660000">위 코드에서 침범한 int형 2개의 공간에 프로그램을 운영하는데 있어서 중요한 데이터가 저장되어 있었다면 프로그램이 실행 도중 죽는 다던가 아니면 아예 실행이 안된다던가 그것도 아니면 프로그램을 종료시킬 때 어떠한 문제가 발생해서 그 동안 프로그램을 이용하면서 기록해 두었던 데이터들이 전부 날아가 버릴지도 모릅니다. </span>방금 든 예는 제가 이틀 전에 겪었던 현상이었습니다. 저런 실수에 대해서는 생각도 못하고 디버깅하다 결국 과장님께서 찾아주셨는데 어찌나 부끄럽던지 모릅니다. <br />
<br />
위 내용을 간단히 그림으로 표현하면 아래와 같습니다.<br />
<br />
<div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200902/13/64/f0055064_499569160d28b.png" width="500" height="263.045793397" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200902/13/64/f0055064_499569160d28b.png');" /></div><br />
<br />
			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1363522#comments</comments>
		<pubDate>Fri, 13 Feb 2009 12:44:13 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ CObject::Dump ]]> </title>
		<link>http://greenfrog7.egloos.com/1325054</link>
		<guid>http://greenfrog7.egloos.com/1325054</guid>
		<description>
			<![CDATA[ 
  <p>보통 디버깅을 할 때면 적당한 위치에 브레이크 포인트를 찍고 변수의 값들을 눈으로 하나씩 확인해 나가며 문제가 되는 부분을 찾아냅니다. 하지만 쓰레드 또는 컨테이너에 담겨있는 데이터들을 보기 위해서는 TRACE 매크로 함수를 주로 사용할 것입니다.(적어도 저는 설명 드린 방법을 즐겨 사용합니다.) 이번에 ASSERT_VALID 매크로에 대해서&nbsp;공부 할 때&nbsp;참고했던 <a href="http://artwook.tistory.com/entry/ASSERTVALID-AssertValid-Dump"><strong>블로그(나비야 나비야 ~)</strong></a>에 Dump에 대한 내용도 함께 포스팅 되어 있었는데요. 이 함수는 TRACE 매크로 함수와 같은 역할을 하지만, Output창에 출력할 내용을 클래스 내부에서 관리할 수 있는 장점이 있으며 파일로도 출력할 수 있는 기능이 갖추고 있습니다.<br><br>Dump함수는 CObject 클래스에 가상함수로 선정 및 정의 되어있습니다. 이 함수 또한 이전에 포스팅 했던 <a href="http://greenfrog7.egloos.com/1324883"><strong>ASSERT_VALID</strong></a> 매크로 함수와 같이 다형성을 이용하여 상위 클래스의 멤버 변수의 내용도 함께 Output창에 출력할 수 있습니다. Dump 함수의 원형을 다음과 같으며 인자로는 MFC에 전역변수로 선언되어져 있는 afxDump를 전달하면 됩니다. <span style="COLOR: #990000">여기서 한가지 주의할 점이 있는데, Dump함수는 물론 afxDump 전역 변수 또한 디버그 모드 일때만 선언이 된다는 것입니다. 즉, Release 모드에서는 사용할 수 없습니다. 이를 위해서 Dump 함수를 호출하기 전 #ifdef _DEBUG #endif 매크로를 코딩한 후 이 안에서 Dump함수를 호출하도록 합니다.<br></span><br>아래는 위 내용을 간단한 예제로 만들어 본 코드입니다.<br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br></a>// Dump.cpp : Defines the entry point for the console application.<br>//<p></p><p>#include "stdafx.h"</p><p>class CDump : public CObject<br>{<br>public:<br>&nbsp;CDump(int i, int j)<br>&nbsp;{<br>&nbsp;&nbsp;this-&gt;i = i;<br>&nbsp;&nbsp;this-&gt;j = j;<br>&nbsp;}<br>&nbsp;~CDump() {}</p><p>#ifdef _DEBUG<br>&nbsp;virtual void Dump(CDumpContext&amp; dc) const<br>&nbsp;{<br>&nbsp;&nbsp;CObject::Dump(dc);</p><p>&nbsp;&nbsp;dc&lt;&lt;_T("\n================= Start, CDump =================\n\n");<br>&nbsp;&nbsp;dc&lt;&lt;_T("i : ")&lt;&lt;i&lt;&lt;_T("\n");<br>&nbsp;&nbsp;dc&lt;&lt;_T("j : ")&lt;&lt;j&lt;&lt;_T("\n");<br>&nbsp;&nbsp;dc&lt;&lt;_T("\n=================The end, CDump =================\n\n");<br>&nbsp;}<br>#endif</p><p>protected:<br>&nbsp;int i;<br>&nbsp;int j;<br>};</p><p><br>int _tmain(int argc, _TCHAR* argv[])<br>{<br>&nbsp;CDump* dump = new CDump(100, -100);</p><p>#ifdef _DEBUG<br>&nbsp;//<br>&nbsp;//&nbsp;CDumpContext 클래스의 전역 객체 변수 afxDump를 인자로 넘겨 줍니다.<br>&nbsp;//<br>&nbsp;dump-&gt;Dump(afxDump);<br>#endif</p><p>&nbsp;delete dump;</p><p>&nbsp;return 0;<br>}</p><p>&nbsp;</p></div><p><strong>* 실행 결과<br></strong><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200901/22/64/f0055064_497877e9e2925.png" width="500" height="121.301775148" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200901/22/64/f0055064_497877e9e2925.png');" /></div></p><br><strong>* 참고 웹 사이트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://artwook.tistory.com/entry/ASSERTVALID-AssertValid-Dump">http://artwook.tistory.com/entry/ASSERTVALID-AssertValid-Dump</a><br><br><strong>* 예제 프로젝트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds11.egloos.com/pds/200901/22/64/Dump.zip"><strong>Dump.zip</strong></a>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1325054#comments</comments>
		<pubDate>Thu, 22 Jan 2009 14:02:44 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ ASSERT_VALID ]]> </title>
		<link>http://greenfrog7.egloos.com/1324883</link>
		<guid>http://greenfrog7.egloos.com/1324883</guid>
		<description>
			<![CDATA[ 
  <p>ASSERT_VALID 매크로는 객체의 메모리 영역과 멤버변수에 대한 유효성을 검사하는데 사용되는 매크로 함수 입니다. <span style="COLOR: #990000">이 매크로 함수를 이용하기 위해서는 클래스를 정의 할 때 반드시 CRuntimeClass를 선언 및 구현해 주어야하며, CObject를 상속 받아야&nbsp;합니다.</span> 이렇게 해주는 이유는 ASSERT_VALID 매크로 함수는 내부적으로 ::AfxAssertValidObject(pOb, THIS_FILE, __LINE__) 함수를 호출하는데, 이 함수 내부에서 CRuntimeClass의 m_nObjectSize 멤버 변수를 이용해 메모리 주소 공간이 옳바른지 체크하는 루틴이 존재하기 때문이며, CObject의 멤버 가상 함수인 AssertValid를 호출하여 객체의 멤버변수에 대한 유효성 검사를 수행하기 때문입니다.<br><br>그럼 이제부터, 위의 글로 서술한 내용을 코드를 통해 하나씩 알아보도록 하겠습니다.<br><br>우선, ASSERT_VALID 매크로 함수의 원형입니다. 아래에 보시는 봐와 같이 AfxAssertValidObject 함수를 재정의 하고 있음을 알 수 있습니다. 결국 ASSERT_VALID를 호출하면 AfxAsertValidObject 함수가 호출 됩니다.<br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>#define ASSERT_VALID(pOb)&nbsp; (::AfxAssertValidObject(pOb, THIS_FILE, __LINE__))<br></div><br><br>아래는 AfxAssertValidObject 함수의 정의입니다. 우선 보이는 것이 #ifdef _DEBUG 인데, 보시는 봐와 같이 이 함수는 컴파일러가 디버그 모드일 때만 정의 되도록 되어 있습니다. 결국, 릴리즈 모드로 빌드해서 배포할때는 이 함수는 포함되지 않기 때문에 코드의 양이 많이지는&nbsp;부담이 전혀 없습니다.&nbsp;그렇기 때문에 효율적으로 객체를 관리하기 위해서 객체의 메모리와 멤버 변수들이 유효한지 확인하고&nbsp;싶을때 여기저기 많이 사용한다면 디버깅 할 때 굉장히 유리할 뿐만 아니라&nbsp;좀 더 견고하고 완성도 높은 프로그램을 개발하는데 많은 도움이 되리라 생각됩니다.<br><br>아래 함수의 동작은 인자로 들어 온 pOb에 대한 NULL 검사를 수행한 이후, CObject 클래스의 크기 만큼 메모리 블록이 유효한지 검사를 합니다. 다음으로 객체의 메모리 블록 최초 4byte를 검사하여 virtual table이 유효한지 검사하며 CRuntimeClass의 m_nObjectSize 멤버 변수를 이용하여 객체의 모든 메모리 영역이 유효한지 검사합니다. 마지막으로 AssertValid함수를 호출하여 객체의 멤버 변수에 대한 유효성 검사를 수행합니다. <br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>#ifdef _DEBUG<br>void AFXAPI AfxAssertValidObject(const CObject* pOb,&nbsp;LPCSTR lpszFileName, int nLine)<br>{<br>&nbsp;if (pOb == NULL)<br>&nbsp;{<br>&nbsp;&nbsp;TRACE(traceAppMsg, 0, "ASSERT_VALID fails with NULL pointer.\n");<br>&nbsp;&nbsp;if (AfxAssertFailedLine(lpszFileName, nLine))<br>&nbsp;&nbsp;&nbsp;AfxDebugBreak();<br>&nbsp;&nbsp;return;&nbsp;&nbsp;&nbsp;&nbsp; // quick escape<br>&nbsp;}<br>&nbsp;if (!AfxIsValidAddress(pOb, sizeof(CObject)))<br>&nbsp;{<br>&nbsp;&nbsp;TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");<br>&nbsp;&nbsp;if (AfxAssertFailedLine(lpszFileName, nLine))<br>&nbsp;&nbsp;&nbsp;AfxDebugBreak();<br>&nbsp;&nbsp;return;&nbsp;&nbsp;&nbsp;&nbsp; // quick escape<br>&nbsp;}<p></p><p>&nbsp;// check to make sure the VTable pointer is valid<br>&nbsp;ASSERT(sizeof(CObject) == sizeof(void*));<br>&nbsp;if (!AfxIsValidAddress(*(void**)pOb, sizeof(void*), FALSE))<br>&nbsp;{<br>&nbsp;&nbsp;TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal vtable pointer.\n");<br>&nbsp;&nbsp;if (AfxAssertFailedLine(lpszFileName, nLine))<br>&nbsp;&nbsp;&nbsp;AfxDebugBreak();<br>&nbsp;&nbsp;return;&nbsp;&nbsp;&nbsp;&nbsp; // quick escape<br>&nbsp;}</p><p>&nbsp;if (!AfxIsValidAddress(pOb, pOb-&gt;GetRuntimeClass()-&gt;m_nObjectSize, FALSE))<br>&nbsp;{<br>&nbsp;&nbsp;TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");<br>&nbsp;&nbsp;if (AfxAssertFailedLine(lpszFileName, nLine))<br>&nbsp;&nbsp;&nbsp;AfxDebugBreak();<br>&nbsp;&nbsp;return;&nbsp;&nbsp;&nbsp;&nbsp; // quick escape<br>&nbsp;}<br>&nbsp;pOb-&gt;AssertValid();<br>}<br></p></div><br>그럼, 위에서 처럼 AssertValid() 함수만 호출 되면 객체의 멤버변수가 유효한지 자동으로 검사를 해 줄까요? 전혀 그렇지 않습니다. 아래는 CObject 클래스의 AssertValid 함수의 선언과 정의입니다. 보시는 봐와 같이 AssertValid 함수는 virtual로 선언 되어있습니다. 이는 다형성을 이용하여 CObject로 부터 파생되는 클래스가 AssertValid 함수를 재정의 하도록 하여 객체 멤버변수에 대한 유효성 검사를 수행하도록 한 함수입니다. CObject로 부터 파생된 클래스는 자신의 부모 클래스의 AssertValid를 호출 한 후 자신의 멤버변수에 대한 유효성 검사를 수행하면 됩니다. CObject클래스의 AssertValid 함수의 정의를 보면 자기 자신의 객체에 대한 NULL 검사를 수행하고 있는 것을 확인하실 수 있습니다.<br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>#if defined(_DEBUG) || defined(_AFXDLL)<br>&nbsp;// Diagnostic Support<br>&nbsp;virtual void AssertValid() const;<br>&nbsp;virtual void Dump(CDumpContext&amp; dc) const;<br>#endif<br><br>void CObject::AssertValid() const<br>{<br>&nbsp;ASSERT(this != NULL);<br>}<br></div><br>위 설명을 기초로 하여 간단히 ASSERT_VALID 매크로를 사용하는 예제 코드를 만들어 보았습니다.<br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>// ASSERT_VALID.cpp : Defines the entry point for the console application.<br>//</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">#include "stdafx.h"</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">class Base : public CObject<br>{<br>&nbsp;//<br>&nbsp;//&nbsp;CRuntimeClass를 선언합니다.<br>&nbsp;//<br>&nbsp;DECLARE_DYNAMIC(Base)</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;int i;<br>&nbsp;<br>public:<br>&nbsp;Base(int i) { this-&gt;i = i; }<br>&nbsp;virtual ~Base() {}</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">#ifdef _DEBUG<br>&nbsp;virtual void AssertValid() const<br>&nbsp;{<br>&nbsp;&nbsp;//<br>&nbsp;&nbsp;//&nbsp;자신의 상위 클래스의 AssertValid함수를 호출하여 <br>&nbsp;&nbsp;//&nbsp;상위 클래스의 멤버 변수에 대한 유효성 검사를 수행합니다.<br>&nbsp;&nbsp;//<br>&nbsp;&nbsp;CObject::AssertValid();</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;&nbsp;ASSERT(i &gt; 0);<br>&nbsp;}<br>#endif<br>};<br>//<br>//&nbsp;CRuntimeClass를 정의합니다.<br>//<br>IMPLEMENT_DYNAMIC(Base, CObject)</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">class Derived : public Base<br>{<br>&nbsp;//<br>&nbsp;//&nbsp;CRuntimeClass를 선언합니다.<br>&nbsp;//<br>&nbsp;DECLARE_DYNAMIC(Derived)</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;int j;</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">public:<br>&nbsp;Derived(int i, int j) : Base(i) { this-&gt;j = j; }<br>&nbsp;virtual ~Derived() {};</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">#ifdef _DEBUG<br>&nbsp;virtual void AssertValid() const<br>&nbsp;{<br>&nbsp;&nbsp;//<br>&nbsp;&nbsp;//&nbsp;자신의 상위 클래스의 AssertValid함수를 호출하여 <br>&nbsp;&nbsp;//&nbsp;상위 클래스의 멤버 변수에 대한 유효성 검사를 수행합니다.<br>&nbsp;&nbsp;//<br>&nbsp;&nbsp;Base::AssertValid();</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;&nbsp;ASSERT(j &gt; 0);<br>&nbsp;}<br>#endif<br>};<br>//<br>//&nbsp;CRuntimeClass를 정의합니다.<br>//<br>IMPLEMENT_DYNAMIC(Derived, Base)</div><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>int _tmain(int argc, _TCHAR* argv[])<br>{<br>&nbsp;Base* p = new Derived(-1, -1);<br>&nbsp;ASSERT_VALID(p);</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;delete p;</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;return 0;<br>}</div><div style="BACKGROUND-COLOR: rgb(192,192,192)">&nbsp;</div><br><strong>* 실행 결과</strong><br><br>위 예제 코드를 보시면&nbsp;각 클래스의 멤버 변수는 0보다 큰 값을 가져야 함을 알 수 있습니다. 하지만 생성자에서는 -1을 각각 멤버 변수에 할당해 두었습니다. 결국 프로그램을 실행하면 아래와 같이 ASSERT&nbsp;창이 뜨며&nbsp;문제가 발생한 파일 명과&nbsp;라인 넘버를 출력해 줍니다. 물론 Debug 모드에서 실행을 하셔야합니다 ~ ^^<br>&nbsp;&nbsp;&nbsp;&nbsp;<div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds14.egloos.com/pds/200901/22/64/f0055064_4978671d2d88d.png" width="500" height="214.42687747" onclick="Control.Modal.openDialog(this, event, 'http://pds14.egloos.com/pds/200901/22/64/f0055064_4978671d2d88d.png');" /></div><p></p><p><br>* <strong>참고 서적 및 웹 사이트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.yes24.com/Goods/FTGoodsView.aspx?goodsNo=2502879"><b>윈도우즈 MFC 프로그래밍</b> : 원리에서 활용까지</a>&nbsp;(정보문화사)<br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://artwook.tistory.com/entry/ASSERTVALID-AssertValid-Dump">http://artwook.tistory.com/entry/ASSERTVALID-AssertValid-Dump</a><br><br><strong>* 예제 프로젝트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds14.egloos.com/pds/200901/22/64/ASSERT_VALID.zip"><strong>ASSERT_VALID.zip</strong></a></p>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1324883#comments</comments>
		<pubDate>Thu, 22 Jan 2009 12:42:10 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ CRuntimeClass - 객체 자료형 검사 ]]> </title>
		<link>http://greenfrog7.egloos.com/1316331</link>
		<guid>http://greenfrog7.egloos.com/1316331</guid>
		<description>
			<![CDATA[ 
  CRuntimeClass에는&nbsp;C++의&nbsp;RTTI에서 dynamic_cast 연산자를 통해 Rum-time에 객체 자료형 검사를&nbsp;가능하게 하는 기능을 갖추고 있습니다. CObject 클래스의 IsKindOf 멤버 함수를 사용하면 되는데 이에 대해서 알아보도록 하겠습니다.<br><br><div style="BACKGROUND-COLOR: rgb(249,235,162)"><div class="title"><strong><span style="FONT-SIZE: 130%"><br>CObject::IsKindOf<br><br></span></strong><!----></div><!--      Content type: Devdiv1. Transform: orcas2mtps.xslt.    --><div id="mainSection"><div id="mainBody"><div class="introduction"><p>Tests this object's relationship to a given class.</p></div><div class="section" id="syntaxSection"><div class="" id="ctl00_rs1_mainContentContainer_ctl01_other"><div class="CodeSnippetTitleBar"><div class="CodeDisplayLanguage"></div></div><div dir="ltr"><pre class="libCScode" id="ctl00_rs1_mainContentContainer_ctl01other" style="WORD-BREAK: break-all; WORD-WRAP: break-word" space="preserve">BOOL IsKindOf(   const CRuntimeClass* pClass ) const;</pre></div></div></div><div class="MTPS_CollapsibleRegion" id="ctl00_rs1_mainContentContainer_cpe10286374"><div class="CollapseRegionLink" id="ctl00_rs1_mainContentContainer_cpe10286374_h"><img class="LibC_o" id="ctl00_rs1_mainContentContainer_cpe10286374_i" style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; VERTICAL-ALIGN: middle; BORDER-RIGHT-WIDTH: 0px" src="http://i.msdn.microsoft.com/Global/Images/clear.gif"><strong>&nbsp;Parameters</strong> </div><div class="MTPS_CollapsibleSection" id="ctl00_rs1_mainContentContainer_cpe10286374_c" style="DISPLAY: block; OVERFLOW: visible; WIDTH: auto; HEIGHT: auto"><div class="MTPS_CollapsibleSection" id="" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none"><a name="parametersToggle"><!----></a><dl class="authored"><dt><font size="+0"><em>pClass</em></font> <dd><p>A pointer to a <a id="ctl00_rs1_mainContentContainer_ctl05" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286374_c|ctl00_rs1_mainContentContainer_ctl05',this);" href="http://msdn.microsoft.com/ko-kr/library/cyfc5et8.aspx"><span style="COLOR: #0033cc">CRuntimeClass</span></a> structure associated with your <b>CObject</b>-derived class.</p></dd></dl></div></div></div><div class="MTPS_CollapsibleRegion" id="ctl00_rs1_mainContentContainer_cpe10286375"><div class="CollapseRegionLink" id="ctl00_rs1_mainContentContainer_cpe10286375_h"><img class="LibC_o" id="ctl00_rs1_mainContentContainer_cpe10286375_i" style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; VERTICAL-ALIGN: middle; BORDER-RIGHT-WIDTH: 0px" src="http://i.msdn.microsoft.com/Global/Images/clear.gif"><strong>&nbsp;Return Value</strong> </div><div class="MTPS_CollapsibleSection" id="ctl00_rs1_mainContentContainer_cpe10286375_c" style="DISPLAY: block; OVERFLOW: visible; WIDTH: auto; HEIGHT: auto"><div class="MTPS_CollapsibleSection" id="" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none"><a name="returnValueToggle"><!----></a><p>Nonzero if the object corresponds to the class; otherwise 0.</p></div></div></div><div class="MTPS_CollapsibleRegion" id="ctl00_rs1_mainContentContainer_cpe10286376"><div class="CollapseRegionLink" id="ctl00_rs1_mainContentContainer_cpe10286376_h"><img class="LibC_o" id="ctl00_rs1_mainContentContainer_cpe10286376_i" style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; VERTICAL-ALIGN: middle; BORDER-RIGHT-WIDTH: 0px" src="http://i.msdn.microsoft.com/Global/Images/clear.gif"><strong>&nbsp;Remarks</strong> </div><div class="MTPS_CollapsibleSection" id="ctl00_rs1_mainContentContainer_cpe10286376_c" style="DISPLAY: block; OVERFLOW: visible; WIDTH: auto; HEIGHT: auto" olddisplay="null"><div class="MTPS_CollapsibleSection" id="" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none"><a name="languageReferenceRemarksToggle"><!----></a><p>This function tests <font size="+0"><em>pClass</em></font> to see if (1) it is an object of the specified class or (2) it is an object of a class derived from the specified class. This function works only for classes declared with the <a id="ctl00_rs1_mainContentContainer_ctl13" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl13',this);" href="http://msdn.microsoft.com/ko-kr/library/ywz9k63y.aspx"><span style="COLOR: #0033cc">DECLARE_DYNAMIC</span></a>, <a id="ctl00_rs1_mainContentContainer_ctl14" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl14',this);" href="http://msdn.microsoft.com/ko-kr/library/56302tyt.aspx"><span style="COLOR: #0033cc">DECLARE_DYNCREATE</span></a>, or <a id="ctl00_rs1_mainContentContainer_ctl15" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl15',this);" href="http://msdn.microsoft.com/ko-kr/library/5593z07w.aspx"><span style="COLOR: #0033cc">DECLARE_SERIAL</span></a> macro.</p><p><span style="COLOR: #dcdcdc; BACKGROUND-COLOR: #cc0000">Do not use this function extensively because it defeats the C++ polymorphism feature. Use virtual functions instead.<br></span></p></div></div></div></div></div></div><div></div><div></div><div></div><div></div><br><div style="BACKGROUND-COLOR: #ccffff"><br>우선, MSDN에서 이 함수를 설명하는 부분을 살펴보면 인자로 들어온 pClass(CRuntimeClass의 객체)와 현재 클래스와의 관계를 테스트하는데 사용한다고 합니다. 이때 서로 같으면 0이 아닌값 (TRUE)를 반환하며 같지 않으면 0을 반환합니다. 이 함수의 검사 대상인 pClass는 이 함수를 호출한 클래스의 CRuntimeClass 객체 일 수도 있고 또는 이 함수를 호출한 클래스를 상속받은 하위 클래스의 CRuntimeClass 객체일 수도 있다는 것입니다. ( 이 두 경우 모두 이 함수의 결과는 참을 반환 합니다. ) 이 함수는 오직 <a id="ctl00_rs1_mainContentContainer_ctl13" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl13',this);" href="http://msdn.microsoft.com/ko-kr/library/ywz9k63y.aspx"><span style="COLOR: #0033cc">DECLARE_DYNAMIC</span></a>, <a id="ctl00_rs1_mainContentContainer_ctl14" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl14',this);" href="http://msdn.microsoft.com/ko-kr/library/56302tyt.aspx"><span style="COLOR: #0033cc">DECLARE_DYNCREATE</span></a>, or <a id="ctl00_rs1_mainContentContainer_ctl15" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe10286376_c|ctl00_rs1_mainContentContainer_ctl15',this);" href="http://msdn.microsoft.com/ko-kr/library/5593z07w.aspx"><span style="COLOR: #0033cc">DECLARE_SERIAL</span></a> macro를&nbsp;선언한 클래스에서만 사용이 가능합니다.<br>이 함수는 C++의 다형성 특징을 약화 시키기 때문에 광범위하게 사용되지는 않습니다. 대신 가상함수를 사용합니다. (이 부분에서 이 함수가 다형성 특징을 약화시키고 그 때문에 가상함수를 대신 사용하라는데 어떤 뜻인지 잘 모르겠네요 ㅡㅡ?)<br><br>※ 어설픈 영어 실력으로 인해 오역이 있을 수 있습니다.<br></div><br>위 설명을 예제 코드로 만들어서 테스트 해 보면 아래와 같습니다. 테스트 방법은 일단 Derived 클래스의 객체를 생성 한 후 첫번째로 Derived 클래스의 상위 클래스인 Base 클래스의 CRuntimeClass 객체를 인자로 넘겨 봅니다. 두번째는 Derived 클래스 자신의 CRuntimeClass객체를 인자로 넘겨보도 세번째로는 전혀 다른 클래스의 CRuntimeClass객체를 넘겨 봅니다. 위 MSDN의 설명데로 예제를 잘 만들었다면 결과는 아래 주석(// 이 내용이 출력 됩니다.)을 달아 놓은 부분의 문장이 콘솔에 출력되어야겠죠?<br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>// IsKindOf.cpp : Defines the entry point for the console application.<br>//<p></p><p>#include "stdafx.h"</p><p>class Base : public CObject<br>{<br>&nbsp;DECLARE_DYNAMIC(Base)</p><p>public:<br>};<br>IMPLEMENT_DYNAMIC(Base, CObject)</p><p>class Derived : public Base<br>{<br>&nbsp;DECLARE_DYNAMIC(Derived)<br>};<br>IMPLEMENT_DYNAMIC(Derived, Base)</p><p>class Other : public CObject<br>{<br>&nbsp;DECLARE_DYNAMIC(Other)</p><p>public:<br>};<br>IMPLEMENT_DYNAMIC(Other, CObject)</p><p>int _tmain(int argc, _TCHAR* argv[])<br>{<br>&nbsp;Base* p = new Derived;<br>&nbsp;<br>&nbsp;if(p-&gt;IsKindOf(RUNTIME_CLASS(Base)))<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Base 클래스의 하위 클래스 또는 Base 클래스 입니다.\n"));&nbsp;&nbsp;&nbsp;// 이 내용이 출력 됩니다.<br>&nbsp;else<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Base 클래스의 하위 클래스 또는 Base 클래스가 아닙니다.\n"));</p><p>&nbsp;if(p-&gt;IsKindOf(RUNTIME_CLASS(Derived)))<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Derived 클래스의 하위 클래스 또는 Derived 클래스 입니다.\n"));&nbsp;&nbsp;// 이 내용이 출력 됩니다.<br>&nbsp;else<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Derived 클래스의 하위 클래스 또는 Derived 클래스가 아닙니다.\n"));</p><p>&nbsp;if(p-&gt;IsKindOf(RUNTIME_CLASS(Other)))<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Other 클래스의 하위 클래스 또는 Other 클래스 입니다.\n"));<br>&nbsp;else<br>&nbsp;&nbsp;_tprintf(_T("p객체는 Other 클래스의 하위 클래스 또는 Other 클래스가 아닙니다.\n"));&nbsp;&nbsp;// 이 내용이 출력 됩니다.</p><p>&nbsp;delete p;</p><p>&nbsp;return 0;<br>}</p></div><br><strong>* 실행 결과</strong><br><br>실행 결과를 보면 의도한데로 잘 나오네요. 위 내용을 정리해보면 IsKindOf 함수는 Run-time에 객체의 자료형을 검사해 주는데 IsKindOf함수는 호출한 클래스 자신의 자료형 뿐만 아니라 상위 클래스에 대해서도 참을 반환 하는 것을 확인 할 수 있습니다.<br><p></p><div></div><p></p><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200901/18/64/f0055064_497310e806624.png" width="500" height="52.427184466" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200901/18/64/f0055064_497310e806624.png');" /></div><p></p><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div><strong>* 참고 문헌</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.yes24.com/Goods/FTGoodsView.aspx?goodsNo=2502879"><b>윈도우즈 MFC 프로그래밍</b> : 원리에서 활용까지</a>&nbsp;(정보문화사)<br><br><strong>* 예제 프로젝트</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds10.egloos.com/pds/200901/22/64/IsKindOf.zip"><strong>IsKindOf.zip</strong></a><br>&nbsp;&nbsp;&nbsp;&nbsp;</div>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1316331#comments</comments>
		<pubDate>Sun, 18 Jan 2009 11:34:27 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 차일드 윈도우 사용하기 .. ]]> </title>
		<link>http://greenfrog7.egloos.com/1288794</link>
		<guid>http://greenfrog7.egloos.com/1288794</guid>
		<description>
			<![CDATA[ 
  <p>에디트 컨트롤과 슬라이더 컨트롤을 얹은 차일드 윈도우를&nbsp;두개&nbsp;만듭니다. 똑같이 에디트 컨트롤과 슬라이더 컨트롤 그리고 차일드 윈도우를 선택하기 위한 라디오 버튼을 두개 IParentCtrlManager*은&nbsp;부모 윈도우를 만듭니다. 각각 윈도우들은 CDialog를 상속 받도록 합니다. 그리고 차일드 윈도우를 부모 윈도우에 붙이고 라디오 버튼의 선택에 따라 각 차일드 윈도우가 보이고 감춰지도록 하며 부모 윈도우의 슬라이더가 움직이면 차일드 윈도우의 슬라이더도 같이 동작하도록 합니다. 대충 .. 이런 시나리오의 간단한 프로그램을 만들어 보도록하겠습니다.<br><br>위 설명을 그림으로 나타내면 아래와 같습니다.<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200901/04/64/f0055064_49605661cd759.png" width="500" height="279.577464789" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200901/04/64/f0055064_49605661cd759.png');" /></div></p><p><br>일단 위의 내용을 코딩 하기 전 클래스는 아래와 같이 설계해 보았습니다.<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds10.egloos.com/pds/200901/04/64/f0055064_4960568dbfee2.png" width="500" height="204.716981132" onclick="Control.Modal.openDialog(this, event, 'http://pds10.egloos.com/pds/200901/04/64/f0055064_4960568dbfee2.png');" /></div>소스 코드가 너무 길어서 각 소스에 주석을 달아 놓았습니다. 아래 예제 프로젝트를 제공하고 있으니 다운로드 받아서 분석해 보세요 ~~<br><br><strong>* 실행 결과<br></strong><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds13.egloos.com/pds/200901/04/64/f0055064_49605bb79bb45.png" width="368" height="261" onclick="Control.Modal.openDialog(this, event, 'http://pds13.egloos.com/pds/200901/04/64/f0055064_49605bb79bb45.png');" /></div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds11.egloos.com/pds/200901/04/64/f0055064_49605bbc1ad36.png" width="368" height="261" onclick="Control.Modal.openDialog(this, event, 'http://pds11.egloos.com/pds/200901/04/64/f0055064_49605bbc1ad36.png');" /></div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds12.egloos.com/pds/200901/04/64/f0055064_49605bbf396ea.png" width="368" height="261" onclick="Control.Modal.openDialog(this, event, 'http://pds12.egloos.com/pds/200901/04/64/f0055064_49605bbf396ea.png');" /></div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds13.egloos.com/pds/200901/04/64/f0055064_49605bc0da8a3.png" width="368" height="261" onclick="Control.Modal.openDialog(this, event, 'http://pds13.egloos.com/pds/200901/04/64/f0055064_49605bc0da8a3.png');" /></div><br>* 예제 프로젝트<br><br><a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds13.egloos.com/pds/200901/04/64/SwitchWindow.zip"><strong>SwitchWindow.zip</strong></a><br></p>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1288794#comments</comments>
		<pubDate>Sun, 04 Jan 2009 06:49:00 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
	<item>
		<title><![CDATA[ WaitForMultipleObjects를 이용하여 특정 커널 오브젝트의 Signaled 상태 대기하기 ]]> </title>
		<link>http://greenfrog7.egloos.com/1288479</link>
		<guid>http://greenfrog7.egloos.com/1288479</guid>
		<description>
			<![CDATA[ 
  <p>WaitForMultipleObjects 함수의 경우 커널 오브젝트 핸들 배열에 대한 모든 핸들이&nbsp;Signaled 상태가 될때&nbsp;까지 대기 할 수도 있지만 특정 핸들이 Signaled 상태가 될 때 까지만 대기 할 수도 있습니다.<br><br>아래는 MSDN의 <strong><a href="http://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx"><strong>WaitForMultipleObjects</strong></a></strong> 함수에 대한 내용 중 세번째 인자인 <strong>bWaitAll</strong>에 대한 설명입니다.<br><br><div style="BACKGROUND-COLOR: rgb(249,235,162)"><br><p></p><dt><strong>bWaitAll [in]</strong> <br><br>If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled. If FALSE, the function returns when the state of any one of the objects is set to signaled. In the latter case, the return value indicates the object whose state caused the function to return.<br><br></dt></div><br><div style="BACKGROUND-COLOR: #ccffff"><br>이 인자를 TRUE로 했을 경우 이 함수는&nbsp;lpHandles 인자로 넘어 온 배열의 모든&nbsp;커널 오브젝트의 상태가 sigaled가 되었을 때 리턴한다고 합니다. 만약 FALSE로 했을 경우 이 함수는 특정 커널 오브젝트가 signaled 상태가 되었을 때&nbsp;리턴 한다고 합니다.&nbsp;그리고 이 리턴값은 이 함수를 리턴하게 한&nbsp;커널 오브젝트를 가리킨다고 합니다.&nbsp;- 즉, 리턴값은 lpHandles 인자로 넘어 온 배열에서 signaled&nbsp;상태가 된 커널 오브젝트의 인덱스 입니다. -<br><br>※ 어설픈 영어 실력으로 인해 오역이 있을 수 있습니다.<br><br></div><br>위 내용에 따라&nbsp;예제 코드를 만들어 보았습니다. 두 개의 쓰레드를 실행 시키는데 이때 쓰레드의 인자값으로 각각의 쓰레드가 sleep할 시간을 전달하였습니다. 그리고 WaitMultipleObjects 함수에서 먼저 종료 된 쓰레드에 대해서 문자열을 출력하도록 하였습니다.<br><br><div style="BACKGROUND-COLOR: rgb(192,192,192)"><br>UINT WINAPI ThreadProc(LPVOID lpParam)<br>{<br>&nbsp;DWORD* waitTime = (DWORD*) lpParam;<br>&nbsp;<br>&nbsp;Sleep(*waitTime);<p></p><p>&nbsp;return 0;<br>}</p><p>int _tmain(int argc, _TCHAR* argv[])<br>{<br>&nbsp;enum {THREAD_1, THREAD_2};<br>&nbsp;HANDLE hArrThread[2];<br>&nbsp;<br>&nbsp;DWORD waitTime_1 = 3000;<br>&nbsp;DWORD waitTime_2 = 1000;</p><p>&nbsp;hArrThread[THREAD_1] = (HANDLE) _beginthreadex(NULL, 0, ThreadProc, (LPVOID) &amp;waitTime_1, 0, NULL);<br>&nbsp;hArrThread[THREAD_2] = (HANDLE) _beginthreadex(NULL, 0, ThreadProc, (LPVOID) &amp;waitTime_2, 0, NULL);</p><p>&nbsp;assert(NULL != hArrThread[THREAD_1] &amp;&amp; NULL != hArrThread[THREAD_2]); </p><p>&nbsp;//<br>&nbsp;//&nbsp;WaiftForMultiPleObjects의 두번째 인자를 FALSE로 셋팅하면 <br>&nbsp;//&nbsp;먼저 signal 상태로 전이 된 쓰레드의 핸들 배열 Index를 반환 한다.<br>&nbsp;//<br>&nbsp;switch(WaitForMultipleObjects(2, hArrThread, FALSE, INFINITE))<br>&nbsp;{<br>&nbsp;case THREAD_1:<br>&nbsp;&nbsp;_tprintf(_T("The ended the THREAD_1.\n"));<br>&nbsp;&nbsp;break;</p><p>&nbsp;case THREAD_2:<br>&nbsp;&nbsp;_tprintf(_T("The ended the THREAD_2.\n"));<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;break;</p><p>&nbsp;case WAIT_TIMEOUT:<br>&nbsp;case WAIT_ABANDONED:<br>&nbsp;&nbsp;return -1;<br>&nbsp;}</p><p>&nbsp;CloseHandle(hArrThread[THREAD_1]);<br>&nbsp;CloseHandle(hArrThread[THREAD_2]);</p><p>&nbsp;return 0;<br>}<br><br></p></div><br><strong>* 실행 결과</strong><br><br>THREAD_1은 3초를 대기 하고 THREAD_2는 1초를 대기 하기 때문에 THREAD_2에 대한 문자열이 출력 됩니다.<br><br><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds13.egloos.com/pds/200901/04/64/f0055064_496015c1a773c.png" width="500" height="142.973856209" onclick="Control.Modal.openDialog(this, event, 'http://pds13.egloos.com/pds/200901/04/64/f0055064_496015c1a773c.png');" /></div><strong>* 예제 프로젝트</strong><br><br><a style="PADDING-RIGHT: 0px; PADDING-LEFT: 15px; BACKGROUND: url(http://md.egloos.com/img/eg/icon_file.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none" href="http://pds12.egloos.com/pds/200901/04/64/WaitForMultiObjects.zip"><strong>WaitForMultiObjects.zip</strong></a><br>&nbsp;<p></p>			 ]]> 
		</description>
		<category>C++ / WIN32 / MFC</category>

		<comments>http://greenfrog7.egloos.com/1288479#comments</comments>
		<pubDate>Sun, 04 Jan 2009 01:55:37 GMT</pubDate>
		<dc:creator>greenfrog</dc:creator>
	</item>
</channel>
</rss>
