CMainFrame 이 CSerialMFC 의 객체를 멤버변수로서 가지게 된다고 했으니 CMainFrame 의 멤버변수를 선언합니다.
아래 그림과 같이 VC++ Work Space 화면의 ClassView 탭에서 CMainFrame 클래스가 표시된 곳에 마우스를 위치시키고 오른쪽 마우스 버튼을 눌러 “Add Member Variable” 메뉴를 선택합니다.
위 그림처럼 ClassView 에서 각 클래스 이름에 대고 마우스 오른쪽버튼을 누르면 나오는 팝업메뉴에는 멤버함수를 추가시킬 수 있는 “Add Member Function”, 멤버 변수를 추가시킬 수 있는 “Add Member Variable”, 가상함수를 정의할 수 있는 “Add Virtual Function”, 윈도우 클래스 (CWnd 로부터 상속되어진 클래스) 이고 소스에 메세지맵이 정의돼 있으면 나오는 “Add Windows Message Handler” 등이 보여집니다.
VC++ 에선 위와같이 Work Space 의 ClassView 탭 에서 팝업메뉴를 사용하거나 Class Wizard 를 직접 띄워(Ctrl+W) 메뉴를 사용하여 간편하게 멤버함수나 변수를 추가시킬 수 있습니다.
그리고 다음 그림과 같이 멤버변수를 Public 으로 선언해줍니다.
( Protected 가 아닙니다. 이전 게시물에서 Protected 로 하라고 돼 있었습니다. 이전 게시물을 보고 컴파일 에러가 나왔던 분들은 이부분을 수정해주세요.)
마찬가지 방식으로 int 형 변수를 m_nPort 란 이름으로 Protected: 로 선언해줍니다.
마찬가지 방식으로 CSerial::EBaudrate 형 변수를 m_eBaudrate 라는 이름으로 Protected: 로 선언해줍니다.
마지막의 m_eBardrate 선언시 위와같은 방식의 변수선언 위저드통한 변수 선언이 안될땐 CMainFrame 클래스가 정의된 헤더파일에 직접 변수선언 부분을 기입합니다.
그러면 아래와 같이 CMainFrame 클래스에 세개의 변수가 public: 으로 새로 선언되었을 것입니다.
CSerialMFC m_Serial;
int m_nPort;
CSerial::EBaudrate m_eBaudrate;
|
m_Serial 변수는 CSerial 클래스가 상속되어져 정의된 CSerialMFC 클래스가 실제 메모리에 인스턴스화 된 것입니다.
m_nPort 와 m_eBaudrate 는 m_Serial 이 사용할 시리얼 포트 번호와 보레이트를 기억시키기 위하여 만들었습니다.
위에서 선언한 변수들을 초기화 시켜주기 위해 CMainFrame 의 OnCreate 함수의 return 0; 구문 바로 이전에 다음과 같이 기입하여 줍니다.
if(CSerial::CheckPort(_T("COM1"))
== CSerial::EPortAvailable)
m_nPort = 1;
else if(CSerial::CheckPort(_T("COM2"))
== CSerial::EPortAvailable)
m_nPort = 2;
else if(CSerial::CheckPort(_T("COM3"))
== CSerial::EPortAvailable)
m_nPort = 3;
else if(CSerial::CheckPort(_T("COM4"))
== CSerial::EPortAvailable)
m_nPort = 4;
else
m_nPort = 1;
m_eBaudrate = CSerial::EBaud9600; // 9600 bits/sec
|
CSerial::CheckPort 함수는 static 함수이므로 CSerial 을 오브젝트로 생성하지 않아도 호출할 수 있습니다.
이 함수는 매개변수로 넘겨진 시리얼 포트가 사용 가능한지 체크해 볼 수 있는 기능이 있습니다.
다음으로 Work Space 의 ResourceView 탭에서 Menu 를 선택해 하위 IDR_MAINMENU 를 클릭하면 나오는 메뉴에디터에서 아래 그림과 같이 “접속”, “접속종료”, “통신포트 설정” 세개의 메뉴 항목을 삽입하고 차례대로 “ID_CONNECT”, “ID_DISCONNECT”, “ID_COMSETTING” 라고 기입합니다.
새로운 메뉴를 삽입하였으므로 이 메뉴가 선택되었을 때 호출되는 함수들을 정의합니다.
Ctrl+W 키를 눌러 클래스 위저드를 실행시키고 방금 삽입한 세개의 메뉴들에 해당하는 ID 값에 대한 COMMNAND 메세지 처리함수를 만들어줍니다.
아래 그림처럼 클래스 위저드가 이름지어주는대로 OnConnect, OnDisconnect, OnComsetting 함수들을 CMainFrame 에 만듭니다.
위와같은 방식으로 OnConnect 와 OnDisconnect 에 대한 UPDATE_COMMAND_UI 메세지 핸들러 함수도 만들어줍니다.
클래스 위저드가 OnUpdateConnect 와 OnUpdateDisconnect 라고 이름지어줄 것입니다.
이 함수들 안에서 위 두 메뉴의 시각적 효과를 특징지워줄 수 있습니다.
접속 메뉴를 클릭해서 포트를 열었다면 접속종료를 클릭해 포트를 닫을 때 까지 이 접속 메뉴를 비활성화 시키야 하고 접속종료 메뉴도 마찬가지의 시각효과를 주어야 하니까요.
OnConnect 와 OnDisconnect 멤버변수내의 코드를 아래와 같이 추가시켜줍니다.
void CMainFrame::OnConnect()
{
CString szPort;
szPort.Format("COM%d", m_nPort);
if (m_Serial.Open(szPort,this) != ERROR_SUCCESS)
{
szPort += _T(" 포트를 열 수 없습니다.");
AfxMessageBox((LPCTSTR)szPort,MB_ICONSTOP|MB_OK);
GetParent()->PostMessage(WM_CLOSE);
return;
}
m_Serial.Setup(m_eBaudrate,
CSerial::EData8,
CSerial::EParNone,
CSerial::EStop1);
m_Serial.SetupHandshaking(CSerial::EHandshakeOff);
}
|
void CMainFrame::OnDisconnect()
{
if(m_Serial.IsOpen())
m_Serial.Close();
}
|
그리고 OnUpdateConnect 와 OnUpdateDisconnect 멤버함수내의 코드를 다음과 같이 기입해줍니다.
void CMainFrame::OnUpdateConnect(CCmdUI* pCmdUI)
{
if(m_Serial.IsOpen())
pCmdUI->Enable(FALSE);
else
pCmdUI->Enable(TRUE);
}
|
void CMainFrame::OnUpdateDisconnect(CCmdUI* pCmdUI)
{
if(m_Serial.IsOpen())
pCmdUI->Enable(TRUE);
else
pCmdUI->Enable(FALSE);
}
|
CSerialMFC::Open() 함수 호출시 열기를 원하는 COM 포트와 함께 현재윈도우 포인터를 넘겨줌으로서 시리얼 포트에 데이터입력이 포착되었을때 시리얼 입력을 처리할 함수가 있는 윈도우가 현재윈도우(CMainFrame) 임을 알려줍니다.
그리고 시리얼 클래스가 이 시점에서 윈도우메세지를 보낼때 이를 받을 메세지 핸들러도 정의해줍니다.
MainFrm.cpp 의 메세지맵안에 다음과 같이 ON_WM_SERIAL(OnSerialMsg) 문구를 삽입합니다. 반드시 //}}AFX_MSG_MAP 구문 바깥에 기입되어야 합니다.
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_CONNECT, OnConnect)
ON_COMMAND(ID_DISCONNECT, OnDisconnect)
ON_COMMAND(ID_COMSETTING, OnComsetting)
//}}AFX_MSG_MAP
ON_WM_SERIAL(OnSerialMsg) // <-- 삽입된 문구
END_MESSAGE_MAP()
|
MainFrm.h 파일에서 CMainFrame 클래스가 정의된 곳의 메세지 핸들러 함수를 선언해주는 곳에서 다음과 같이 afx_msg LRESULT OnSerialMsg (WPARAM wParam, LPARAM lParam); 문구를 삽입합니다.
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnConnect();
afx_msg void OnDisconnect();
afx_msg void OnComsetting();
//}}AFX_MSG
//삽입된 문구
afx_msg LRESULT OnSerialMsg (WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
|
이제 MainFrm.cpp 에 다음과 같이 OnSerialMsg 멤버함수를 정의해줍니다.
LRESULT CMainFrame::OnSerialMsg (WPARAM wParam, LPARAM /*lParam*/)
{
CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam));
CSerial::EError eError = CSerial::EError(HIWORD(wParam));
if (eEvent & CSerial::EEventRecv)
{
}
return 0;
}
|
그리고 현재까지의 작업이 오류없이 진행되었는지를 컴파일 해봅니다.
프로그램을 실행시켜 메뉴에서 “접속” 을 누르면 자신 PC 의 COM1 포트가 이상이 없다면 COM1 시리얼 포트를 통해 프로그램이 통신됩니다.
그러나 타겟을 COM1 으로 연결해 데이터를 전송해도 프로그램에는 아무 정보도 표시되지 않고 있습니다.
바로 위 메세지 핸들러가 이때의 처리를 해줍니다만 if 문 안에 아무런 처리루틴도 기입하지 않았기 때문에 아무런 정보도 표시되고 있지 않습니다.




Leave a Reply
댓글을 달기 위해서는 로그인해야합니다.