728x90
SMALL
- 설명 -
프로젝트 명 : Notepad(단일 문서)
① 문자와 커서(캐럿)를 직접 view에 그려주는 방식
② Document-View 구조
③ Document의 Serialize()를 이용해 입력 내용을 저장 또는 열기
1. NotepadDoc.h
사용자 지정 변수
CString strDB[256] : 입력하는 문자열을 저장할 배열(256줄) -> 256줄 표시 가능
long pline : 현재 줄 표시
2. NotepadDoc.cpp
① 변수 초기화
② Serialize() : 내용 저장 및 열기. 줄의 개수와 문자열을 파일로 저장.
- Serialize() 소스 보기
더보기
// CNotepadDoc serialization
// 줄의 개수와 문자열을 파일로 저장
void CNotepadDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 여기에 저장 코드를 추가합니다.
// 줄과 스트링을 파일로 저장
ar << pline;
for (int i = 0; i <= pline; i++) {
ar << strDB[i];
}
}
else
{
// TODO: 여기에 로딩 코드를 추가합니다.
ar >> pline;
for (int i = 0; i <= pline; i++) {
ar >> strDB[i];
}
}
}
3. NotepadView.h
사용자 지정 변수
CPoint pntCur : 현재 캐럿의 위치 저장
CNotepadDoc *pDoc : Document 포인터
int lastline : 마지막 라인 기억
4. NotepadView.cpp
① 변수 초기화 코드 추가
② WM_CREATE 메시지 함수(OnCreate) : 최초 캐럿 위치 및 캐럿의 크기 지정.
③ WM_CHAR 메세지 함수(OnChar) : 문자 출력.
④ WM_KEYUP 메세지 함수(OnKeyUp) : WM_CHAR 메시지는 출력이 불가능한 키(기능키, SHIFT, CTRL, ALT, 방향키 등)를 처리할수 없으므로, 방향키를 처리하기 위해 WM_KEYUP 메세지 함수 추가.
⑤ WM_PAINT 메세지 함수(OnPaint) : View가 다시 그려질 때 호출되는 함수
- OnCreate() 소스 보기
더보기
// 최초 캐럿 위치 및 캐럿의 크기 지정
int CNotepadView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 여기에 특수화된 작성 코드를 추가합니다.
pDoc = GetDocument(); // Document 포인터 얻기
TEXTMETRIC txtKey;
CClientDC dc(this); // dc 얻기
dc.GetTextMetrics(&txtKey); // 현 dc(View)의 폰트정보 얻기
// 캐럿 생성(문자 평균 넓이의 절반, 문자의 높이)
CreateSolidCaret(txtKey.tmAveCharWidth / 2, txtKey.tmHeight);
CPoint pntTmp(0, 0);
// 캐럿의 최초 위치 지정(0, 0)
SetCaretPos(pntTmp);
// 캐럿 보이기
ShowCaret();
return 0;
}
- OnChar() 소스 보기
더보기
void CNotepadView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
CClientDC dc(this);
TEXTMETRIC txtKey;
dc.GetTextMetrics(&txtKey);
// 문자 입력하는 동안 캐럿을 숨긴다
HideCaret();
if (nChar == VK_BACK) { // 백 스페이스 경우
if (!pDoc->strDB[pDoc->pline].IsEmpty()) {
// 원래 문자열의 맨 끝을 잘라낸다.
pDoc->strDB[pDoc->pline] = pDoc->strDB[pDoc->pline].Left(pDoc->strDB[pDoc->pline].GetLength() - 1);
// 끝을 잘라낸 후 다시 출력
dc.TextOut(0, pntCur.y, pDoc->strDB[pDoc->pline] + _T(" "));
}
else {
if (pDoc->pline == lastline && pDoc->pline > 0) {
pDoc->pline--; // 줄을 하나 감소
lastline--;
}
}
}
else if (nChar == VK_RETURN) { // 엔터의 경우
pDoc->pline++; // 줄을 하나 증가
lastline++;
}
else if (nChar == VK_UP) { // 위 일경우
pDoc->pline--; // 줄을 하나 감소
}
else if (nChar == VK_DOWN) { // 아래 일 경우
if (pDoc->pline < lastline) {
pDoc->pline++;
}
}
else { // 일반 문자의 경우
pDoc->strDB[pDoc->pline] += (TCHAR)nChar;
// 화면에 출력
dc.TextOut(0, (int)pDoc->pline * txtKey.tmHeight, pDoc->strDB[pDoc->pline]);
}
// 현재 문자열이 끝나는 위치 계산
CSize strSize;
strSize = dc.GetTextExtent(pDoc->strDB[pDoc->pline]);
CString convert;
convert.Format(_T("%d"), strSize);
// 캐럿 위치 계산
pntCur.x = strSize.cx;
pntCur.y = int(pDoc->pline) * txtKey.tmHeight;
// 캐럿 위치 지정
SetCaretPos(pntCur);
// 캐럿 보여주기
ShowCaret();
CView::OnChar(nChar, nRepCnt, nFlags);
}
SMALL
- OnKeyUp() 소스 보기
더보기
// WM_CHAR 메세지는 출력이 불가능한 키(기능키, SHIFT, CTRL, ALT, 방향키 등)를 처리할수 없음
// 방향키를 처리하기 위해 WM_KEYUP 메세지 함수 추가
void CNotepadView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
if (nChar == VK_UP) {
if (!pDoc->pline == 0) {
OnChar(nChar, nRepCnt, nFlags);
}
}
else if (nChar == VK_DOWN) {
OnChar(nChar, nRepCnt, nFlags);
}
CView::OnKeyUp(nChar, nRepCnt, nFlags);
}
- OnPaint() 소스 보기
더보기
void CNotepadView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.
TEXTMETRIC txtKey;
dc.GetTextMetrics(&txtKey);
for (int i = 0; i <= pDoc->pline; i++) {
dc.TextOut(0, (int)i * txtKey.tmHeight, pDoc->strDB[i]);
}
}
5. 실행화면
728x90
LIST
'C++ > MFC' 카테고리의 다른 글
[MFC] 채팅 프로그램 - 서버 (1/3) (0) | 2021.08.25 |
---|---|
[MFC] 그림 그리기(그림판) (0) | 2021.08.24 |
[MFC] 파일 및 폴더 검색기 (2) | 2021.08.23 |
[MFC] C, C++ 컴파일러 오류 C4996 해결방법 (0) | 2021.08.20 |
[MFC] C++ 컴파일러 오류 C2664 두가지 해결방법 (0) | 2021.08.20 |