1

I am currently trying to subclass a CRichEditCtrl in my application. This is the subclass class:

class FileEdit : public CWindowImpl<FileEdit, CRichEditCtrl>
{
    DECLARE_WND_CLASS(L"FileEdit");
public:
    BEGIN_MSG_MAP_EX(FileEdit)
        MSG_WM_PAINT(OnPaint)
        MSG_WM_LBUTTONUP(OnLButtonUp)
    END_MSG_MAP()

    bool Init();

private:
    void OnPaint(CDCHandle dc);
    void OnLButtonUp(UINT nFlags, CPoint point);
};

My paint method looks like this:

void FileEdit::OnPaint(CDCHandle dc)
{
    PAINTSTRUCT ps;
    if (!dc)
    {
        dc = BeginPaint(&ps);
    }
    POINT p[2];
    p[0].x = 1;
    p[0].y = 1;

    p[1].x = 5;
    p[1].y = 5;
    Polygon(dc, p, 2);

    EndPaint(&ps);
}

This does indeed draw the polygon I want, but that is the only thing it does paint, as well. I am pretty sure why this is happening. I am accepting the Paint message, I am handling it, and then it is done. I don't go through the default routine which would paint the background white for example.

However, I would actually like to have it like this:

  1. Go through the default paint routine, which would happen, if I don't specify a custom paint routine
  2. Paint the things I request in FileEdit::OnPaint-method.

I still want the usual paint routine, but I just want to add a few things "on top" afterwards.

Is there any way to accomplish this? Maybe I could pass the PAINTSTRUCT to a base method?

Thanks in advance

Sossenbinder
  • 4,852
  • 5
  • 35
  • 78
  • Possible option: handle `WM_PAINT` in your subclass handler by reconstructing the parts of the `PAINTSTRUCT` you need, then calling the superclass's `OnPaint()` (I'm not sure how with ATL/WTL, sorry), and then using `GetDC()` to do the extra drawing? For the fields of `PAINTSTRUCT`, `hdc` comes from `GetDC()` and `rcPaint` comes from `GetUpdateRect()`. This *shouldn't* have any ill effects, unless `EndPaint()` is doing some magic (other than removing the update rect)...? There's probably a way to hook into WTL that I don't know about; if there isn't, this would be a pure Win32 last resort. – andlabs Feb 12 '17 at 04:36
  • Also not sure if you should call `GetDC()` before the superclass handler runs, as my comment seems to suggest. I wouldn't personally, but... – andlabs Feb 12 '17 at 04:41

1 Answers1

1

The cleanest way to customize WM_PAINT handler is to find a way to insert your code in the middle of BeginPaint and EndPaint pair. Standard control handler has its own calls so it would be the best to get called back between those, when such opportunity exists. For example, common controls such as listview and treeview do provide this opportunity by sending NM_CUSTOMDRAW notification, however edit control is not that flexible.

The task is, of course, much easier if you handle the painting completely, in which case you just handle the message yourself without thinking too much about standard handler.

An edit-specific solution which works well (meaning that it is compatible with standard control implementation, which is not necessarily true for other controls; it is also for simple edit control, not rich edit control) is to:

  1. Provide your own WM_PAINT handler
  2. Call DefWindowProc to let the control do standard painting with its own BeginPaint and EndPaint
  3. Then continue in your handler by getting HDC using GetDC and ReleaseDC (as opposed to BeginPaint and EndPaint) and updating the obtained DC with your customizations.

A WTL handler of subclasses edit control might look like:

LRESULT OnPaint(CDCHandle)
{
    if(!(GetStyle() & ES_READONLY)) // Just an example how to make custom draw optional
    {
        DefWindowProc();
        CClientDC Dc(m_hWnd);
        // TODO: Paint using Dc
    } else
        SetMsgHandled(FALSE);
    return 0;
}

See also:

Community
  • 1
  • 1
Roman R.
  • 68,205
  • 6
  • 94
  • 158