GraphicsPath 和 DrawPath - 删除相交线
GraphicsPath and DrawPath - Removing Intersecting Lines
下面的代码画了一个十字:
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using(GraphicsPath path = new GraphicsPath())
{
path.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
path.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
path.FillMode = FillMode.Winding;
e.Graphics.DrawPath(Pens.DimGray, path);
}
}
我想这样画:
我试过使用 Flatten();
和 CloseAllFigures();
,但它们不起作用。
我正在寻找类似 Union 的效果:
这可以用 GraphicsPath 实现吗?
这是可能的,您所追求的是地区。看看:
我猜你的下一步是勾勒出该地区的轮廓。这是困难的部分,因为没有 API 可以做到这一点。最简单的方法是:
- 用粗笔像第一张图一样画出所有内容。
- 根据路径创建区域并合并结果区域。
- 填充或删除生成的合并区域(为此有 API)。
这将生成您附加的第二张图片。由于缺少边缘检测、轮廓或区域到路径 API 来帮助您绘制结果,因此区域操作需要一点创造力。
我知道这不是一个完美的解决方案,但将其作为一种选择:
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using (GraphicsPath path = new GraphicsPath())
{
var rect1 = new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height - 1);
var rect2 = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width - 1, 40);
path.AddRectangle(rect1);
path.AddRectangle(rect2);
e.Graphics.DrawPath(Pens.DimGray, path);
var bgRect1 = new Rectangle(rect1.X + 1, rect1.Y + 1, rect1.Width - 1, rect1.Height - 1);
var bgRect2 = new Rectangle(rect2.X + 1, rect2.Y + 1, rect2.Width - 1, rect2.Height - 1);
using (GraphicsPath backgroundPath = new GraphicsPath())
{
backgroundPath.AddRectangle(bgRect1);
backgroundPath.AddRectangle(bgRect2);
e.Graphics.FillPath(Brushes.White, backgroundPath);
}
}
}
这是结果:
您将需要为此使用区域,这是根据您现有代码改编的示例。需要注意的是,您还可以对该区域调用 Exclude、Intersect 和 Xor! :)
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath Shape1 = new GraphicsPath();
Shape1.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
GraphicsPath Shape2 = new GraphicsPath();
Shape2.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
Region UnitedRegion = new Region();
UnitedRegion.MakeEmpty();
UnitedRegion.Union(Shape1);
UnitedRegion.Union(Shape2);
e.Graphics.FillRegion(Brushes.Black, UnitedRegion);
}
可以使用Regions.But如果没有其他解决方案,你应该使用APIGDI中的FrameRgn来绘制区域的框架。
Graphics g = e.Graphics;
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
path.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
path.FillMode = FillMode.Winding;
using (Region region = new Region(path))
{
IntPtr reg = region.GetHrgn(g);
IntPtr hdc = g.GetHdc();
IntPtr brushPtr = Win32.GetStockObject(Win32.WHITE_BRUSH);
IntPtr oldbrushPtr = Win32.SelectObject(hdc, brushPtr);
Win32.FrameRgn(hdc, reg, brushPtr, 1, 1);
Win32.DeleteObject(brushPtr);
Win32.SelectObject(hdc, oldbrushPtr);
region.ReleaseHrgn(reg);
g.ReleaseHdc();
}
}
}
下面的代码画了一个十字:
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using(GraphicsPath path = new GraphicsPath())
{
path.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
path.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
path.FillMode = FillMode.Winding;
e.Graphics.DrawPath(Pens.DimGray, path);
}
}
我想这样画:
我试过使用 Flatten();
和 CloseAllFigures();
,但它们不起作用。
我正在寻找类似 Union 的效果:
这可以用 GraphicsPath 实现吗?
这是可能的,您所追求的是地区。看看:
我猜你的下一步是勾勒出该地区的轮廓。这是困难的部分,因为没有 API 可以做到这一点。最简单的方法是:
- 用粗笔像第一张图一样画出所有内容。
- 根据路径创建区域并合并结果区域。
- 填充或删除生成的合并区域(为此有 API)。
这将生成您附加的第二张图片。由于缺少边缘检测、轮廓或区域到路径 API 来帮助您绘制结果,因此区域操作需要一点创造力。
我知道这不是一个完美的解决方案,但将其作为一种选择:
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using (GraphicsPath path = new GraphicsPath())
{
var rect1 = new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height - 1);
var rect2 = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width - 1, 40);
path.AddRectangle(rect1);
path.AddRectangle(rect2);
e.Graphics.DrawPath(Pens.DimGray, path);
var bgRect1 = new Rectangle(rect1.X + 1, rect1.Y + 1, rect1.Width - 1, rect1.Height - 1);
var bgRect2 = new Rectangle(rect2.X + 1, rect2.Y + 1, rect2.Width - 1, rect2.Height - 1);
using (GraphicsPath backgroundPath = new GraphicsPath())
{
backgroundPath.AddRectangle(bgRect1);
backgroundPath.AddRectangle(bgRect2);
e.Graphics.FillPath(Brushes.White, backgroundPath);
}
}
}
这是结果:
您将需要为此使用区域,这是根据您现有代码改编的示例。需要注意的是,您还可以对该区域调用 Exclude、Intersect 和 Xor! :)
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath Shape1 = new GraphicsPath();
Shape1.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
GraphicsPath Shape2 = new GraphicsPath();
Shape2.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
Region UnitedRegion = new Region();
UnitedRegion.MakeEmpty();
UnitedRegion.Union(Shape1);
UnitedRegion.Union(Shape2);
e.Graphics.FillRegion(Brushes.Black, UnitedRegion);
}
可以使用Regions.But如果没有其他解决方案,你应该使用APIGDI中的FrameRgn来绘制区域的框架。
Graphics g = e.Graphics;
using (SolidBrush brush = new SolidBrush(Color.FromArgb(192, 99, 104, 113)))
{
using (GraphicsPath path = new GraphicsPath())
{
path.AddRectangle(new Rectangle(e.ClipRectangle.X + (e.ClipRectangle.Width - 40) / 2, e.ClipRectangle.Y, 40, e.ClipRectangle.Height));
path.AddRectangle(new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y + (e.ClipRectangle.Height - 40) / 2, e.ClipRectangle.Width, 40));
path.FillMode = FillMode.Winding;
using (Region region = new Region(path))
{
IntPtr reg = region.GetHrgn(g);
IntPtr hdc = g.GetHdc();
IntPtr brushPtr = Win32.GetStockObject(Win32.WHITE_BRUSH);
IntPtr oldbrushPtr = Win32.SelectObject(hdc, brushPtr);
Win32.FrameRgn(hdc, reg, brushPtr, 1, 1);
Win32.DeleteObject(brushPtr);
Win32.SelectObject(hdc, oldbrushPtr);
region.ReleaseHrgn(reg);
g.ReleaseHdc();
}
}
}