如何在OnPaint()事件中获取需要绘制的确切区域?

时间:2013-01-17 15:38:14

标签: c# winforms gdi+ paint

WinForm应用程序中,订阅OnPaint()个活动时,PaintEventArgs会提供一个ClipRectangle属性,用于定义要绘制的区域。

当表格垂直或水平调整大小时,它会给出最小的矩形。

enter image description here

但是当窗口在两个方向上调整大小时,需要绘制几个区域(一个在右侧,一个在底部)和OnPaint事件合并它们。它产生一个与Form大小相同的矩形(因此一切都是重绘的)。我想要的是单独的区域(图片上的两个矩形)

enter image description here

我知道GDI+自动剪辑不需要绘制的内容(事物在两个矩形之外,而不仅仅是ClipRectangle),但我想最小化GDI+个调用最多(由于许多OnPaint调用,我在GDI+事件中绘制时已经出现性能问题,这不是过早的优化)

1 个答案:

答案 0 :(得分:3)

Windows中的绘制由WM_PAINT消息处理程序启动。它必须调用BeginPaint()来获取有关需要绘制的内容的信息。它返回一个PAINTSTRUCT类型的结构,它看起来像这样:

typedef struct tagPAINTSTRUCT {
  HDC  hdc;
  BOOL fErase;
  RECT rcPaint;              // <=== here
  BOOL fRestore;
  BOOL fIncUpdate;
  BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;

rcPaint成员是您从Graphics.ClipRectangle获得的成员。 Graphics.Clip和Graphics.ClipBounds属性不相关,只有在您通过指定Clip属性故意剪辑自己时它们才有效。

显然,Windows本身并不能让你找到你要求的东西。 rcPaint是一个简单的矩形RECT。 Windows仅跟踪脏矩形,而不是区域。 InvalidateRect()添加的新矩形与现有的矩形合并,你很容易就会得到整个客户区。

解决此问题的唯一合理方法是注意ResizeBegin和ResizeEnd事件。当您获得ResizeBegin时,您就会知道用户正在拖动窗口边缘或角落。你可以用来优化绘画的知识,跳过昂贵的部分,使模态调整大小循环工作不佳。