FillRectangle和DrawRectangle的像素行为

Mar*_*ner 14 .net gdi+

几乎每次我使用Graphics.DrawRectangleGraphics.FillRectangle(int版本)我似乎都会错过我想要绘制的矩形的右边和右边的像素.

什么是哪些像素被填充的确切定义

Graphics.FillRectangle(brush,x,y,width,height)
Run Code Online (Sandbox Code Playgroud)

Graphics.DrawRectangle(pen,x,y,width,height) // pen is one pixel width, i.e. width=0f
Run Code Online (Sandbox Code Playgroud)

对它有合理的解释吗?(所以我终于可以记住行为:) ...)

编辑:

使用Oleg Zhuk奇妙的Try GDI +应用程序,我能够找到FillRectangle和之间的奇怪区别DrawRectangle:

FillRectangle(brush,0,0,1,1) 在(0,0)绘制一个点,这在某种程度上是可以理解的(它毕竟是一个宽度和高度的矩形).

DrawRectangle(pen,0,0,1,1) 另一方面,绘制一个2×2像素的小矩形.

对于其他宽度/高度组合显示相同的行为,DrawRectangle总是向左和向下延伸一个像素(这有点烦人,例如当使用ClientRectangle属性在控件周围绘制框架时)

我的第一个问题解决了(他们如何表现......)仍然存在第二个问题:为什么他们这样做?

Lib*_*bor 8

这些方法可以正常工作,您只需要考虑抗锯齿和舍入的效果.

首先,打开消除锯齿功能以查看所有内容(不仅仅是舍入结果):

graphics.SmoothingMode = SmoothingMode.AntiAlias;
Run Code Online (Sandbox Code Playgroud)

现在FillRectangle(10,10,10,10)将产生模糊的结果,DrawRectangle(10,10,10,10)将是锐利的.

模糊的结果意味着你有离网的像素坐标.如果你需要打电话:

graphics.FillRectangle(9.5f, 9.5f, 10, 10);
Run Code Online (Sandbox Code Playgroud)

在网格上对齐矩形的左上角.

DrawRectangle很清晰,因为它使用宽度为1.0的Pen.因此,线从像素中心开始,在两个方向上都是0.5像素,因此恰好填充1个像素.

请注意,宽度和高度以这种方式计算:

width = (right - left) = 19.5 - 9.5 = 10
height = (bottom - top) = ...
Run Code Online (Sandbox Code Playgroud)

请注意,19.5是矩形的右/底坐标,也在网格上对齐,结果是整数.

您可以使用不同的公式:

width2 = (right - left + 1)
Run Code Online (Sandbox Code Playgroud)

但这仅适用于圆角坐标,因为最小单位为1像素.当使用使用抗锯齿的GDI +时,请注意这个点的大小为零并位于像素的中心(它不是整个像素).

  • 抗锯齿并不重要.真正的原因在这里描述:http://social.msdn.microsoft.com/Forums/en-US/a170efaf-829a-4cf1-b854-351938be24ae/drawrectangle-method-creates-oversize-rectangle?forum=vblanguage (5认同)