Click here to Skip to main content
Click here to Skip to main content

See through Rich Edit control

, 8 Aug 2005
Rate this:
Please Sign up or sign in to vote.
This article discribes how to give a see through look to your Rich Edit control.

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);
}

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);

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;
}

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;
}

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);

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));

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);

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, <BR>                                (LPARAM) &point);
    fr.chrg.cpMax = -1;
    //Requesting to draw on the DC
    lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) TRUE, <BR>                           (LPARAM) &fr);  
    lResult = SendMessage( m_hWnd, EM_FORMATRANGE, (WPARAM) FALSE, <BR>                           (LPARAM) NULL);
    BitBlt (hStretchedMem, m_RichEditRect.left + 1, m_RichEditRect.top + 1,<BR>        m_RichEditRect.right - m_RichEditRect.left, <BR>        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

Share

About the Author

Amro Ibrahim
Software Developer
United States United States
I love coding with C++. I always split my free time between coding and gaming Smile | :)
 
Linkedin

Comments and Discussions

 
GeneralThe method I use. PinmemberRandor7-Dec-05 14:14 
GeneralRe: The method I use. PinmemberReDFoX12-Dec-05 3:24 
Generalgreat work Pinmemberkvrnkiran1-Sep-05 4:50 
GeneralSlow control Pinmember_Stilgar_27-Aug-05 11:07 
GeneralRe: Slow control PinsussAnonymous27-Aug-05 11:28 
GeneralRe: Slow control PinmemberAmro Fawzy6-Aug-06 21:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411028.1 | Last Updated 8 Aug 2005
Article Copyright 2005 by Amro Ibrahim
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid