1

スクロール可能な領域に何千ものグラフィック プリミティブを視覚化するカスタム WPF コントロールに取り組んでいます。コントロールのテンプレートのコア部分は次のとおりです。

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:ItemVisualizer}">
            <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">

                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <local:ItemAreaElement Grid.Row="0" Grid.Column="0" x:Name="PART_ItemArea" />
                    <ScrollBar Grid.Row="0" Grid.Column="1" x:Name="PART_ScrollBarVert" Orientation="Vertical" Maximum="100" />
                    <ScrollBar Grid.Row="1" Grid.Column="0" x:Name="PART_ScrollBarHorz" Orientation="Horizontal" Maximum="100" />
                    <Rectangle Grid.Row="1" Grid.Column="1" x:Name="PART_SizeGrip" Focusable="False" Fill="#F0F0F0" />
                </Grid>

            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

パフォーマンスを向上させるために、すべての描画操作は ItemAreaElement の OnRender メソッドで実行されます。鮮明な描画を行うために、初期化コードで次の設定も使用します。

this.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

しかし、私の絵にはいくつかの奇妙な問題があります。それらを示すために、ItemAreaElement の定義を次のように単純化しました。

class ItemAreaElement : FrameworkElement
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);

        const int ITEM_WIDTH = 60;
        const int ITEM_HEIGHT = 20;

        Pen penRed = new Pen(Brushes.Red, 1);
        Pen penGreen = new Pen(Brushes.Green, 1);

        int y = 0;
        for (int iRow = 0; iRow < 3; iRow++)
        {
            int x = 0;
            for (int iCol = 0; iCol < 2; iCol++)
            {
                Point cornerTopLeft = new Point(x, y);
                dc.DrawLine(penRed, cornerTopLeft, new Point(x + ITEM_WIDTH - 1, y));
                dc.DrawLine(penRed, cornerTopLeft, new Point(x, y + ITEM_HEIGHT - 1));

                Point cornerBottomRight = new Point(x + ITEM_WIDTH - 1, y + ITEM_HEIGHT - 1);
                dc.DrawLine(penGreen, new Point(x + ITEM_WIDTH - 1, y), cornerBottomRight);
                dc.DrawLine(penGreen, new Point(x, y + ITEM_HEIGHT - 1), cornerBottomRight);

                x += ITEM_WIDTH;
            }
            y += ITEM_HEIGHT;
        }
    }
}

このコードを 282ppi の Ultra-HD 画面 (システム スケール ファクターは 300%) を備えたメインの開発用ラップトップで起動すると、次の画像が表示されます。

ここに画像の説明を入力

または、グリッド線で paint.net を拡大した後:

ここに画像の説明を入力

ご覧のとおり、ItemAreaElement の左端と上端は、コントロールの境界線で部分的に覆われています。そうでなければなりませんか?これを回避するために使用できる設定はありますか?

2 番目の問題は、開始点を含まない行です (「セル」の左上隅を参照してください)。これは予想される動作ですか?もしそうなら、WPFに強制的に開始ピクセルを描画させる方法は?

3 つ目の問題は、緑色の線が交わる場所またはデバイスに依存しないポイント (セルの右下隅) です。ご覧のとおり、この点はギザギザです。その場所には緑色の四角が見えるだけだと思っていました。DrawingContext.DrawLine メソッドを使用してこれを実装できますか? または、マルチポイント ラインなどに特別な設定を加えた、より複雑なジオメトリを使用する必要がありますか?

ところで、このコードを「クラシック」96 ppi モニターと 100% に設定された OS のスケール ファクターを備えたテスト PC で起動すると、状況は右下隅で少し良くなります。

ここに画像の説明を入力

しかし、一番上の行の赤い横線や最初の列の赤い縦線さえ見えません。そこにそれらが表示されることを期待していましたが、コントロールの境界線で覆われていないことを期待していました. これらの問題をすべて解決する方法を知っている場合は、教えてください。

4

1 に答える 1