【问题标题】:How can I draw something in my subclassed controls paint method on top of the default paint outcome?如何在我的子类控件中在默认绘制结果之上绘制一些东西?
【发布时间】:2017-06-29 18:50:17
【问题描述】:

我目前正在尝试在我的应用程序中对CRichEditCtrl 进行子类化。这是子类:

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-method 中绘制我要求的东西。

我仍然想要通常的绘画程序,但我只是想在之后“在上面”添加一些东西。

有没有办法做到这一点?也许我可以将PAINTSTRUCT 传递给基本方法?

提前致谢

【问题讨论】:

  • 可能的选项:在子类处理程序中处理WM_PAINT,方法是重构您需要的PAINTSTRUCT 的部分,然后调用超类的OnPaint()(我不确定如何使用ATL/WTL,抱歉),然后使用GetDC() 进行额外的绘图?对于PAINTSTRUCT的字段,hdc来自GetDC()rcPaint来自GetUpdateRect()。这不应该有任何不良影响,除非EndPaint() 正在做一些魔术(除了删除更新矩形)...?可能有一种方法可以连接到我不知道的 WTL;如果没有,这将是纯 Win32 的最后手段。
  • 也不确定是否应该在超类处理程序运行之前调用GetDC(),正如我的评论所暗示的那样。我个人不会,但是...

标签: c++ winapi atl wtl


【解决方案1】:

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

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

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

  1. 提供您自己的WM_PAINT 处理程序
  2. 调用DefWindowProc让控件使用自己的BeginPaintEndPaint进行标准绘画
  3. 然后通过使用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;
}

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多