2

GDI + DrawLines関数には、次のc#コードを実行することで再現できるクリッピングバグがあります。コードを実行すると、2つのラインパスが表示されます。どちらもクリッピング領域内にあるため、同じである必要があります。ただし、クリッピング領域が設定されている場合、線分の1つは描画されません。

protected override void OnPaint(PaintEventArgs e)
{
   PointF[] points = new PointF[] { new PointF(73.36f, 196), 
             new PointF(75.44f, 32), 
             new PointF(77.52f, 32), 
             new PointF(79.6f, 196), 
             new PointF(85.84f, 196) };

   Rectangle b = new Rectangle(70, 32, 20, 164);         
   e.Graphics.SetClip(b);
   e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
   e.Graphics.TranslateTransform(80, 0);
   e.Graphics.ResetClip();
   e.Graphics.DrawLines(Pens.Red, points);
 }

グラフィックオブジェクトにantialsモードを設定すると、これが解決されます。しかし、それは本当の解決策ではありません。

誰かが回避策を知っていますか?

4

3 に答える 3

3

これは既知のバグのようです...

次のコードは、要求どおりに機能しているように見えます。

protected override void OnPaint(PaintEventArgs e)
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        e.Graphics.SmoothingMode =  System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        Rectangle b = new Rectangle(70, 32, 20, 165);
        e.Graphics.SetClip(b);
        e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
        e.Graphics.TranslateTransform(80, 0);
        e.Graphics.ResetClip();           
        e.Graphics.DrawLines(Pens.Red, points);
    }

注:ラインをアンチエイリアス処理し、クリッピング領域を1つ拡張しました

次の回避策が役立つ可能性があります(テストされていませんが)。

  • ペンの太さは1ピクセルを超えています
  • 線は完全に水平または垂直です
  • クリッピングは、クリップの長方形ではなく、ウィンドウの境界に対して行われます。

以下は、役に立たない可能性のある/または役に立たない可能性のある記事のリストです。

http://www.tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf http://www.tech-archive.net/Archive/Development /microsoft.public.win32.programmer.gdi/2004-08/0368.html

また...

次のことも可能です。

protected override void OnPaint ( PaintEventArgs e )
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        Rectangle b = new Rectangle( 70, 32, 20, 164 );
        Region reg = new Region( b );
        e.Graphics.SetClip( reg, System.Drawing.Drawing2D.CombineMode.Union);
        e.Graphics.DrawLines( Pens.Red, points ); // clipped incorrectly
        e.Graphics.TranslateTransform( 80, 0 );
        e.Graphics.ResetClip();
        e.Graphics.DrawLines( Pens.Red, points );
    }

これは、キャンバス/コントロールのClientRectangleと結合/結合された領域(私は思う)を使用して効果的にクリップします。領域は長方形から区別されるため、結果は期待どおりになるはずです。このコードは、追加することで機能することが証明できます

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

setClip()呼び出しの後。これは、クリップされた領域にのみ表示される黒い長方形を明確に示しています。

回線のアンチエイリアシングがオプションでない場合、これは有効な回避策になる可能性があります。

お役に立てれば

于 2008-08-19T20:43:20.257 に答える
0

コードの問題は何ですか?

OK、問題は...コードがまだしていないことを何をすべきかということです。

コードを実行すると、2 つの赤い「スパイク」が表示されます。

Rectangle の宣言の後に次を追加することによって検証された、クリップされた長方形領域内に最初のスパイクを描画するように見えます。

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

次に、変換を実行し、クリップをリセットします。この時点で、clientRectangle が適切なクリップ領域として使用されていると想定し、変換されたスパイクを再描画しようとします。バグはどこですか?!?

于 2008-08-19T06:52:57.297 に答える
0

バグは、両方の線分が同一に描画される必要があることですが、クリッピング領域内に描画されたスパイクが完全にクリッピング領域内にあり、決してクリップされるべきではないため、そうではありません。これは非常に面倒ですが、ポリゴンにギャップが発生する可能性があるため、ドローラインとクリッピングを多用するソフトウェアはプロらしくないように見えます。

于 2008-08-19T09:17:37.113 に答える