C# .Net DrawString字体引用在调用

C# .Net DrawString字体引用在调用,c#,.net,graphics,onpaint,drawstring,C#,.net,Graphics,Onpaint,Drawstring,给定以下代码。第一个DrawString方法是否有可能使用Arial而不是Times New Roman protected override void OnPaint(PaintEventArgs pe) { Font f = new Font("Times New Roman", this.TextSize); pe.Graphics.DrawString("Test 1", f, Brushes.Black, loc); f = new Font("Arial",

给定以下代码。第一个DrawString方法是否有可能使用Arial而不是Times New Roman

protected override void  OnPaint(PaintEventArgs pe)
{
    Font f = new Font("Times New Roman", this.TextSize);
    pe.Graphics.DrawString("Test 1", f, Brushes.Black, loc);
    f = new Font("Arial", this.TextSize);
    pe.Graphics.DrawString("Test 2", f, Brushes.Black, loc);
}
我有一个问题,这段代码基本上是断断续续地以错误的字体绘制第一个字符串。我已经将代码更改为有两个静态字体引用,但是由于我无法重现代码,我无法确定是否修复了问题

注意:loc是一个会被实际代码改变的位置,为了简化,我在这里删去了一些代码

这是我的修正的整个方法。如果你看不出它有什么问题-我会去责备宇宙射线或其他东西

protected override void  OnPaint(PaintEventArgs pe)
{
       base.OnPaint(pe);
        if (bcf == null)
        {
            FontFamily[] families = pfc.Families;
            foreach (FontFamily ff in families)
            {
                if (ff.Name.Equals("Free 3 of 9"))
                {
                    bcf = ff;
                }
            }
        }
        if (bcf != null)
        {
            Font f = new Font(bcf, this.BarcodeSize);
            SizeF s = TextRenderer.MeasureText(barcodeValue, f);
            Rectangle r = pe.ClipRectangle;
            Point loc = new Point(0, 0);
            if (s.Width < r.Width)
            {
                loc.X = (int)Math.Ceiling((r.Width - s.Width) / 2);
            }
            pe.Graphics.DrawString(barcodeValue, f, Brushes.Black, loc);

            float barcodeBottom = s.Height + 5;

            Font fp = new Font("Arial", this.TextSize);
            s = TextRenderer.MeasureText(barcodeValue, fp);
            r = pe.ClipRectangle;
            loc = new Point(0, (int)Math.Ceiling(barcodeBottom));
            if (s.Width < r.Width)
            {
                loc.X = (int)Math.Ceiling((r.Width - s.Width) / 2);
            }
            if (s.Height + loc.Y > r.Height)
            {
                loc.Y = (int)Math.Ceiling(r.Height - (s.Height));
            }
            pe.Graphics.FillRectangle(Brushes.White, new Rectangle(loc, new Size((int)Math.Ceiling(s.Width), (int)Math.Ceiling(s.Height))));
            pe.Graphics.DrawString(barcodeValue, fp, Brushes.Black, loc);
        }
    }
修复的代码现在如下所示。现在GDI呼叫减少了很多:

protected override void  OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
        if (bcf != null)
        {
            Rectangle r = pe.ClipRectangle;
            Point loc = new Point(0, 0);
            if (barcodeDimensions.Width < r.Width)
            {
                loc.X = (int)Math.Ceiling((r.Width - barcodeDimensions.Width) / 2);
            }
            pe.Graphics.DrawString(barcodeValue, barcodeFont, Brushes.Black, loc);

            float barcodeBottom = barcodeDimensions.Height + 5;

            r = pe.ClipRectangle;
            loc = new Point(0, (int)Math.Ceiling(barcodeBottom));
            if (plaintextDimensions.Width < r.Width)
            {
                loc.X = (int)Math.Ceiling((r.Width - plaintextDimensions.Width) / 2);
            }
            if (plaintextDimensions.Height + loc.Y > r.Height)
            {
                loc.Y = (int)Math.Ceiling(r.Height - (plaintextDimensions.Height));
            }
            pe.Graphics.FillRectangle(Brushes.White, new Rectangle(loc, new Size((int)Math.Ceiling(plaintextDimensions.Width), (int)Math.Ceiling(plaintextDimensions.Height))));
            pe.Graphics.DrawString(barcodeValue, plaintextFont, Brushes.Black, loc);
        }
    }

如果我打算让它更优化,我会将矩形测量部分置于OnResize的覆盖中,但我认为现在就可以了…

不,我看不出会发生什么情况-这不像第一次调用知道变量f-它只知道调用DrawString时它的值。字体引用的参数是按值传递的,而不是按引用传递的

我所能想象的导致问题的唯一方法是,如果图形对象记住其当前字体,并在调用DrawString时重置它,但延迟实际绘制。那会有各种各样的恶果——我看不到它会发生


基本上,就DrawString调用而言,就好像使用了两个不同的变量。

不,我看不出会发生什么情况-这不像第一次调用知道变量f-它只知道调用DrawString时的值。字体引用的参数是按值传递的,而不是按引用传递的

我所能想象的导致问题的唯一方法是,如果图形对象记住其当前字体,并在调用DrawString时重置它,但延迟实际绘制。那会有各种各样的恶果——我看不到它会发生


基本上,就DrawString调用而言,就好像使用了两个不同的变量。

Skeet涵盖了基本情况。我做过很多GDI+,但我从未见过你描述的行为。很可能是由于本代码未显示的其他影响。

双向飞碟涵盖了基本情况。我做过很多GDI+,但我从未见过你描述的行为。很可能是由于此代码未显示的其他影响。

无法查看所提供代码的任何问题。在您的完整代码中,图形位置是否可能不正确


您是否100%确定在Arial中呈现的字符串值只能通过使用TNR字体调用DrawString来呈现?

所提供的代码没有任何问题。在您的完整代码中,图形位置是否可能不正确


您是否100%确定在Arial中呈现的字符串值只能通过使用TNR字体调用DrawString来呈现?

是的,当您的程序接近使用10000个GDI句柄时,奇怪的事情开始发生。它几乎肯定会影响Windows字体映射程序,而不一定引发异常。您的程序正在玩俄罗斯轮盘赌,因为您没有调用您使用的字体的Dispose。如果垃圾收集器没有足够频繁地运行,那么你很可能会让那把枪熄火。你需要这样写:

using (Font fp = new Font("Arial", this.TextSize)) {
    // etc..
}

还要注意代码中的另一个错误,您使用的是TextRenderer.MeasureText,但使用Graphics.DrawString绘制。测量结果不一致。您必须使用Graphics.MeasureString。

是的,当您的程序接近消耗10000个GDI句柄时,奇怪的事情开始发生。它几乎肯定会影响Windows字体映射程序,而不一定引发异常。您的程序正在玩俄罗斯轮盘赌,因为您没有调用您使用的字体的Dispose。如果垃圾收集器没有足够频繁地运行,那么你很可能会让那把枪熄火。你需要这样写:

using (Font fp = new Font("Arial", this.TextSize)) {
    // etc..
}

还要注意代码中的另一个错误,您使用的是TextRenderer.MeasureText,但使用Graphics.DrawString绘制。测量结果不一致。必须使用Graphics.MeasureString.

是-实际代码中唯一更复杂的是第一种字体来自PrivateFontCollection。我在集合中迭代查找具有特定名称的FontFamily,然后在特定位置呈现文本。。。。我将编辑这个问题,并将整个方法以及简单的版本放在那里以防万一…是的-实际代码中唯一更复杂的是第一个字体来自PrivateFontCollection。我遍历集合,查找具有特定名称的FontFamily,然后在特定位置呈现文本。。。
. 我将编辑这个问题,并将整个方法以及简单的版本放在那里以防万一…我想了很多,只是以前在GDI+中没有做很多,并且不确定这里是否发生了疯狂的事情…@Matt-这是很有可能的。我想了很多,只是之前在GDI+中没有做太多,也不确定这里是否发生了疯狂的事情…@Matt-这是很有可能的。我认为无论如何都不应该用OnPaint方法来完成。我正在对整个过程进行重构,以便只在setter中为渲染的文本设置字体、大小和位置。我认为无论如何都不应该在OnPaint方法中完成。我正在对整个过程进行重构,以便只为呈现的文本设置setter中的字体、大小和位置。