7월 28일 수업 정리입니다.
Edit
기존의 클라이언트에서 라인을 그려 맵을 그리는 방식에서
같은 솔루션안에 새로운 프로젝트 Edit을 만들어 Edit에서 맵을 만들어 저장하고 클라이언트에서 읽어오는 방식을 구현하겠습니다.
우선 같은 솔루션안에 Edit프로젝트를 생성하고 Client와 동일하게 Edit.cpp를 구성해줍니다 (메세지를 읽어오는 방식을 PeekMessage로 설정하고 GetTickAcount()를 통해 0.1초에 한번씩만 메인의 업데이트를 실행해주는 방식으로)
다음으로 클라이언트에서 사용하던 헤더들을 Edit으로 옮겨줘야합니다 (공통적으로 사용되는 부분을 굳이 두번 구현할필요없기때문 - 라인,라인매니저,키매니저 등등) 이때 원하는 파일들을 Edit폴더안으로 옮겨주는 방법과 Client와 Edit이 공통되는 폴더에서 헤더를 받아오도록 설정하는 방법중 편한방법을 사용하면 됩니다.
이제 중요부분은 LineManager를 수정하는것입니다 우선 마우스를 통해 라인을 그리는것을 구현 해보겠습니다.
우선 마우스의 좌표를 받아와서 선을 그려줘야합니다. 이 부분을 Update_LineManager에 구현합니다.
void CLine_Manager::Update_LineManager()
{
POINT pt{};
GetCursorPos(&pt);
ScreenToClient(g_hWnd, &pt);
if (CKey_Manager::Get_Instance()->Key_Down(KEY_LBUTTON))
{
m_listLine.emplace_back(CLine::Create(LINEINFO({ float(pt.x), float(pt.y) }, { float(pt.x), float(pt.y) })));
}
if (CKey_Manager::Get_Instance()->Key_Pressing(KEY_LBUTTON))
{
m_listLine.back()->Set_RightPos({ float(pt.x), float(pt.y) });
}
if (CKey_Manager::Get_Instance()->Key_Down(KEY_S))
{
SaveData();
}
if (CKey_Manager::Get_Instance()->Key_Down(KEY_L))
{
LoadData();
}
}
우선 좌표값을 담을 pt를 선언해주고 GetCursorPos를 통해 좌표값을 받아온뒤 ScreenToClient를통해 전체화면 기준인 커서의 좌표를 해당 클라이언트 기준 좌표로 변경해줍니다.
다음 키가 눌렸을때 시작점과 끝점을 현재 마우스 좌표로 Line을 생성해
m_listLine에 넣어주고 키가 눌려있는동안 이 끝점을 Set_Rightpos를 통해 수정해줍니다 이때 리스트에 바로 전의 넣어준값을 수정해줄것이기때문에 back을 통해 가장 뒤에있는것의 값을 수정해주면됩니다.
이를통해 마우스로 선을 생성해 화면에 표시할수있습니다.
다음으론 우린 이 정보를 Client에서 사용할것이기 때문에 저장과 불러오기기능 필요합니다.
저장을 먼저 구현해보겠습니다
void CLine_Manager::SaveData()
{
HANDLE hFile = CreateFile(L"../Data/LineData.dat",// 경로
GENERIC_WRITE,//쓸것인지 읽을 것인지
0, nullptr,// 파일 공유 및 보안 속성이건 건드릴 필요 없음.
CREATE_ALWAYS,// 늘 새로 만들겠다.
FILE_ATTRIBUTE_NORMAL,//애는 파일 만들때 속성 어떻게 할건지. 그냥 보통. 건드릴 필요 없음.
nullptr);// 이건 그냥 널널
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(nullptr, L"나랏말쌈이뒹귁에닳아 사맛디아니할세 살어리 살어리 랏다 청산에 살어리 랏다 이런들 어떠하리 저런들 어떠하리 이몸이 죽고 죽어 일백번 고쳐죽어", L"공부좀하자 애들아...", MB_OK);
return;
}
DWORD dwByte = 0;
for (CLine* pLine : m_listLine)
WriteFile(hFile, pLine->Get_LineInfo(), sizeof(LINEINFO), &dwByte, nullptr);
CloseHandle(hFile);
MessageBox(nullptr, L"나랏말쌈이뒹귁에닳아 사맛디아니할세 살어리 살어리 랏다 청산에 살어리 랏다 이런들 어떠하리 저런들 어떠하리 이몸이 죽고 죽어 일백번 고쳐죽어", L"성공성공!!!", MB_OK);
}
이전의 학습했던 파일입출력에서의 구현과 비슷합니다 대신 핸들과 INVALID_HANDLE_VALUE,메시지박스,CloseHandle을 사용합니다
FILE대신 핸들을 사용한다고 보시면 됩니다.
CreateFile을 통해 핸들을 받아오고 INVALID_HANDLE_VALUE와 비교하여 성공적으로 핸들을 불러왔는지 검사합니다 이때 메시지박스 함수를 이용하면 메시지박스를 화면에 띄울수있습니다.
다음 Write파일을 통해 리스트라인에있는 라인들을 모두 파일안에 저장해줍니다
저장을 모두끝냈다면 CloseHandle을통해 핸들을 닫아줍니다.
그리고 키입력을 받으면 저장을하게 업데이트에서 키매니저를 호출해줍니다
이로써 저장을 구현하였고 다음은 불러오기입니다.
void CLine_Manager::LoadData()
{
HANDLE hFile = CreateFile(L"../Data/LineData.dat",// 경로
GENERIC_READ,//쓸것인지 읽을 것인지
0, nullptr,// 파일 공유 및 보안 속성이건 건드릴 필요 없음.
OPEN_EXISTING,// 늘 새로 만들겠다.
FILE_ATTRIBUTE_NORMAL,//애는 파일 만들때 속성 어떻게 할건지. 그냥 보통. 건드릴 필요 없음.
nullptr);// 이건 그냥 널널
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(nullptr, L"나랏말쌈이뒹귁에닳아 사맛디아니할세 살어리 살어리 랏다 청산에 살어리 랏다 이런들 어떠하리 저런들 어떠하리 이몸이 죽고 죽어 일백번 고쳐죽어", L"공부좀하자 애들아...", MB_OK);
return;
}
DWORD dwByte = 0;
for (CLine* pLine : m_listLine)
Safe_Delete(pLine);
m_listLine.clear();
LINEINFO tLineInfo{};
while (true)
{
ReadFile(hFile, &tLineInfo, sizeof(LINEINFO), &dwByte, nullptr);
if (0 == dwByte)
break;
m_listLine.emplace_back(CLine::Create(tLineInfo));
}
CloseHandle(hFile);
MessageBox(nullptr, L"성공!", L"성공성공!!!", MB_OK);
}
불러오기는 Create_file에서 GENERIC_WRITE대신 GENERIC_READ로 바꿔줍니다 그리고 저장에선 파일의 끝을 알수있었지만 불러오기에서는 파일의 끝을 알수없습니다 그래서 dwByte를 이용합니다 ReadFile함수는 dwByte인자에 읽어온 바이트의 길이를 리턴해줍니다 이게 0이라면 읽어온 바이트가없다는것이고 곧 파일을 모두읽어왔다는 뜻이니 불러오기를 종료해주면됩니다.
똑같이 불러오기로 지정한 버튼을 누르면 이전에 저장한 맵을 잘 불러오는것을확인할수있습니다.
이로써 맵의 저장과 불러오기를 구현하였습니다.
오늘의 복습은 여기서 마치겠습니다.