今更ながらWPFに置き換えてみる(10)


ボケ問題再び

セッティング項目を展開表示する際の小さな三角形。
元のForms版では 16×16ピクセルのBMPを2つ作ってON/OFFでスイッチしてpictureBoxに表示してました。画面解像度比が1の場合は画面ピクセルが画像の画素と一致するので、当然ボケない。

今回解像度に応じてコントロールの物理ピクセルサイズが自動で変わるため、元画像が16ピクセルの固定サイズで作成してあると拡大時にどうしてもぼけて表示されます(以前のnotifyIconの時と同じ問題)。
じゃ、どうすればいいの?ってことになりますが思いつくのは論理サイズ16×16ピクセルのcanvasを作成してそこにDrawするくらいしか思いつきません。試しに実装してIMAGEとCANVASを画面上で並べてみると

左がBITMAPをimagesource変換してImageに張り付けたもの。右がCanvasを作成してPolygonで描画したもの。パっと見わからないので拡大。はい当然20*20ピクセルになってますね。

ほかの個所でも同じことをするのでcanvasと状態を引数にして分離

 private void DrawArrowBox(Canvas aCanvas , int sw)
        {

            aCanvas.Children.Clear();

            //外枠
            Rectangle myRectangle = new Rectangle();
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();
            mySolidColorBrush.Color = Color.FromArgb(255, 150, 150, 150);
            myRectangle.Fill = mySolidColorBrush;
            myRectangle.StrokeThickness = 1 / 1.25;    //ここは解像度に変更
            myRectangle.Stroke = Brushes.White;
            myRectangle.Width = aCanvas.Width;
            myRectangle.Height = aCanvas.Height;
            aCanvas.Children.Add(myRectangle);

            //三角形
            Polygon myPolygon = new Polygon();
            SolidColorBrush myPolyColorBrush = new SolidColorBrush();

            if (sw == 1)
            {
                System.Windows.Point Point1 = new System.Windows.Point(aCanvas.Width * 2 / 10, aCanvas.Height * 1 / 3);
                System.Windows.Point Point2 = new System.Windows.Point(aCanvas.Width * 8 / 10, aCanvas.Height * 1 / 3);
                System.Windows.Point Point3 = new System.Windows.Point(aCanvas.Width * 1 / 2, aCanvas.Height * 2 / 3);
                System.Windows.Point Point4 = new System.Windows.Point(aCanvas.Width * 2 / 10, aCanvas.Height * 1 / 3);
                PointCollection polygonPoints = new PointCollection();
                polygonPoints.Add(Point1);
                polygonPoints.Add(Point2);
                polygonPoints.Add(Point3);
                polygonPoints.Add(Point4);
                myPolygon.Points = polygonPoints;
                myPolyColorBrush.Color = Color.FromArgb(255, 150, 150, 150);
            }
            else
            {
                System.Windows.Point Point1 = new System.Windows.Point(CanvasSettings.Width * 1 / 3, CanvasSettings.Height - CanvasSettings.Height * 8 / 10);
                System.Windows.Point Point2 = new System.Windows.Point(CanvasSettings.Width * 1 / 3, CanvasSettings.Height - CanvasSettings.Height * 2 / 10);
                System.Windows.Point Point3 = new System.Windows.Point(CanvasSettings.Width - CanvasSettings.Width * 1 / 3, CanvasSettings.Height * 1 / 2);
                System.Windows.Point Point4 = new System.Windows.Point(CanvasSettings.Width * 1 / 3, CanvasSettings.Height - CanvasSettings.Height * 8 / 10);
                PointCollection polygonPoints = new PointCollection();
                polygonPoints.Add(Point1);
                polygonPoints.Add(Point2);
                polygonPoints.Add(Point3);
                polygonPoints.Add(Point4);
                myPolygon.Points = polygonPoints;
                myPolyColorBrush.Color = Color.FromArgb(255, 255, 255, 255);
            }
            myPolygon.Stroke = Brushes.White;
            myPolygon.StrokeThickness = 1 / 1.25;    //ここは解像度に変更
            myPolygon.Fill = myPolyColorBrush;
            aCanvas.Children.Add(myPolygon);
        }

当初元のCanvasを1回描画して、on/off切り替えの際はrotatetransformさせればいいかな、と思ってましたが、回転の中心点の指定方法がいまいちわからず。
結局poly内のヌキを変えるんで再描画してしまえと、記述としてはしつこいものになっています。

設定画面切り替え。便利すぎ

以前悩んでいた設定部の表示非表示ですが、StackPanelを構成の上位に配置して、その下にそれぞれのコントロールグループでGridを並べ、visibilityで表示非表示を切り替え。StackPanelにしておくことで中間のGridをCollapsedにした場合、流し込まれて下のGridが上がってくれるので、面倒な位置操作は不要。
メインのWindowのHeightに対象のGridのHeightを加減することで希望の表現ができました。