1

次のコードが与えられます。Times New RomanではなくArialで最初のDrawStringメソッドを描画する可能性はありますか?

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);
}

基本的に、このコードが断続的に最初の文字列を間違ったフォントで描画しているという問題があります。コードを2つの静的フォント参照を持つように変更しましたが、コードを再現できなかったため、問題が修正されたかどうかがわかりません。

注: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のオーバーライドに配置しますが、今のところこれでうまくいくと思います...

4

4 に答える 4

2

いいえ、それがどのように発生するかはわかりません。最初の呼び出しが変数について知っているわけではありません。呼び出さfれたときの値しか知りませんDrawString。引数(Font参照)は、参照ではなく値によって渡されます。

これが問題を引き起こすと私が想像できる唯一の方法は、Graphicsオブジェクトがその「現在の」フォントを記憶している(そしてへの呼び出しでそれをリセットするDrawString)が、実際の描画を延期する場合です。それはあらゆる種類の厄介な影響をもたらすでしょう-私はそれが起こっているのを見ることができません。

基本的に、DrawString呼び出しに関する限り、2つの異なる変数を使用しているかのようになります。

于 2010-09-28T15:30:38.693 に答える
2

はい、プログラムが10,000 GDIハンドルを消費しそうになると、奇妙なことが起こり始めます。必ずしも例外をスローすることなく、ほぼ確実にWindowsフォントマッパーに影響します。使用するフォントでDispose()を呼び出していないため、プログラムはこの潜在的な問題でロシアンルーレットを再生しています。ガベージコレクターが十分な頻度で実行されない場合は、その銃を停止させる可能性があります。あなたはそれをこのように書く必要があります:

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

また、コードの別のバグにも注意してください。TextRenderer.MeasureTextを使用していますが、Graphics.DrawStringを使用して描画しています。測定値は同じではありません。Graphics.MeasureStringを使用する必要があります。

于 2010-09-28T16:04:34.940 に答える
0

スキートがベースケースを覆った。私は多くのGDI+を実行しましたが、あなたが説明する動作を見たことがありません。ほとんどの場合、このコードでは示されていない他の影響が原因です。

于 2010-09-28T15:33:25.833 に答える
0

提供されたコードに問題はありません。完全なコードで、描画位置が正しくない可能性はありますか?

Arialでレンダリングされる文字列値は、TNRフォントを使用したDrawStringの呼び出しによってのみレンダリングできる可能性があることを100%確信していますか?

于 2010-09-28T15:39:02.957 に答える