GDI+中的非缩放笔

4

我需要创建一支笔,无论图形转换矩阵的比例如何,都能以0.5毫米的宽度绘制。这是我的做法:

注意:示例代码为C++/CLI,但使用C#回答也可以。

// assume that g is a Graphics object
int dpi = g->DpiX;
float dotsPerHalfInch = dpi * 0.5;

// to extract scale factor from the transformation matrix...
// create two points distant one unit apart...
array<PointF> ^points = gcnew array<PointF>{
    PointF(0.0f, 0.0f), PointF(1.0f, 0.0f)
};

// transform them...
g->Transform->TransformPoints(points);

// get distance after transformation...
float dX = points[1].X - points[0].X;
float dY = points[1].Y - points[0].Y;
float distance = Math::Sqrt(dX * dX + dY * dY);

// reverse the effects of any scale factor in graphics transform
float penWidth = dotsPerHalfInch / distance;

Pen ^halfInchPen = gcnew Pen(Color::Black, penWidth);

在屏幕上(96 dpi)似乎不起作用...给我一支像素宽的笔。在 PDF 打印机(600 dpi)上,它给了我一支比半英寸更粗的笔。

我做错了什么?在 GDI 中创建非缩放笔的正确方法是什么?


标签C#不正确,它看起来像C++。 - Jehof
这是C++/CLI... 但欢迎使用C#进行回答。 - Agnel Kurian
3个回答

7
笔本身具有“Transform”属性。将其与图形对象上的全局缩放变换的逆变换一起使用。将笔宽度设置为任意常数。
另外,gdi+中存在一个bug,使得宽度小于1.5的笔无法进行缩放。
好的链接:https://web.archive.org/web/20131221083258/http://bobpowell.net/scalepens.aspx (此外,图形对象上还有一个“PageUnit”属性,可以在像素、毫米等之间进行切换。不知道这是否有帮助)

1

我知道这是一个非常古老的帖子,但是我发现了一些有关缩放笔宽的有趣内容,因为我正在尝试做到这一点。

也许是因为我正在使用 .Net Core 3?无论如何,我对控件进行了 ScaleTransform 和 TranslateTransform 的操作,以便可以按不同比例绘制线条。目前为止还不错。但是,正如大多数人所知道的那样,绘制的线宽也会被缩放,并且通常是一个不良影响 - 线条太粗。

为了保持线条在1像素,我看到以下解决方案(即在笔构造函数中将宽度参数添加0f:

            Pen penBlack0 = new Pen(Color.Black, 0f);
            sg.Graphics.DrawLine(penBlack0, 10, 20, 100, 50);

但这并没有什么区别。划线仍然太粗。此外,如果您在调试器中查看,笔的宽度属性为1,而不是零。然而,如果我这样做...

            Pen penBlack0 = new Pen(Color.Black);
            penBlack0.Width = 0f;
            sg.Graphics.DrawLine(penBlack0, 10, 20, 100, 50);

结果是正确的绘制了1像素线宽。

我不确定这样做的区别在哪里,或者为什么构造函数中没有将Width属性设置为0f。

无论如何,那就是我克服这个障碍的方法。


这需要在正确的答案中。它已经在.NET Framework 4.8中确认工作,因此如果您不在笔的构造函数中声明它,那么它将起作用,然后将使变换与笔的宽度无关。 - mslugx

0
太棒了。我们遇到了同样的问题,当在构造函数中使用0f时,一切正常,但在某些Windows更新后,笔开始使用缩放因子,导致线条变粗。在构造函数之外设置笔宽度-解决了这个问题。

这并没有真正回答问题。如果您有不同的问题,可以通过点击提问来提出。如果您想在此问题获得新的答案时得到通知,您可以关注此问题。一旦您拥有足够的声望,您还可以添加悬赏以吸引更多关注。- 来自审核 - AndrewSilver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接