본문 바로가기

3.구현/VC++

[컨트롤이야기] 리치에디트(RichEdit) 컨트롤 사용하기

리치에디트는 일반 에디트(Edit) 컨트롤 보다 더 많은 기능을 제공한다. 노트패드와 워드패드 차이라고 볼 수 있다.

여기서는 MFC, Win32 및 WTL 모두 다루겠다. 사실 MFC가 사용이 쉽다. 무엇을 사용하는지는 개인적 선호도 차이가 있기 때문에 알아서 선택하면된다.

생성하기: 리치에디트를 핸들러를 생성하고 화면에 추가하고 변수와 연결하는 부분을 다룬다.

작성일: 2009.06.18 (http://ospace.tistory.com/), ospace114@empal.com

생성하기

MFC

MFC에서 리소스 에디터로 ToolBox(대화 상자 편집기)에서 "Rich Editor 2.0 Control"이라는 컨트롤을 사용한다.

주의 할 것은 MFC Application으로 프로젝트에서 대화상자 형태로 작성하는 경우 반드시 아래 코드를 App클래스의 InitInstance()에 추가해야한다. 추가 위치는 대화상자가 사용되기 전에 하면 된다.

본인은 InitCommonControls() 함수 다음에 넣어주었다.

AfxInitRichEdit();

아래 코드는 리소스 파일에 들어 있는 내용을 가져왔다. "RichEdit20A"로 리치에디트 버전 2.0을 사용한다는 의미이다.

CONTROL         "",IDC_EDIT_MAIN,"RichEdit20A",ES_MULTILINE | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,7, 33,229,160

생성된 컨트롤에 대해 "Add Variable..."로 컨트롤 제어할 수 있는 변수를 추가한다. 그러면 아래와 같은 인자가 추가된다.

CRichEditCtrl m_editMain;

Win32

Win32에서는 리치에디트용 DLL를 로딩하고 버전 1.0과 2.0에 따라서 이름을 다르게 사용한다. 그리고 반드시 "Richedit.h"를 포함시켜야 한다.

DLL로딩은

HMODULE hMod = LoadLibrary("Riched20.dll");

리치에디트 핸들러 생성

HANDLE hRich = Create(RICHEDIT_CLASS, NULL, WS_CHILD | WS_VISIBLE |
                                    WS_BORDER | WS_MULTILINE | WS__VSCROLL,
                                    0, 0, 0, hWnd, (HMENU)0, g_hInst, NULL);

리치 에디트 버전 1.0을 사용한다면 RICHEDIT_CLASS 대신에 "RichEdit"를 사용한다. hWnd은 생성된 부모 윈도우 핸들러이고, g_hInst는 WinMain()에서 넘겨받은 인스탄스 핸들러이다.

WTL

WTL는 _tWinMain() 함수가 있는 파일로 이동한다. 보통 자신의 프로젝트 이름과 동일한 cpp파일에 있다. 이곳에서 리치에디터 모듈을 로딩해야한다. 이는 WIn32과 동일한 과정이라 보면 된다. 맨 첫줄에 넣어주면 된다.

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, 
LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
{
    HINSTANCE hRich = LoadLibrary(CRichEditCtrl::GetLibraryName());
    if(NULL == hRich) {
        AtlMessageBox(NULL, _T("Error load a rich edit module."), _T("Error"), 
            MB_OK | MB_ICONERROR);
        return 0;
    }
    // ... 중략
}

그리고 정당한 위치에 해당 리치에디터 변수를 선언해준다.

CRichEditCtrl m_editMain;

그리고, 대화상자면 OnInitDialog()에 아니면 OnCreate()등에 리치에디트 컨트롤과 변수를 연결해주면 된다.

m_editMain.Attach(GetDlgItem(IDC_RICHEDIT2_MAIN));

WTL은 MFC와 멤버함수가 거의 비슷해서 사용하는데 어렵지는 않을 것이다.

출력하기

MFC, WTL

MFC와 WTL의 사용법은 동일하다. 리치 에디터로 텍스트 출력은 다음과 같이한다.

void CXXX::PrintMain(const std::string& msg) {
    m_editMain.ReplaceSel(msg.c_str());
}

간혹 위의 코드 컴파일서 chr*를 LPCTSTR로 변환이 안된다며 컴파일 에러가 발생한다. 그러면, 프로젝트 설정에서 문자열 사용을 Use Multi-Byte Character Set로 하면된다.

Win32

이번에는 Win32를 사용해보자.

void CXXX::PrintMain(const std::string& msg) {
    SendMessage(hRich, EM_REPLACESEL, (WPARAM)0, (LPARAM)msg.c_str());
}

커서 이동하기

아래는 특정 줄로 이동하여 해당 줄의 텍스트를 선택하는 것이다.

void CXXX::selectLine(int lien) {
    int lineIdx = m_editMain.LineIndex(line);
    int lineLen = m_editMain.LineLength(lineIdx);
    m_editMain.SetSel(lineIdx, lineIdx + lineLen);
}

int value1 = -1;
int nchar = m_richeditMain.SendMessage(EM_LINEFROMCHAR, (WPARAM) value1, 0);

int value2 = 1;
int nline = m_richeditMain.SendMessage(EM_LINEINDEX, (WPARAM) value2, 0);

int value3 = 0;
int nlength = m_richeditMain.SendMessage(EM_LINELENGTH, (WPARAM) value3, 0);

영역 가져오기

글자모양 변경

현재 문자 속성 획득

CHARFORMAT2 cf2;
memset(&cf, 0, sizeof(CHARFORMAT2));
cf2.cbSize = sizeof(CHARFORMAT2);
SendMessage(hRich, EM_GETCHARFORMAT, 1, (LPARAM)&cf2);

문자 속성 설정

CHOOSEFONT CFT; // 글꼴 공통 대화상자 사용
LOGFONT lf;
// ... CFT 대화상자에서 글꼴 설정
// 

CHARFORMAT2 cf2;
memset(&cf, 0, sizeof(CHARFORMAT2));
cf2.cbSize = sizeof(CHARFORMAT2);
cf2.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT;
cf2.crTextColor = CFT.rgbColors;
cf2.yHeight = CFT.iPointSize * 2;
strcpy(cf2.szFaceName, lf.lfFaceName); // lf는
df2.dwEffects = 0;
if(lf.lfItalic) cf.dwEffects |= CFE_ITALIC;
if(lf.lfwight == FW_BOLD) cf.dwEffects |= CFE_BOLD;
//...(생략)

SendMessae(hRich, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);

문단속성 변경

문단 속성 읽어옴.

PARAMFORMAT2 pf2;

memset(&pf2, 0, sizeof(PARAMFORMAT2));
pf2.cbSize = sizeof(PARAMFORMAT2);
pf2.dwMask = PFM_ALIGNMENT | PFM_OFFSETINDENT | PFM_OFFSET | PFM_RIGHTINDENT | PFM_LINESPACING;
SendMessage(hRigh, EM_GETPARAFORMAT, 0, (LPARAM)&pf2);

문단 속성 적용

SendMessage(hRigh, EM_SETPARAMFORMAT, 0, (LPARAM) &pf);

잘라내기/붙이기

클립 보드 기능은 WM_CUT, WM_COPY, WM_PASTE 메시지만 보내면 선택영역에 대한 클립 보드 동작을 한다.

기타

EM_HIDESELECTION 메시지는 포커스를 가지 않은 상태에서도 선택 영역을 보여주도록 함.

참고

[1] http://win32assembly.online.fr/tut33.html

[2] 리치 에디트, http://jacking75.cafe24.com/WTL/100.htm

반응형