상세 컨텐츠

본문 제목

CRichEditCtrl 이미지넣기 활용 관련

프로그래밍 관련/MFC

by AlrepondTech 2020. 9. 13. 20:35

본문

반응형









//
출차 http://en.pudn.com/downloads/sourcecode/windows/control/richedit/detail283_en.html

- RTF를 이용한 edit 이미지 넣기관련


//////////////////////////////////////////////////////////////////////////////////






출처: http://www.codeproject.com/KB/edit/SemiRichEdit.aspx

Introduction

Giving a rich edit control a background image seems to be impossible, but it is possible to give a rich edit control full transparency so you can see what is drawn on its parent window, this seems to be very helpful. Simply we can make the parent window draw what ever background (any image, any background color, see-thought look, etc) we desire to give the rich edit control the desired look and feel.

Background

I don�t think this control will be of any use to you if you don�t have a picture in the background of your dialog box. I built this controller to enhance a chat application that I�m building. But how does this work? It is really simple. I created a dialog with a Rich Edit control giving the Rich Edit control the Transparency property (that will give the Rich Edit control a fully transparent background) , now we are half way through, all you need to do is draw the background for the Rich Edit control yourself (on its parent window). If you are drawing an image in your dialog background then you must have handled the dialog�s WM_ERASEBKGND message to get your background drawn, here is where you should ask your Rich Edit control to draw its background too. The Rich Edit control takes the HDC of your dialog and a memory DC where you have already drawn your background. The Rich Edit calculates its dimensions and draws itself on the memory DC. Then all you have to do is draw that memory DC on your dialog.

How Does it Work?

First of all, a bitmap is created to keep the background image in the main application dialog so its size should be as big as the dialog it self:

void SemiRichEditDlg::CreateMemoryDC() {
    HDC hdc = GetDC(m_hWnd);
    m_hMemDC = CreateCompatibleDC(hdc);
    SelectObject(m_hMemDC, m_hBKbitmap);
    m_hStretchedBitmap = ::CreateCompatibleBitmap(hdc, WndClintRect.right - WndClintRect.left, WndClintRect.bottom - WndClintRect.top);
    m_hStretchedMem = CreateCompatibleDC(hdc);
    SelectObject(m_hStretchedMem, m_hStretchedBitmap);
    ReleaseDC(m_hWnd, hdc);
}

void SemiRichEditDlg::CreateMemoryDC() { HDC hdc = GetDC(m_hWnd); m_hMemDC = CreateCompatibleDC(hdc); SelectObject (m_hMemDC, m_hBKbitmap); m_hStretchedBitmap = ::CreateCompatibleBitmap(hdc, WndClintRect.right - WndClintRect.left, WndClintRect.bottom - WndClintRect.top); m_hStretchedMem = CreateCompatibleDC(hdc); SelectObject(m_hStretchedMem, m_hStretchedBitmap); ReleaseDC(m_hWnd, hdc); }

This bitmap needs to be deleted and resized whenever the dialog size changes so it would fit the new dialog size (remember to delete the old one or you will run out of memory soon). The new crated bitmap should be the same size as the resized dialog. This is how you handle the sizing message WM_SIZE:

  SelectObject(m_hStretchedMem,m_hStretchedBitmapOld);
    DeleteObject(m_hStretchedBitmap);
    HDC hdc = GetDC(m_hWnd);
    m_hStretchedBitmap = ::CreateCompatibleBitmap(hdc, 
                          WndClintRect.right - WndClintRect.left, 
                          WndClintRect.bottom - WndClintRect.top);
    InvalidateRect(m_hWnd, NULL, false);
    SelectObject(m_hStretchedMem, m_hStretchedBitmap);
    ReleaseDC(m_hWnd, hdc);

SelectObject(m_hStretchedMem,m_hStretchedBitmapOld); DeleteObject(m_hStretchedBitmap); HDC hdc = GetDC(m_hWnd); m_hStretchedBitmap = ::CreateCompatibleBitmap(hdc, WndClintRect.right - WndClintRect.left, WndClintRect.bottom - WndClintRect.top); InvalidateRect(m_hWnd, NULL, false); SelectObject(m_hStretchedMem, m_hStretchedBitmap); ReleaseDC(m_hWnd, hdc);

You need to select the old bitmap first so that you can delete the currently selected bitmap safely.

Now that we have a bitmap the same size of the dialog all we need to do is draw it on the background of the dialog, but remember before we draw the background we will pass the bitmap to the rich edit control so it would draw its background on the given bitmap. We will handle this in the background erasing of the main dialog.:

int SemiRichEditDlg::OnEraseBkgnd(WPARAM wParam, LPARAM lParam)
{
    HDC hdc = (HDC)wParam;    
    StretchBlt(m_hStretchedMem, 0, 0, WndClintRect.right, 
                      WndClintRect.bottom, m_hMemDC, 0, 0, 
                      m_iBitmapWidth, m_iBitmapHight, SRCCOPY);
    m_semiricheditctrl.DrawBackGround(hdc, m_hStretchedMem);
    BitBlt(hdc, 0, 0, WndClintRect.right - WndClintRect.left, 
                        WndClintRect.bottom - WndClintRect.top, 
                        m_hStretchedMem, 0, 0, SRCCOPY);
    return 1;
}

int SemiRichEditDlg::OnEraseBkgnd(WPARAM wParam, LPARAM lParam) { HDC hdc = (HDC)wParam; StretchBlt(m_hStretchedMem, 0, 0, WndClintRect.right, WndClintRect.bottom, m_hMemDC, 0, 0, m_iBitmapWidth, m_iBitmapHight, SRCCOPY); m_semiricheditctrl.DrawBackGround(hdc, m_hStretchedMem); BitBlt(hdc, 0, 0, WndClintRect.right - WndClintRect.left, WndClintRect.bottom - WndClintRect.top, m_hStretchedMem, 0, 0, SRCCOPY); return 1; }

How Does the Rich Edit draw its Background (Rich Edit to Bitmap)?

Here the rich edit control need to build its custom background on a bitmap then simply copy it to the parent window background image. In windows programming for customizing the behavior of a control we need to subclass the control. This is what we exactly need to customize the rich edit control. All that has to be done is to set the rich edit a new window procedure, this is how it is done. (Remember to keep the original windows procedure)

bool SemiRichEditCtrl::AttachCtrl(HWND hwnd)
{
    m_hWnd = hwnd;
    SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
    OrgCrlProc = (WNDPROC) SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)CtrlProc_);
    GetRectPos(&m_RichEditRect);
    return true;
}

bool SemiRichEditCtrl::AttachCtrl(HWND hwnd) { m_hWnd = hwnd; SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); OrgCrlProc = (WNDPROC) SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)CtrlProc_); GetRectPos(&m_RichEditRect); return true; }

Once this is done the windows messages will go to the new window procedure. Now you can over ride what ever messages you want to customize the control.

Now that we are almost done all we need to draw the background of the rich edit control to a bitmap and then copy it to the main window background(the main bitmap). So we need to create a bitmap the size of the rich edit background

 //Creating A DC 

    HDC hdcTransparent = CreateCompatibleDC(hdc);
    //Creating a bitmap

    hTransparentBitmap = ::CreateCompatibleBitmap(hdc,
        m_RichEditRect.right - m_RichEditRect.left, 
        m_RichEditRect.bottom - m_RichEditRect.top);
    //Selecting the bitmap in to the created DC

    SelectObject(hdcTransparent, hTransparentBitmap);

//Creating A DC HDC hdcTransparent = CreateCompatibleDC(hdc); //Creating a bitmap hTransparentBitmap = ::CreateCompatibleBitmap(hdc, m_RichEditRect.right - m_RichEditRect.left, m_RichEditRect.bottom - m_RichEditRect.top); //Selecting the bitmap in to the created DC SelectObject(hdcTransparent, hTransparentBitmap);

My Goal here was to give the rich edit control the see throught look so I will fill the bitmap with white color

  //Fill the bitmap with white colour

    FloodFill(hdcTransparent, 0, 0,RGB(255,255,255));

//Fill the bitmap with white colour FloodFill(hdcTransparent, 0, 0,RGB(255,255,255));

Now to give the see-through look we will use the AlphaBlend function to draw the rich edit bitmap to the parent background. If you want to control the transparency modify the BLENDFUNCTION (last parameter passed to the AlphaBlend function)

   AlphaBlend(hStretchedMem, m_RichEditRect.left + 1, m_RichEditRect.top + 1, 
        m_RichEditRect.right - m_RichEditRect.left,
        m_RichEditRect.bottom - m_RichEditRect.top,
        hdcTransparent, 0, 0, m_RichEditRect.right - m_RichEditRect.left, 
        m_RichEditRect.bottom - m_RichEditRect.top, blend);

AlphaBlend(hStretchedMem, m_RichEditRect.left + 1, m_RichEditRect.top + 1, m_RichEditRect.right - m_RichEditRect.left, m_RichEditRect.bottom - m_RichEditRect.top, hdcTransparent, 0, 0, m_RichEditRect.right - m_RichEditRect.left, m_RichEditRect.bottom - m_RichEditRect.top, blend);

For now we need the rich edit control to draw it self (content) on the bitmap this will reduce the flickering effect when ever the control is invalidated. The rich edit content is rendered to the bitmap then rendered to the main parent bitmap by using BitBlt with SRCAND as the raster operation code

 //Finding the size in twips

    nLogPixelsX = ::GetDeviceCaps(hdcTransparent, LOGPIXELSX);
    nLogPixelsY = ::GetDeviceCaps(hdcTransparent, LOGPIXELSY);
	
    rc.left = MulDiv(rc.left, 1440, nLogPixelsX);
    rc.top = MulDiv(rc.top, 1440, nLogPixelsY);
    rc.right = MulDiv(rc.right, 1440, nLogPixelsX);
    rc.bottom = MulDiv(rc.bottom, 1440, nLogPixelsY);
	
    fr.hdc = hdcTransparent;
    fr.hdcTarget = hdcTransparent;
    fr.rc = rc;
    fr.rcPage = rc;
    fr.chrg.cpMin = SendMessage( m_hWnd, EM_CHARFROMPOS, (WPARAM) FALSE, 

                                (LPARAM) &point);
    fr.chrg.cpMax = -1;
    //Requesting to draw on the DC

    lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) TRUE, 

                           (LPARAM) &fr);  
    lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) FALSE, 

                           (LPARAM) NULL);
    BitBlt (hStretchedMem, m_RichEditRect.left + 1, m_RichEditRect.top + 1,

        m_RichEditRect.right - m_RichEditRect.left, 

        m_RichEditRect.bottom - m_RichEditRect.top,
        hdcTransparent, 0, 0,SRCAND);

//Finding the size in twips nLogPixelsX = ::GetDeviceCaps(hdcTransparent, LOGPIXELSX); nLogPixelsY = ::GetDeviceCaps(hdcTransparent, LOGPIXELSY); rc.left = MulDiv(rc.left, 1440, nLogPixelsX); rc.top = MulDiv(rc.top, 1440, nLogPixelsY); rc.right = MulDiv(rc.right, 1440, nLogPixelsX); rc.bottom = MulDiv(rc.bottom, 1440, nLogPixelsY); fr.hdc = hdcTransparent; fr.hdcTarget = hdcTransparent; fr.rc = rc; fr.rcPage = rc; fr.chrg.cpMin = SendMessage( m_hWnd, EM_CHARFROMPOS, (WPARAM) FALSE,
(LPARAM) &point); fr.chrg.cpMax = -1; //Requesting to draw on the DC lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) TRUE,
(LPARAM) &fr); lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) FALSE,
(LPARAM) NULL); BitBlt (hStretchedMem, m_RichEditRect.left + 1, m_RichEditRect.top + 1,
m_RichEditRect.right - m_RichEditRect.left,
m_RichEditRect.bottom - m_RichEditRect.top, hdcTransparent, 0, 0,SRCAND);

Known Issues

  • The Rich Edit control doesn't always draw the correct content. This is due to the limitation rendering the contect of rich edit control for a specific device

History

  • Version 1.5 Improved performance, almost no flicking
  • Version 1 of the see through Rich Edit control

License

 

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

 

////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=569088&ref=569088

STDMETHODIMP CEmoEdit::GetText(BSTR * pbsStr) {
    // TODO: Add your implementation code here
    // TODO: Add your implementation code here
    HRESULT hr = S_OK;
    IRichEditOle * pOlePtr = NULL;
    TCHAR tc[4096];
    // 한번에 4096 이상은 허용하지 않는다.
    // 중간 변형에 쓰일 버퍼.
    TCHAR tcInterim[4096];
    ZeroMemory(tc, 4096);
    ZeroMemory(tcInterim, 4096);::SendMessage(m_ctlRichEdit.m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM) & pOlePtr);
    int nCount = pOlePtr -> GetObjectCount();
    GETTEXTLENGTHEX ex;
    ex.flags = GTL_DEFAULT;
    ex.codepage = CP_ACP;
    int nLength =::SendMessage(m_ctlRichEdit.m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM) & ex, 0);
    int nFound = 0;
    int nLastIndex = 0;
    REOBJECT rObject;
    TEXTRANGE tr;
    for (int index = 0; index < nCount; index ++) {
        ZeroMemory(& rObject, sizeof(REOBJECT));
        rObject.cbStruct = sizeof(REOBJECT);
        rObject.cp = index;
        hr = pOlePtr -> GetObject(index, & rObject, REO_GETOBJ_ALL_INTERFACES);
        if (SUCCEEDED(hr)) { // first get text .
            if (rObject.cp >= 0) { // retrieve string from last index to the current pos minus 1.
                if (nLastIndex != rObject.cp) {
                    tr.chrg.cpMin = nLastIndex;
                    tr.chrg.cpMax = rObject.cp - 1;
                    tr.lpstrText = tcInterim;
                    // OK , Get String.
                    int nLen =::SendMessage(m_ctlRichEdit.m_hWnd, EM_GETTEXTRANGE, NULL, (LPARAM) & tr);
                    // buffer check.
                    if (_tcslen(tc) + nLen + 5 > 4096) 
                        break;
                    
                    // buffer copy stop.
                    // append string.
                    _tcsncat(tc, tcInterim, nLen);
                }
            }
            // modify last index .
            nLastIndex = rObject.cp + 1;
            // get emoticon string.
            LPCTSTR lpEmo = m_EmoStorageMap[(DWORD)rObject.pstg];
            // buffer check.
            if (_tcslen(tc) + _tcslen(lpEmo) > 4096) 
                break;
            
            // append string.
            _tcsncat(tc, lpEmo, _tcslen(lpEmo));
            nFound ++;
            // copy left strings.
            if (nFound == nCount) {
                if (rObject.cp == nLength - 1) 
                    break;
                
                // 더 이상 Copy할필요는 없다.
                // 그렇지 않으면 복사한다.
                tr.chrg.cpMin = nLastIndex;
                tr.chrg.cpMax = nLength - 1;
                tr.lpstrText = tcInterim;
                // OK , Get String.
                int nLen =::SendMessage(m_ctlRichEdit.m_hWnd, EM_GETTEXTRANGE, NULL, (LPARAM) & tr);
                // buffer check.
                if (_tcslen(tc) + nLen > 4096) 
                    break;
                
                // buffer copy stop.
                // append string.
                _tcsncat(tc, tcInterim, nLen);
                break;
            }
        }
    }
    if (nLastIndex == 0) { // OK , Get String.
        GETTEXTEX tex;
        ZeroMemory(& tex, sizeof(GETTEXTEX));
        tex.cb = 4096;
        tex.codepage = CP_ACP;
        tex.flags = GT_USECRLF;::SendMessage(m_ctlRichEdit.m_hWnd, EM_GETTEXTEX, (WPARAM) & tex, (LPARAM)tc);
        // int nLen = ::SendMessage( m_ctlRichEdit.m_hWnd , EM_GETTEXTRANGE , NULL , (LPARAM)&tr );
    }
    USES_CONVERSION;
    *pbsStr = SysAllocString(A2W(tc));
    return S_OK;
}




///////////////////////////////////////////////////////////////////////////////////////

// MultiLookView.cpp : implementation of the CMultiLookView class
//

#include "stdafx.h"
#include "MultiLook.h"

#include "MultiLookDoc.h"
#include "MultiLookView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMultiLookView

IMPLEMENT_DYNCREATE(CMultiLookView, CFormView)

BEGIN_MESSAGE_MAP(CMultiLookView, CFormView)
	//{{AFX_MSG_MAP(CMultiLookView)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMultiLookView construction/destruction

CMultiLookView::CMultiLookView()
	: CFormView(CMultiLookView::IDD)
{
	//{{AFX_DATA_INIT(CMultiLookView)
	//}}AFX_DATA_INIT
	// TODO: add construction code here

}

CMultiLookView::~CMultiLookView()
{
}

void CMultiLookView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMultiLookView)
	//}}AFX_DATA_MAP
}

BOOL CMultiLookView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CFormView::PreCreateWindow(cs);
}

void CMultiLookView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();
	// 탭 컨트롤에서 사용할 이미지 설정
	CTabCtrl* pTab = (CTabCtrl*)GetDlgItem(IDC_TAB1);
	CImageList imgList;
	imgList.Create(IDB_TAB, 32, 0, (COLORREF)-1);
	pTab->SetImageList(&imgList);
	imgList.Detach();
	// 탭에 타이틀과 이미지 추가
	pTab->InsertItem(0, "편지", 0);
	pTab->InsertItem(1, "날짜", 1);
	pTab->InsertItem(2, "전화", 2);
	pTab->InsertItem(3, "계획서", 3);	
	pTab->InsertItem(4, "일기장", 4);	
	pTab->InsertItem(5, "메모", 5);	
	// 리치 에디트 컨트롤의 내용 초기화
	InitRichEdit();
}

/////////////////////////////////////////////////////////////////////////////
// CMultiLookView diagnostics

#ifdef _DEBUG
void CMultiLookView::AssertValid() const
{
	CFormView::AssertValid();
}

void CMultiLookView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CMultiLookDoc* CMultiLookView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMultiLookDoc)));
	return (CMultiLookDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMultiLookView message handlers

void CMultiLookView::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CTabCtrl* pTab = (CTabCtrl*)GetDlgItem(IDC_TAB1);
	CRichEditCtrl* pRich = (CRichEditCtrl*)GetDlgItem(IDC_RICHEDIT1);
	int count = pTab->GetCurSel();  // 선택된 탭의 인덱스
	switch(count)
	{
	case 0:			
		pRich->ShowWindow(SW_SHOW);
		break;
	default:					
		pRich->ShowWindow(SW_HIDE);
		break;
	}
	*pResult = 0;
}

void CMultiLookView::SetHeadFormat(CHARFORMAT& cf)
{
	// 문자 형식 설정
	cf.cbSize = sizeof(CHARFORMAT);
	cf.dwMask = CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_BOLD|CFM_ITALIC;
	cf.dwEffects = CFE_BOLD|CFM_ITALIC;
	cf.yHeight = 400;
	cf.crTextColor = RGB(255,0,0);
	cf.bCharSet = ANSI_CHARSET;
	cf.bPitchAndFamily = FF_SWISS;
	lstrcpy(cf.szFaceName, "Arial");
}

void CMultiLookView::SetTailFormat(CHARFORMAT& cf, PARAFORMAT& pf)
{
	// 문자 형식 설정
	cf.cbSize = sizeof(CHARFORMAT);
	cf.dwMask = CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_BOLD|CFM_UNDERLINE;
	cf.dwEffects = CFE_BOLD|CFE_UNDERLINE;
	cf.yHeight = 300;
	cf.crTextColor = RGB(0,0,255);
	cf.bCharSet = ANSI_CHARSET;
	cf.bPitchAndFamily = FF_ROMAN;
	lstrcpy(cf.szFaceName, "Times New Roman");

	// 문단 형식 설정
	pf.cbSize = sizeof(PARAFORMAT);
	pf.dwMask = PFM_ALIGNMENT;
	pf.wAlignment = PFA_RIGHT;
}

void CMultiLookView::InitRichEdit()
{
	// 리치 에디트 컨트롤의 내용 초기화
	CRichEditCtrl* pRich = (CRichEditCtrl*)GetDlgItem(IDC_RICHEDIT1);
	CTime time = CTime::GetCurrentTime();
	CString strDate = time.Format("%Y년 %m월 %d일");
	CString strTime = time.Format("%A %p:%I시%M분%S초");
	CString strText; 
	strText = strDate + "\r\n" + strTime + "\r\n\r\n";
	pRich->SetWindowText(strText);

	CHARFORMAT cf; // 문자 형식 구조체
	PARAFORMAT pf; // 문단 형식 구조체

	SetHeadFormat(cf);
	int nStart = 0;
	int nEnd = strDate.GetLength()+2;
	pRich->SetSel(nStart, nEnd); // 셀 범위 설정
	pRich->SetSelectionCharFormat(cf); // 선택된 셀의 글자 형식 설정

	SetTailFormat(cf, pf);
	nStart = nEnd;
	nEnd += strTime.GetLength()+2;
	pRich->SetSel(nStart, nEnd); // 셀 범위 설정
	pRich->SetSelectionCharFormat(cf); // 선택된 셀의 글자 형식 설정
	pRich->SetParaFormat(pf); // 선택된 셀의 문단 형식 설정
}

 


///////////////////////////////////////////////////////////////////////////////

이거 또, 정말 오랜만에 글을 하나 올려봅니다. ㅋ 

한동인 미투데이에 빠져들면서~ 블로그를 좀 등한시 했는데, 요즘 미투데이가 시들시들해지면서~

다시 블로그로~~ ^^;;;; 아.하.하.하..;;


요즘 개인적으로 툴을 하나 만들어볼까~~~!? 하고 작업을 시작했습니다.

텍스트(?)를 화면에 뿌려주는 게 필요해서 뭘로 할까~ 고민하다가 RichEdit 컨트롤 로 정했습니다.
( 텍스트에 따라 글자 색깔도 조금 바꿔주는 등의 처리가 필요할 듯 싶어서...^^;;;; )

본격적으로 작업을 시작하기도 전에~ 테스트 단계에서 무진장(?) 애를 먹었습니다.

간단하게 RichEdit 컨트롤을 테스트하기 위해 약간의 입력을 했는데, 아래의 결과가 나오더군요;;;

 

< 그림. 01 > RichEdit 컨트롤 테스트

폰트를 '돋움체 - 크기 : 11' 로 맞춰두고 입력을 했는데~ 이 모양입니다;;;
( '돋움체' 는 고정폭으로 한글 1자와 숫자, 영어 2자의 폭이 일치해야하거든요... =_=;;; )

숫자와 한글은 입력이 잘된다 싶었는데, 이 놈의 영어 입력에서~ 살짝 태클이 들어오더군요;;;

보시는 것처럼 영어 입력시 폰트가 달라집니다. 이후에 입력되는 숫자들도 영향을 받구요...

이.것.때문에 한참 삽질을 했습니다...ㅠ.ㅠ...

검색으로 RichEdit 컨트롤에 관련된 내용을 뒤지다가 엄~~~~청 뒷북으로 알게된 사실....;;;

RichEdit 2.0 부터는 사용자가 입력하는 언어를 바꾸면 자동으로 글꼴을 바꿔주는 옵션이 있다. ( IMF_AUTOFONT )


이런게 있더군요... 하아 =3=3=3
( RichEdit 1.0 이후로는 쓴 적이 없다보니 이런 일이... oTL;;;; )

이 옵션은 IDE 폼 디자이너의 컨트롤 속성 창으로는 변경이 불가능하며~

SendMessage() 를 이용해야 합니다.


[ Visual C++ 에서의 코드 ]


CRichEditCtrl m_ctrlRichEdit;

...

m_ctrlRichEdit.SendMessage(EM_SETLANGOPTIONS, 0,
            (LPARAM)(m_ctrlRichEdit.SendMessage(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONT));


[ C++ Builder 에서의 코드 ]


TRichEdit *RichEdit1;

...

::SendMessage(RichEdit1->Handle, EM_SETLANGOPTIONS, 0,
      (LPARAM)(::SendMessage(RichEdit1->Handle, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONT));


RichEdit 2.0 나온지도 한참 됐는데... 이제서야 알게됐다는게 심히 부끄럽네요.. *^_^*;;;

슬~~ 슬~~ 저는 또 작업 진행하러 갑니다~~ : )




출처들:

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=569088&ref=569088

http://www.sarangnamu.net/basic/basic_view.php?no=2617&page=62&sCategory=0

http://blog.naver.com/PostView.nhn?blogId=lopi1&logNo=80019212520&redirect=Dlog&widgetTypeCall=true

 

반응형


관련글 더보기

댓글 영역