[MFC :: OpenGL] IPC 적용 (옮김)

심플디 2014.04.25 13:14 조회 수 : 1560


ProjectMFCReport.zip

ProjectOpenGL.zip



이 테크닉의 오류는 흡사 s1에서 Nurbs curve가 샘플용임을 발견했을 때의 짜증 수치의 1/4정도를 유발 시킬 수 있다.



일단 Visual C++ 2008 MFC 시스템 프로그래밍, 이창현, 혜지원 서적에서는 Chapter 13에서 ipc 방법 중 하나인 프로세스 지목형을 소개하고 있다.
이 서적에서는 다른 ipc 방법도 소개하고 있지만, 필자는 이 방식이 가장 마음에 들었다. 이 서적은 Dialog기반의 ipc 방법만 기술하였다.
필자는 Dialog 기반의 소스코드를 Doc-View 기반의 소스코드에 옮겨도 제대로 동작하리라 믿었다.

그런데 처음에는 프로세스의 '지목'이 제대로 이루어지지 않았다.
ProjectOpenGL의 Dialog에서 데이터를 보냄에 있어서, 서버(sever)가 되는 ProjectMFCReport의 이름을 찾지 못하는 것이였다.

이에 따라 Pipe형식의 소스코드도 제작할 필요가 있었다.
그런데 이번에는 더 가관이였다. Pipe 형식의 데이터가 한번 수신 됨에 따라 파이프가 종료되는 현상을 볼 수 있었기 때문이다.

하지만.
가장 큰 문제는, 어떤 소스 코드를 사용하더라도 제대로 동작하는지의 여부를 한번도 알 수 없었다는 것이다.
에러 메시지가 뜨지 않은 것을 보아, 메시지가 제대로 송수신 되었음을 짐작 할 뿐, 
화면 업데이트 처리를 2중 3중으로 한 소스코드가 무색할 만큼, 화면의 변화가 전혀 보이지 않았다.

그래서 애매하게 동작하는 Pipe 형식의 소스코드를 완전 삭제하고 프로세스 지목형 소스코드만 활용하기로 했다.

<그림 1 ::  Project MFC Report>


<그림 1>은 ProjectMFCReport 의 WM_COPYDATA 메시지 메서드의 적용 사례를 보여주고 있다.

report 구조체는 view 클래스의 헤더파일에서 public 상태로 선언되어 있다.

이에 따라 _REPORT.h를 헤더파일(.h) 및 구현파일(.cpp)의 선언부(#include)에 섞어 주는 과정이 있어야겠다.

구조체 내부는 CString이 아닌, TCHAR 의 배열만 들어있으므로 서로의 데이터 교환에 있어서, 그냥 wsprintf함수 사용방식을 택했다.


아래 코드는 ProjectMFCReport의 View 클래스에 있는 메서드 OnDraw의 수정사항을 보여주고 있다.


// CProjectMFCReportView 메시지처리기

void CProjectMFCReportView::OnDraw(CDC* pDC)

{

        CProjectMFCReportDoc* pDoc = GetDocument();

        ASSERT_VALID(pDoc);

        if (!pDoc)

               return;

              

        int y_Position=0;

              

        if(pDC->IsPrinting())

        {

               pDC->SetMapMode(MM_ISOTROPIC);

               pDC->SetWindowExt(100, 100);

               pDC->SetViewportExt(800, 800);

        }

              

        // Area

               CRect reArea(0, 0, 594, 841);

               SetBkMode(pDC->m_hDC, TRANSPARENT);

              

        // Font List

               CFont ftReport, ftMyNumber, tfTitle, tfInfo, *OldFont;

               ftReport.CreateFont(60, 0, 0, 0,FW_HEAVY,FALSE, FALSE, FALSE,

                                                                     ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,

                                                                    DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,

                                                                    _T("Times New Roman"));

               ftMyNumber.CreateFont(13, 0, 0, 0,FW_HEAVY,FALSE, FALSE, FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,

                                                                     CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,

                                                                    _T("Lucida Grande"));

              tfTitle.CreateFont(15, 0, 0, 0,FW_HEAVY,FALSE, FALSE, FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,

                                                                     CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,

                                                                    _T("Lucida Grande"));

              tfInfo.CreateFont(13, 0, 0, 0,FW_NORMAL,FALSE, FALSE, FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,

                                                                     CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,

                                                                    _T("Lucida Grande"));

              

        // Rectangle

               int off = 20;

               // pDC->Rectangle(reArea.left, reArea.top, reArea.right, reArea.bottom);

               pDC->Rectangle(reArea.left+off, reArea.top+off, reArea.right-off, reArea.bottom-off);

              

        // REPORT

               y_Position = 25;

 

               TCHAR tcReport[10];

               wsprintf(tcReport, _T("REPORT"));

              

               OldFont = pDC->SelectObject(&ftReport);

               SetTextAlign(pDC->m_hDC, TA_CENTER);

               pDC->TextOutW(reArea.right/2, reArea.top+y_Position, tcReport, lstrlen(tcReport));

               pDC->SelectObject(OldFont);

               SetTextAlign(pDC->m_hDC, TA_LEFT);

              

        // Line 1

               y_Position = 90;

               pDC->MoveTo(reArea.left+55,   reArea.top+y_Position  );

               pDC->LineTo(reArea.right-55,  reArea.top+y_Position);

              

        // Div

               y_Position = 100;

                       TCHAR tcMyNumber[20], tcDate[20], tcMyText[60], tcMyName[200];

                       CTime Today = CTime::GetCurrentTime();

                       OldFont = pDC->SelectObject(&ftMyNumber);

                       SetTextAlign(pDC->m_hDC, TA_CENTER);

                       SetTextColor(pDC->m_hDC, RGB(100, 100, 100));

                       wsprintf(tcMyNumber, _T("2005 02219"));

                       wsprintf(tcDate, _T("%d.%d.%d, %d:%d"), Today.GetDay(), Today.GetMonth(), Today.GetYear(), Today.GetHour(), Today.GetMinute());

                       wsprintf(tcMyText, _T("%s // %s"), tcMyNumber, tcDate);

                       pDC->TextOutW(reArea.right/2, reArea.top+y_Position, tcMyText, lstrlen(tcMyText));

               y_Position+=20;

                       wsprintf(tcMyName, _T("D.S Shin"));

                       pDC->TextOutW(reArea.right/2, reArea.top+y_Position, tcMyName, lstrlen(tcMyName));

                       pDC->SelectObject(OldFont);

                       SetTextAlign(pDC->m_hDC, TA_LEFT);

              

        // Line 2

               y_Position+=20;

                       pDC->MoveTo(reArea.left+55,                  reArea.top+y_Position);

                       pDC->LineTo(reArea.right-55,          reArea.top+y_Position);

              

        // FILE title

               y_Position+=20;

                       TCHAR tcFileTitle[20];

                       OldFont = pDC->SelectObject(&tfTitle);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                       wsprintf(tcFileTitle, _T("FILE") );

                       pDC->TextOutW(reArea.left + 55, 160, tcFileTitle, lstrlen(tcFileTitle));

                       pDC->SelectObject(OldFont);

              

        // FILE info

               y_Position+=25;

                       TCHAR tcPath[500], tcName[200], tcExtention[200];

                       OldFont = pDC->SelectObject(&tfInfo);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                      

                       wsprintf(tcPath, _T("Path : %s"), report.tcPath);

                       wsprintf(tcName, _T("Name : %s"), report.tcName);

                       wsprintf(tcExtention, _T("Extention : %s"), report.tcExtention);

              

                       pDC->TextOutW(reArea.left + 80, y_Position, tcPath, lstrlen(tcPath));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcName, lstrlen(tcName));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcExtention, lstrlen(tcExtention));

                       pDC->SelectObject(OldFont);

              

        // DATA title

               y_Position+=40;

               TCHAR tcDataTitle[20];

               OldFont = pDC->SelectObject(&tfTitle);

               SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

               wsprintf(tcDataTitle, _T("DATA") );

               pDC->TextOutW(reArea.left + 55, y_Position, tcDataTitle, lstrlen(tcDataTitle));

               pDC->SelectObject(OldFont);

              

        // DATA info

               y_Position+=25;

                       TCHAR tcPoint[200], tcUV[200],

                              tcMax[200], tcMin[200],

                              tcSize[200],   tcMesh[200], tcFlag[200];

 

                       OldFont = pDC->SelectObject(&tfInfo);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

 

                       wsprintf(tcPoint,      _T("Point : %s"),      report.tcPoint );

                       wsprintf(tcUV,         _T("U, V : %s"),       report.tcUV);

                       wsprintf(tcMax,        _T("Max : %s"),        report.tcMax);

                       wsprintf(tcMin,        _T("Min : %s"),        report.tcMin);

                       wsprintf(tcSize,       _T("Size : %s"),       report.tcSize);

                       wsprintf(tcMesh,       _T("Mesh : %s"),       report.tcMesh);

                       wsprintf(tcFlag,       _T("Flag : %s"),       report.tcFlag);

 

                       pDC->TextOutW(reArea.left + 80, y_Position, tcPoint, lstrlen(tcPoint));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcUV, lstrlen(tcUV));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcMax, lstrlen(tcMax));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcMin, lstrlen(tcMin));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcSize, lstrlen(tcSize));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcMesh, lstrlen(tcMesh));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcFlag, lstrlen(tcFlag));

               pDC->SelectObject(OldFont);

              

        // REVISION title

               y_Position+=40;

                       TCHAR tcRevisionTitle[20];

                       OldFont = pDC->SelectObject(&tfTitle);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                       wsprintf(tcRevisionTitle, _T("REVISION") );

                       pDC->TextOutW(reArea.left + 55, y_Position, tcRevisionTitle, lstrlen(tcRevisionTitle));

                       pDC->SelectObject(OldFont);

       

        // REVISION info

               y_Position+=25;

                       TCHAR tcTranslate[200], tcRotate[200];

                       OldFont = pDC->SelectObject(&tfInfo);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                      

                       wsprintf(tcTranslate,  _T("Translate : %s"),  report.tcTranslate );

                       wsprintf(tcRotate,     _T("Rotate : %s"),     report.tcRotate);

                      

 

                       pDC->TextOutW(reArea.left + 80, y_Position, tcTranslate, lstrlen(tcTranslate));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcRotate, lstrlen(tcRotate));

                       pDC->SelectObject(OldFont);

              

        // Set-Value title

               y_Position+=40;

                       TCHAR tcSetValue[20];

                       TCHAR tcColor[20];

                       OldFont = pDC->SelectObject(&tfTitle);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                       wsprintf(tcSetValue, _T("Set-Value") );

                       wsprintf(tcColor, _T("Color"));

                       pDC->TextOutW(reArea.left + 55, y_Position, tcSetValue, lstrlen(tcSetValue));

                       pDC->TextOutW(reArea.right/2 + 25,    y_Position, tcColor, lstrlen(tcColor));

                       pDC->SelectObject(OldFont);

                      

        // Set-Value info

               y_Position+=25;

                       TCHAR   tcMeshType[200], tcMeshVector[200], tcClipping[200], tcPerspective[200], tcLightPosition[200],

                                      tcPointColor[200], tcMeshColor[200], tcFaceColor[200], tcLightColor[200], tcBackgroundColor[200];

                       OldFont = pDC->SelectObject(&tfInfo);

                       SetTextColor(pDC->m_hDC, RGB(0, 0, 0));

                      

                       wsprintf(tcMeshType,          _T("Mesh type : %s"),                 report.tcMeshType );

                       wsprintf(tcMeshVector,        _T("Mesh vector : %s"),               report.tcMeshVector);

                       wsprintf(tcClipping,          _T("Clipping : %s"),                  report.tcClipping);

                       wsprintf(tcPerspective,       _T("Perspective : %s"),               report.tcPerspective);

                       wsprintf(tcLightPosition,     _T("Light position : %s"),            report.tcLightPosition);

                       wsprintf(tcPointColor,        _T("Point color : %s"),               report.tcLightColor);

                       wsprintf(tcMeshColor,         _T("Mesh color : %s"),                report.tcMeshColor);

                       wsprintf(tcFaceColor,         _T("Face color : %s"),                report.tcFaceColor);

                       wsprintf(tcLightColor,        _T("Light color : %s"),               report.tcLightColor);

                       wsprintf(tcBackgroundColor,   _T("Background color : %s"),          report.tcBackgroundColor);

                      

                       pDC->TextOutW(reArea.left + 80, y_Position, tcMeshType, lstrlen(tcMeshType));

                       pDC->TextOutW(reArea.right/2 + 50, y_Position, tcPointColor, lstrlen(tcPointColor));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcMeshVector, lstrlen(tcMeshVector));

                       pDC->TextOutW(reArea.right/2 + 50, y_Position, tcMeshColor, lstrlen(tcMeshColor));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcClipping, lstrlen(tcClipping));

                       pDC->TextOutW(reArea.right/2 + 50, y_Position, tcFaceColor, lstrlen(tcFaceColor));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcPerspective, lstrlen(tcPerspective));

                       pDC->TextOutW(reArea.right/2 + 50, y_Position, tcLightColor, lstrlen(tcLightColor));

               y_Position+=25;

                       pDC->TextOutW(reArea.left + 80, y_Position, tcLightPosition, lstrlen(tcLightPosition));

                       pDC->TextOutW(reArea.right/2 + 50, y_Position, tcBackgroundColor, lstrlen(tcBackgroundColor));

                       pDC->SelectObject(OldFont);

              

        // Line 3

               pDC->MoveTo(reArea.left+55,           reArea.bottom-80);

               pDC->LineTo(reArea.right-55,  reArea.bottom-80);

              

        // Div...

               OldFont = pDC->SelectObject(&ftMyNumber);

               TCHAR tcMecha[128];

               SetTextAlign(pDC->m_hDC, TA_CENTER);

               SetTextColor(pDC->m_hDC, RGB(100, 100, 100));

               wsprintf(tcMecha, _T("Div. Of Mechanical and auto motive Engineering Kong-ju National University"));

               pDC->TextOutW(reArea.right/2, reArea.bottom-70, tcMecha, lstrlen(tcMecha));

               SetTextAlign(pDC->m_hDC, TA_LEFT);

               pDC->SelectObject(OldFont);

}




코드를 보면 약간 달라진것이 있다.

대부분의 출력문에 %s가 붙고, 그곳에 report 멤버가 들어가게 만들었다.

물론 구조체의 문자열은 처음에 전부 쓰래기 값을 갖고 있기 때문에, 생성자 차원에서 모든 배열을 NULL로 제로 셋팅 해줄 필요가 있겠다. ^^

코드를 완성 한 후에 게시글을 올리는 것이라 무엇이 좀 빠진듯한 느낌을 받는데, 아무튼 이 정도까지 하고 책과 비교해 보기를 바란다.


그럼 수신자 입장은 충분히 설명했으니

송신자의 입장이 되는 ProjectOpenGL의 DataView 다이얼로그의 메시지 처리를 한번 보도록 하자.


 <그림 2 :: 송신자!>


<그림 2>에서는 ProjectMFCReport의 이름을 갖는 윈도우를 찾고, 그 윈도우의 핸들을 얻는 소스코드를 볼 수 있다.

토시 하나 틀리면 찾지 못한다는 것이다.


필자는 이 버그하나 때문에, 48시간이 넘게 새우잠을 자고 있다. 때문에 이 문제에 굉장히 민감해져있다.

혹시나 하는 마음에 ProjectMFCReport의 Frame 구현부로 가서 제목 표시줄에도 ProjectMFCReport로 나오게 했다.

왜냐하면, 처음에 "제목없음 - ProjectMFCReport"로 나오기 때문이다. -_-^


또한 WM_COPYDATA 메시지, copydata.lpData의 report를 SendMessage함수를 통해 '통신(?)'하는 것 처럼 보이게 하는 소스코드도 볼 수 있다.

여기까지 했다면 다음과 같은 상황에 봉착한다.


0. ProjectOpenGL과 ProjectMFCReport 프로세스를 각 1개씩 띄운다.

1. ProjectOpenGL의 DataView 다이얼로그에서 Report 버튼을 누른다.

2. 에러 메시지는 나지 않지만 ProjectMFCReport의 화면에도 아무런 변화가 일어나지 않는다.

3. 당신은 이미 빡쳐있다.


원래 필자는 이런 상황을 기대했었다.


0. ProjectOpenGL과 ProjectMFCReport 프로세스를 각 1개씩 띄운다.

1. ProjectOpenGL의 DataView 다이얼로그에서 Report 버튼을 누른다.

2. NULL 처리된 report멤버들이 통신으로 인한 초기화 작업을 거치고, OnDraw에서 출력 변수들과 Mix 된다.

3. 화면에 변화가 보인다.


이에 따라 정말 많은 생각을 하게 되었다.

요컨데 필자가 기계과라서, 누구에게 이런 상황을 하소연 할 수 없다.

그리고 코드블럭스부터 써왔기 때문에 디버그 방법도 모른다.


소스코드를 처음부터 하나 하나 고쳐보았다.

틀린 점은 없었다.


혹시 교재가 거지같이 만들어져서 내가 지금 엿먹고 있는지 알고 싶었다.

교재는 의외로 완벽했다.


그러다가 혹시, 메시지가 가는 도중에 변질되는 것이 아닌가 하는 의심이 들었다.

그래서 WM_COPYDATA가 아닌, WM_DESTROY를 보내 보았다.


 <그림 3 :: 메시지 수신 전>



  <그림 4 :: 메시지 수신 후>


필자가 이 현상을 보았을 때 얼마나 기뻤는지 알겠는가? (너무 기뻐서 기동이 형한테 자랑했다 ㅋㅋ)


 

요컨데 메시지는 제대로 갔다.

그런데, 그 메시지를 받은 클래스가 view가 아니였던 것이다.


툴바까지 없어진것을 보니 메시지가 도착한곳은 Frame클래스로 짐작되었다.


필자는 이에 따라, Frame, App, Doc, View 클래스에 모두 다 WM_COPYDATA 메시지 맵을 통한 메서드를 추가해 주었다.

그리고 WM_COPYDATA가 수신되자마자 Frame은 Frame이라고, App는 App라고 Doc는 Doc라고, View는 View라고, 적힌 대화상자를 띄우게 설정했다.


마지막으로 <그림 2>에서 WM_DESTROY 메시지를 WM_COPYDATA로 다시 설정해 주었다.


<그림 5 :: 할렐루야..ㅠㅠㅠㅠ>


<그림 5>는 이 버그가 잡히는 순간을 보여주고 있다.

4일 전부터 이 버그에서 손을 못 땟으니 레알 황송한 순간이다.


 <그림 6 :: 변수 등록>



 <그림 7 :: WM_COPYDATA 메시지 맵 정의>



이벤트에 대한 메시지 맵 추가는, 충분히 언급했으므로, 구구절절히 설명하지 않겠다.

보면 view 클래스에서 써먹었던 놈들 그대로 갖다 붙였음을 알 수 있다.


view 클래스에서 썼던 WM_COPYDATA 메시지 맵은 과감하고 꼼꼼하게 삭제해주었다.


이제 우리가 주목해야 할 것은 

Frame <-> View 간의 데이터 이동이다.

이전에 우리는 ProjectOpenGL 프로젝트에서 View <->Doc 간의 데이터 이동 기술 구현에 성공한 사례를 갖고 있다.


필자는 이와 같은 경험으로 Frame의 report에 변수가 들어가자마자 View클래스를 조작하여 화면을 갱신하고자 했다.

하지만 제대로 동작하지 않았다..ㅠ.ㅠ



필자는 이와 관련하여 더 이상 스트래스 받는것이 싫다. 짜증이 폭발하기 직전이다.

현재까지 필자는 View클래스 내부에서 doc, frame, app를 소환할 줄 알지만, 역 소환 기술 방법에 대해서는 무지한 상태다.

따라서 역 소환처럼 보이는 트릭을 사용하려 한다.


Frame은 Doc과 같이 Data를 보관만 하게 두었다. 그리고 View에서 그것을 끄집어 내는 구조를 생각했다.


1. View 클래스는 매 밀리 초마다 Frame의 bActive (bool)값이 true인지 검사한다. false인 경우는 아무 동작도 하지 않는다.

2. WM_COPYDATA 메시지가 동작하면 불리안 값을 TRUE로 놓고 Frame의 데이터를 초기화 한다.

3. View 클래스에서 bActive값이 true임을 확인하고 View 클래스의 report에 초기화 시킨다.

4. View 클래스의 report 변수가 모두 초기화 되면 Frmae의 bActive 값을 false로 초기화 시킨다.


참고 자료 : http://blog.naver.com/risnuby1?Redirect=Log&logNo=20037452956


바로 작업에 착수하였다. 

1. Timer를 설정하였다.

2. OnTimer 내부에서 CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();를 선언하였다.

3. pFrame->report의 멤버들을 view클래스의 문자열 멤버들로 복사했다. 

    ex : wsprintf(report.tcPath, TEXT("%s"), pFrame->report.tcPath);

4. pFrame의 변수가 선언되자마자 알 수 없는 에러가 떴다.

5. 당신은 이미 빡쳤다.


요컨데 CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd(); 를 써야 하는데, 

pFrame으로 불러오는 변수가 view 메서드에 선언되면 알수없는 오류가 나타났다.

 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ 아 진짜!!!


혹시 Timer 내부에서 pFrame객체 자체를 받아들이지 못하는 것이 아닐까 생각해보았다.

그리고 지푸라기라도 잡는 심정으로 WM_LBUTTONDOWN 메시지를 만들어서 실험했다.


<그림 8 :: 뭐만 하면 제일 만만한 WM_LBUTTONDOWN에 적용ㅋㅋ>


<그림 8>의 우측 하단은 아이유님의 가사임.ㅋㅋㅋㅋ 이런 노래라도 안 들으면 정신 회까닥 할거 같음.ㅋㅋㅋㅋ

군대 가소대였을 때, 개미 돌아다니는 것만 봐도 재밌다고 깔깔거렸던게 기억난다. 침만 안 흘렸을 뿐이지 레알 미친 놈이였는데 ㅋㅋㅋ

난 지금 그와 비슷한 정신적 공황상태에서 코딩하고 있는것 같다.ㅋㅋㅋㅋ


 <그림 9 :: 그래도 신은 있는것 같다.jpg>


<그림 9>는 필자가 처음부터 기획했던 의도를 보여주고 있다.

소수점 때문에 범위를 벗어나는 것이 흠이긴 한데, 그것은 ProjectOpenGL의 Dialog에 담기는 report 초기화 방법을 조금 변형시켜주면 되겠다.


<그림 9>를 설명하면 아래와 같다.


 <그림 10 :: report 변수 20번 클릭>


<그림 10>처럼 report 변수만 백날 눌러봐야 소용이 없다.

report 변수도 한번 누르고 ProjectMFCReport 화면을 한번 눌러야 화면이 갱신되기 때문이다.


 <그림 11 :: NULL data 전송 결과>


report 버튼을 한번 누르고 Report화면을 한번 누르면 <그림 11>과 같은 화면을 볼 수 있다.

몇몇 변수가 깨져있음을 볼 수 있다. 이것은 별로 어렵지 않은 문제다.



이제 사소한 버그들을 잡아볼 것이다.


1. Mesh 및 Size 문자열이 표시되지 않는 문제.


 <그림 12 :: 코드 수정>


 <그림 13 :: 코드 수정결과>



2. 리포트의 칸이 모자른 현상

void CProjectOpenGLView::OnDa()에서, 문자열을 포맷하는 wsprintf에 들어가는 


 %e 를 %.3e로 바꾸었고,

 %lf 에 관련된 모든것은 %.1lf로 바꾸었다.


 <그림 14 :: 코드 수정결과>


<그림 14>에 보면 Point color가 255,255,255인데, 으레는 255,0,0 이다.

ProjectMFCReport 의 OnDraw에서 tcPointColor가 아닌, tcLightColor를 덧붙였기 때문에 저런 현상이 일어난 것이다.

저건 너무 간단한것이니 굳이 과정을 보여줄 필요는 없을 것 같다.



3. Report 화면을 눌러야 화면이 갱신된다.

요컨데 이게 가장 큰 화제가 되어야 하는것 아닌가?ㅋㅋ


 <그림 15 :: Init !!>


WM_CRAETE와 WM_DESTROY 메시지 함수를 등록하자.

혹시 WM_TIMER 메시지 함수를 삭제하거나 등록하지 않았다면 WM_TIMER 메시지 함수도 등록해야 한다.

그리고 <그림 15>와 같이 정의해 준다.


<그림 15>의 OnTimer 함수에 등록되어있는 Frame_Data_Init은 헤더파일에 public으로 다음과 같이 선언되어 있다.



public:

bool Frame_Data_Init(void);


<그림 16>으로 내부 기능을 볼 수 있다.


<그림 16 :: 내부 구조>


완벽해 보이는 <그림 16>의 코드에도 한가지 문제점이 있는데, 그것은 바로 더블 버퍼링을 전혀 고려하지 않은 view 라는 것이다.

화면 refresh가 300밀리초마다 반복되기 때문에, 사양이 낮은 컴퓨터에서는 상당히 답답해 보이는 프로그램이 될 가능성이 높다.


왠만하면 Invalidate()함수는 if문 안에 넣어주자.

그러면 정보가 갱신 될 때만, 화면도 갱신하는 효과를 볼 수 있을 것이다.


<그림 17 :: 내부 구조>


하앍... 드디어 완성.

생각보다 글씨가 곱게 나오지 않아서 상심이 컸다.

폰트 조절이 필요하다.


<그림 18 :: OnDraw 변화>


요컨데, 프린트 모드와 일반 그리기 모드에서의 폰트 변화만 주면 되기 때문에 <그림 18>과 같이 코드를 일부 변경하였다.

컴퓨터로 볼 때는 13이 좋지만, 프린트해서 볼 때는 10이 더 좋더라.ㅋ 














프로젝트 단위로 올리면 용량이 너무 커서, 내부의 소스코드만 올리겠습니다.


Project MFC Report : ProjectMFCReport.zip

Project OpenGL : ProjectOpenGL.zip

번호 제목 글쓴이 날짜 조회 수
공지 본 게시글의 첨부파일 권한 심플디 2014.08.22 2376
47 [MFC :: OpenGL] 컴공 수업 발표 자료 (옮김) [2] 심플디 2014.04.25 2878
46 [MFC :: OpenGL] Project 시즌 2 후기 (옮김) 심플디 2014.04.25 1568
45 [MFC :: OpenGL] File output (옮김) 심플디 2014.04.25 1500
44 [MFC :: OpenGL] Tool bar(툴바) 편집방법 (옮김) 심플디 2014.04.25 1821
43 [MFC :: OpenGL] IntroPage (옮김) file 심플디 2014.04.25 1500
» [MFC :: OpenGL] IPC 적용 (옮김) file 심플디 2014.04.25 1560
41 MFC :: OpenGL] ProjectMFCReport 와꾸짜기 (옮김) 심플디 2014.04.25 1681
40 [MFC :: OpenGL] Data Dialog 와꾸짜기 (옮김) 심플디 2014.04.25 1710
39 [MFC :: OpenGL] 시즌 2 개요 (옮김) file 심플디 2014.04.25 1499
38 [MFC :: OpenGL] Project 시즌 2 시작 (옮김) [1] 심플디 2014.04.25 1504
37 [MFC :: OpenGL] Project 시즌 1 후기 (옮김) file 심플디 2014.04.25 1566
36 [MFC :: OpenGL] Mesh :: Part 2 (옮김) [1] file 심플디 2014.04.25 1533
35 [MFC :: OpenGL] Mesh :: Part 1 (옮김) file 심플디 2014.04.25 1584
34 [MFC :: OpenGL] DXF :: Part 5 (옮김) file 심플디 2014.04.25 1574
33 [MFC :: OpenGL] DXF :: Part 4 (옮김) file 심플디 2014.04.25 1469
32 [MFC :: OpenGL] DXF :: Part 3 (옮김) file 심플디 2014.04.25 1453
31 [MFC :: OpenGL] DXF :: Part 2 (옮김) file 심플디 2014.04.25 1503
30 [MFC :: OpenGL] DXF :: Part 1 (옮김) file 심플디 2014.04.25 1545
29 [MFC :: OpenGL] Proposal 및 앞으로의 계획 (옮김) 심플디 2014.04.25 1539