如何在默认绘制结果之上的子类控件绘制方法中绘制某些内容?

How can I draw something in my subclassed controls paint method on top of the default paint outcome?

我目前正在尝试在我的应用程序中 class 一个 CRichEditCtrl。这是子class 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);
};

我的绘画方法是这样的:

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

这确实绘制了我想要的多边形,但这也是它唯一绘制的东西。我很确定为什么会这样。我正在接受 Paint 消息,我正在处理它,然后它就完成了。例如,我没有执行将背景涂成白色的默认例程。

然而,我实际上想要这样:

  1. 执行默认绘制例程,如果我不指定自定义绘制例程,就会发生这种情况
  2. FileEdit::OnPaint方法绘制我要求的东西。

我还是想要平时的绘画套路,但我只是想在之后添加一些东西"on top"。

有什么办法可以实现吗?也许我可以将 PAINTSTRUCT 传递给基本方法?

提前致谢

自定义 WM_PAINT 处理程序的最干净的方法是找到一种方法将您的代码插入 BeginPaintEndPaint 对的中间。标准控制处理程序有自己的调用,因此最好在存在此类机会时在这些调用之间进行回调。例如,listview 和 treeview 等常用控件通过发送 NM_CUSTOMDRAW 通知来提供此机会,但是编辑控件并不那么灵活。

当然,如果您完全处理绘画,任务会容易得多,在这种情况下,您只需自己处理消息,而无需过多考虑标准处理程序。

一个运行良好的edit-specific解决方案(意味着它与标准控件实现兼容,对于其他控件不一定如此;它也适用于简单的编辑控件,而不是丰富的编辑控件)是:

  1. 提供您自己的 WM_PAINT 处理程序
  2. 调用DefWindowProc让控件用自己的BeginPaintEndPaint
  3. 做标准绘画
  4. 然后在您的处理程序中继续使用 GetDCReleaseDC(而不是 BeginPaintEndPaint)获取 HDC 并更新获得的 DC与您的自定义。

子类编辑控件的 WTL 处理程序可能如下所示:

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

另请参阅: