如何在默认绘制结果之上的子类控件绘制方法中绘制某些内容?
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 消息,我正在处理它,然后它就完成了。例如,我没有执行将背景涂成白色的默认例程。
然而,我实际上想要这样:
- 执行默认绘制例程,如果我不指定自定义绘制例程,就会发生这种情况
- 用
FileEdit::OnPaint
方法绘制我要求的东西。
我还是想要平时的绘画套路,但我只是想在之后添加一些东西"on top"。
有什么办法可以实现吗?也许我可以将 PAINTSTRUCT
传递给基本方法?
提前致谢
自定义 WM_PAINT
处理程序的最干净的方法是找到一种方法将您的代码插入 BeginPaint
和 EndPaint
对的中间。标准控制处理程序有自己的调用,因此最好在存在此类机会时在这些调用之间进行回调。例如,listview 和 treeview 等常用控件通过发送 NM_CUSTOMDRAW
通知来提供此机会,但是编辑控件并不那么灵活。
当然,如果您完全处理绘画,任务会容易得多,在这种情况下,您只需自己处理消息,而无需过多考虑标准处理程序。
一个运行良好的edit-specific解决方案(意味着它与标准控件实现兼容,对于其他控件不一定如此;它也适用于简单的编辑控件,而不是丰富的编辑控件)是:
- 提供您自己的
WM_PAINT
处理程序
- 调用
DefWindowProc
让控件用自己的BeginPaint
和EndPaint
做标准绘画
- 然后在您的处理程序中继续使用
GetDC
和 ReleaseDC
(而不是 BeginPaint
和 EndPaint
)获取 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;
}
另请参阅:
- Win32: How to custom draw an Edit control?
- Custom edit control in WTL doing painting completely without calling
DefWindowProc
我目前正在尝试在我的应用程序中 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 消息,我正在处理它,然后它就完成了。例如,我没有执行将背景涂成白色的默认例程。
然而,我实际上想要这样:
- 执行默认绘制例程,如果我不指定自定义绘制例程,就会发生这种情况
- 用
FileEdit::OnPaint
方法绘制我要求的东西。
我还是想要平时的绘画套路,但我只是想在之后添加一些东西"on top"。
有什么办法可以实现吗?也许我可以将 PAINTSTRUCT
传递给基本方法?
提前致谢
自定义 WM_PAINT
处理程序的最干净的方法是找到一种方法将您的代码插入 BeginPaint
和 EndPaint
对的中间。标准控制处理程序有自己的调用,因此最好在存在此类机会时在这些调用之间进行回调。例如,listview 和 treeview 等常用控件通过发送 NM_CUSTOMDRAW
通知来提供此机会,但是编辑控件并不那么灵活。
当然,如果您完全处理绘画,任务会容易得多,在这种情况下,您只需自己处理消息,而无需过多考虑标准处理程序。
一个运行良好的edit-specific解决方案(意味着它与标准控件实现兼容,对于其他控件不一定如此;它也适用于简单的编辑控件,而不是丰富的编辑控件)是:
- 提供您自己的
WM_PAINT
处理程序 - 调用
DefWindowProc
让控件用自己的BeginPaint
和EndPaint
做标准绘画
- 然后在您的处理程序中继续使用
GetDC
和ReleaseDC
(而不是BeginPaint
和EndPaint
)获取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;
}
另请参阅:
- Win32: How to custom draw an Edit control?
- Custom edit control in WTL doing painting completely without calling
DefWindowProc