fc2ブログ

Material Design In XAML Toolkitを使うには

 WPFではControlTemplateをカスタマイズすることでコントロールの見た目を自由に変更できますが、ControlTemplateを自分で書くのはかなり大変です。
 ControlTemplateは書きたくないけどカッコいい見た目にしたいという方は他の人が作ったライブラリを使わせてもらいましょう。
 Material Design In XAML Toolkitを使うことでマテリアルデザインコントロールをXAMLで使用できるようになります。
 Material Design In XAML Toolkitのサイトにある「Clone or download」ボタンからデモアプリのコードをダウンロードできます。
 Material Design In XAML Toolkitを使うには、NuGetでMaterialDesignThemesを検索してインストールしてください。
MaterialDesign NuGet
 次にApp.xamlに4つのリソースディクショナリを追加します。
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>    
</Application.Resources>
 この4つのリソースディクショナリのうち2つ目に指定したMaterialDesignTheme.Defaults.xamlにボタンやチェックボックス等のコントロール定義が含まれています。
 その他の3つはコントロールの色を指定しています。
 一番上のリソースディクショナリはLightとDarkの2種類が用意されています。
 Darkを使用することで背景色が黒くなり、それに合わせて文字色等も変更されます。
 3つめと4つめのリソースディクショナリはコントロールの主要な色とアクセントとして使用する色を指定します。
 どんな色が使えるかはデモアプリのPaletteを参照してください。
 最後にWindowにいくつかのプロパティを設定して終了です。
<Window x:Class="MdDemo1.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:MdDemo1.Views"
        xmlns:vm="clr-namespace:MdDemo1.ViewModels"
        Title="MainWindow" Height="100" Width="280"

        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        TextElement.Foreground="{DynamicResource MaterialDesignBody}"
        TextElement.FontWeight="Regular"
        TextElement.FontSize="13"
        TextOptions.TextFormattingMode="Ideal"
        TextOptions.TextRenderingMode="Auto"
        Background="{DynamicResource MaterialDesignPaper}"
        FontFamily="{DynamicResource MaterialDesignFont}">
    
</Window>
 xmlns:materialDesignからFontFamilyまで(11~18行目)がMaterialDesignToolkitを使用するために追加したプロパティです。
 これでMaterialDesignToolkitを使用する準備が整いました。
 あとは普通にコントロールを配置していくだけです。
 試しに4種類のボタンを設置して実行してみた結果が以下の画像です。
MaterialDesign Light Demo
 MaterialDesignToolkitではApp.xamlで指定したリソースディクショナリを変更することで使用する色を変更できます。
 この画像ではLightテーマでPrimaryにDeepPurpleを、AccentにLimeを使用しています。
 試しにDarkテーマ、PrimaryにIndigoを、AccentにYellowを使用してみると以下の様になります。
MaterialDesign Dark Demo
 色の組み合わせはデモアプリのPalleteで試すことができます。

 とりあえずMaterialDesignToolkitを使用する際に最低限必要なことを説明しました。
 次回からは各種コントロールについて紹介していこうと思っています。  
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

Modelでデータ検証をしてみる

 以前にINotifyDataErrorInfoとSystem.ComponentModel.DataAnnotationsを使ったデータ検証の方法を紹介しましたが、あの時はWPFでデータ検証を行う方法を説明することが目的だったためViewModelでデータ検証を行っていました。(ほかのサイトでもViewModelでやっているのをよく見かけます)
 でもデータ検証はModelで行いたいと思うのが人情(?)です。
 そこでModelでデータ検証をやってみました。
 先ずはデータ検証機能をもったModelと、Modelのデータ検証情報を通知するViewModelを作成します。
 なお、このサンプルコードはLivetを利用しています。
using Livet;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;

namespace ValidationDemo.Models
{
    public class ValidationModel : NotificationObject, INotifyDataErrorInfo
    {
        // データ検証エラー情報
        protected Dictionary<string, string[]> Errors;

        public ValidationModel()
        {
            Errors = new Dictionary<string, string[]>();
            HasErrors = false;
        }

        #region HasErrors変更通知プロパティ
        private bool _HasErrors;
        // エラーの有無
        public bool HasErrors
        {
            get
            { return _HasErrors; }
            private set
            { 
                if (_HasErrors == value)
                    return;
                _HasErrors = value;
                RaisePropertyChanged();
            }
        }
        #endregion

        // エラー情報が変更された際に発生するイベント
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        // ErrorsChangedイベントを発生させる
        protected virtual void RaiseErrorsChanged([CallerMemberName]string propertyName = "")
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }

        // エラー情報を取得する。
        public IEnumerable GetErrors(string propertyName)
        {
            if (string.IsNullOrWhiteSpace(propertyName)) return null;
            if (!Errors.ContainsKey(propertyName)) return null;
            return Errors[propertyName];
        }

        // 属性を利用した検証を行う
        protected void Validation(object value, [CallerMemberName] string propertyName = "")
        {
            if (string.IsNullOrWhiteSpace(propertyName)) return;

            var results = new List<ValidationResult>();
            string[] messages = null;

            if (!Validator.TryValidateProperty(
                value,
                new ValidationContext(this, null, null) { MemberName = propertyName },
                results))
            {
               messages = results.Select(x => x.ErrorMessage).ToArray();
            }

            UpdateErrors(messages, propertyName);
        }

        // エラー情報(Errors)を更新する。
        protected void UpdateErrors(string[] messages, [CallerMemberName] string propertyName = "")
        {
            if (string.IsNullOrWhiteSpace(propertyName)) return;

            Errors[propertyName] = messages;

            HasErrors = Errors.Values.Any(x => x != null);
            RaiseErrorsChanged(propertyName);
        }
    }
}
 NotificationObjectクラスはLivetが提供しているModelの基底クラスでプロパティの変更通知処理を行ってくれるクラスです。
 データ検証を行う為にINotifyDataErrorInfoを実装し、データ検証用の処理を記載します。
 ここら辺のコードは以前紹介したデータ検証の処理と同じなので説明は省きます。
 System.ComponentModel.DataAnnotationsの属性を利用した検証用にValidationメソッドを、自分でデータ検証を行うとき用にUpdateErrorsメソッドを用意しました。
 HasErrorsプロパティは変更通知プロパティにしてあります。
using Livet;
using Livet.EventListeners;
using System;
using System.Collections;
using System.ComponentModel;
using ValidationDemo.Models;

namespace ValidationDemo.ViewModels
{
    public class ValidationViewModel : ViewModel, INotifyDataErrorInfo
    {
        private ValidationModel Model;

        public ValidationViewModel(ValidationModel model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));

            Model = model;

            // Modelのプロパティ変更通知にViewModelの変更通知を紐づけ
            CompositeDisposable.Add(new PropertyChangedEventListener(Model)
            {
                (sender, e) => RaisePropertyChanged(e.PropertyName)
            });

            // ModelのErrorsChangedイベントとViewModelのErrorsChangedイベントを紐づけ
            CompositeDisposable.Add(new EventListener<EventHandler<DataErrorsChangedEventArgs>>(
                h => Model.ErrorsChanged += h,
                h => Model.ErrorsChanged -= h,
                (sender, e) => ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(e.PropertyName))));
        }

        public bool HasErrors
        {
            get { return Model.HasErrors; }
        }

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public IEnumerable GetErrors(string propertyName)
        {
            return Model.GetErrors(propertyName);
        }
    }
}
 ValidationViewModelではINotifyDataErrorInfoを実装し、ValidationModelのデータ検証情報をそのままViewに渡すことができるようにします。

 これでデータ検証機能付きのModelとViewModelが準備できました。
 このクラスを使用してデータ検証をやってみます。
using System.ComponentModel.DataAnnotations;

namespace ValidationDemo.Models
{
    public class Data : ValidationModel
    {

        public Data()
        {
            // エラーになる値を設定
            Value = 500;
            Start = 10;
            End = 1;
        }

        #region Value変更通知プロパティ
        private int _Value;
        [Range(1, 100, ErrorMessage = "1~100の整数を入力してください。")]
        public int Value
        {
            get
            { return _Value; }
            set
            { 
                if (_Value == value)
                    return;
                _Value = value;
                RaisePropertyChanged();

                Validation(value);  // 属性を利用したデータ検証を行う。
            }
        }
        #endregion


        #region Start変更通知プロパティ
        private int _Start;

        public int Start
        {
            get
            { return _Start; }
            set
            { 
                if (_Start == value)
                    return;
                _Start = value;
                RaisePropertyChanged();

                StartAndEndValidation();    // StartとEndの値によるデータ検証
            }
        }
        #endregion


        #region End変更通知プロパティ
        private int _End;

        public int End
        {
            get
            { return _End; }
            set
            { 
                if (_End == value)
                    return;
                _End = value;
                RaisePropertyChanged();

                StartAndEndValidation();    // StartとEndの値によるデータ検証
            }
        }
        #endregion

        // StartとEndの大小関係でデータ検証
        private void StartAndEndValidation()
        {
            var message = Start <= End
                ? null
                : new[] { "Start <= End になるように値を入力してください。" };
            UpdateErrors(message, nameof(Start));
            UpdateErrors(message, nameof(End));
        }
    }
}
 データ検証を行うModelとしてDataクラスをつくりました。
 ValueプロパティはRange属性を利用したデータ検証を行っています。
 データ検証を行う場合はsetterでValidationメソッドを呼び出すだけです。
 StartとEndプロパティは属性を使わず自分でデータ検証を行っています。
 このサンプルではStartとEndの大小関係をチェックしたのち、UpdateErrorsメソッドを呼び出しErrorsを更新します。
using ValidationDemo.Models;

namespace ValidationDemo.ViewModels
{
    public class DataViewModel : ValidationViewModel
    {
        private Data Model;

        public DataViewModel(Data model)
            : base(model)
        {
            Model = model;
        }

        public int Value
        {
            get { return Model.Value; }
            set { Model.Value = value; }
        }

        public int Start
        {
            get { return Model.Start; }
            set { Model.Start = value; }
        }

        public int End
        {
            get { return Model.End; }
            set { Model.End = value; }
        }
    }
}
 ViewModelではValidationViewModelを基底クラスにして、コンストラクタの引数でデータ検証機能付きのModelを受け取るだけです。
 データ検証用のコードは一切描く必要がありません。
 あとは適当にMainWindowViewModelとViewを作って動かしてみます。(一応、コードを載せておきます)
using Livet;
using ValidationDemo.Models;

namespace ValidationDemo.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        private Data Model;

        public MainWindowViewModel()
        {
            Model = new Data();
            Data = new DataViewModel(Model);
        }

        public DataViewModel Data { get; }
    }
}
<Window x:Class="ValidationDemo.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:ValidationDemo.Views"
        xmlns:vm="clr-namespace:ValidationDemo.ViewModels"
        Title="MainWindow" Height="100" Width="350">
    
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>

    <Window.Resources>
        <ControlTemplate x:Key="ErrorTemplate">
            <DockPanel>
                <ItemsControl DockPanel.Dock="Right"
                              ItemsSource="{Binding ElementName=adornedElement, Path=AdornedElement.(Validation.Errors)}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

                <Border BorderBrush="Red" BorderThickness="1"
                        Width="{Binding ElementName=adornedElement, Path=ActualWidth}"
                        Height="{Binding ElementName=adornedElement, Path=ActualHeight}">
                    <AdornedElementPlaceholder Name="adornedElement"/>
                </Border>
            </DockPanel>
        </ControlTemplate>

        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Width" Value="50"/>
            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}"/>
        </Style>
    </Window.Resources>
    
    <Grid DataContext="{Binding Data}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Text="値:"/>
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Value}"/>

        <TextBlock Grid.Row="1" Grid.Column="0" Text="Start:"/>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Start}"/>

        <TextBlock Grid.Row="2" Grid.Column="0" Text="End:"/>
        <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding End}"/>
    </Grid>
</Window>
このコードを実行すると以下の様になります。
ModelValidation.png
 データ検証機能はきちんと動いています。
 個人的にはModelでデータ検証を行うほうが断然作りやすいと感じました。

テーマ : プログラミング
ジャンル : コンピュータ

【Graphics】 Imageを描画する

 DrawImageメソッドを使用することで、画像ファイルから読み込んだImageや描画したImageを指定した位置に書き込むことができます。
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace Graphics5
{
    class Program
    {
        static void Main(string[] args)
        {
            var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Image.png");

            using (var bitmap1 = new Bitmap(200, 200))
            using (var graphics1 = Graphics.FromImage(bitmap1))
            using (var blue = Brushes.Blue)
            {
                // 背景色
                graphics1.FillRectangle(blue, graphics1.VisibleClipBounds);

                using (var bitmap2 = new Bitmap(100, 100))
                {
                    using (var graphics2 = Graphics.FromImage(bitmap2))
                    using (var red = Brushes.Red)
                    {
                        graphics2.FillRectangle(red, graphics2.VisibleClipBounds);
                    }

                    // 作成したImageを使って描画する
                    graphics1.DrawImage(bitmap2, 10, 10);
                }

                bitmap1.Save(path, ImageFormat.Png);
            }
        }
    }
}
 このコードを実行すると以下の画像が作成されます。
DrawImage.png
 使い方は矩形などを描画するDrawXxxメソッドとほぼ同じです。
 DrawImageメソッドに描画したいImageとそのImageを描画する位置を指定します。
 サンプルコードでは自分で描画したImageを使用しています。
 この時GraphicsインスタンスがDisposeされていても問題ありません。
 (BitmapインスタンスがDisposeされている場合は例外になります)

テーマ : プログラミング
ジャンル : コンピュータ

【Graphics】 テキスト描画と描画サイズ

今回はテキストを描画する方法と描画するテキストのサイズを計算する方法を紹介します。
まずはテキストを描画する方法を説明します。
using (var bitmap = new Bitmap(800, 250))
using (var graphics = Graphics.FromImage(bitmap))
using (var bgBrush = Brushes.White)
using (var textBrush = Brushes.Blue)
using (var font = new Font("メイリオ", 30))
{
    graphics.FillRectangle(bgBrush, graphics.VisibleClipBounds);

    var text = "0123456789:";

    // アンチエイリアス処理を変更してテキストを描画
    graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
    graphics.DrawString(text + "AntiAlias", font, textBrush, 10, 0);

    graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
    graphics.DrawString(text + "AntiAliasGridFit", font, textBrush, 10, 50);

    graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
    graphics.DrawString(text + "ClearTypeGridFit", font, textBrush, 10, 100);

    graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
    graphics.DrawString(text + "SingleBitPerPixel", font, textBrush, 10, 150);

    graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
    graphics.DrawString(text + "SingleBitPerPixelGridFit", font, textBrush, 10, 200);

    bitmap.Save(filePath, ImageFormat.Png);
}
 このコードを実行すると以下の画像が作成されます。
DrawText1.png
 テキストを描画する際にはDrawStringメソッドを使用します。
 DrawStringメソッドの引数には描画したいテキスト、フォント、文字の色、描画する位置を指定します。
 テキスト描画の場合もアンチエイリアス処理が可能ですが、図形のアンチエイリアスとは別扱いになっています。
 テキスト描画の場合はGraphicsインスタンスのTextRenderingHintプロパティでアンチエイリアス処理の方法を指定します。
 GraphicsインスタンスのTextContrastプロパティもアンチエイリアス処理に関係していますが、大きな違いは出ない様なのでこのサンプルコードでは省略しています。
 テキストのアンチエイリアス処理をしたい場合はTextRenderingHintをAntiAlias、AntiAliasGridFit又はClearTypeGridFitにします。
 次に描画するテキストの描画サイズを取得する方法です。
 テキストの描画サイズを計算するにはGraphicsインスタンスのMeasureStringメソッドを使用します。
using (var bitmap = new Bitmap(290, 90))
using (var graphics = Graphics.FromImage(bitmap))
using (var bgBrush = Brushes.White)
using (var borderPen = new Pen(Brushes.Red, 1))
using (var textBrush = Brushes.Black)
using (var font = new Font("メイリオ", 30))
{
    graphics.FillRectangle(bgBrush, graphics.VisibleClipBounds);

    var text = "0123456789";
    var startX = 10;
    var startY = 10;

    // 文字を描画するために必要なサイズを計算
    var size = graphics.MeasureString(text, font);

    graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
    graphics.DrawString(text, font, textBrush, startX, startY);
    graphics.DrawRectangle(borderPen, startX, startY, size.Width, size.Height);

    bitmap.Save(filePath, ImageFormat.Png);
}
 このコードを実行すると以下の画像が作成されます。
MeasureStringNormal.png
 テキストの描画サイズを計算する場合はMeasureStringメソッドに描画したいテキストと使用するフォント情報を渡します。
 Graphicsインスタンスにテキストが描画されていないくても計算可能です。
 取得したテキスト描画領域を枠線で表示してみるとテキストの前後に余白があります。
 この余白をなくしたい場合はStringFormatを利用します。
using (var bitmap = new Bitmap(290, 90))
using (var graphics = Graphics.FromImage(bitmap))
using (var bgBrush = Brushes.White)
using (var borderPen = new Pen(Brushes.Red, 1))
using (var textBrush = Brushes.Black)
using (var font = new Font("メイリオ", 30))
using (var format = new StringFormat(StringFormat.GenericTypographic))
{
    graphics.FillRectangle(bgBrush, graphics.VisibleClipBounds);

    var text = "0123456789";
    var startX = 10;
    var startY = 10;

    // 文字を描画するために必要なサイズを計算
    var size = graphics.MeasureString(text, font, bitmap.Width, format);
    format.Trimming = StringTrimming.Word;

    graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
    graphics.DrawString(text, font, textBrush, startX, startY, format);
    graphics.DrawRectangle(borderPen, startX, startY, size.Width, size.Height);

    bitmap.Save(filePath, ImageFormat.Png);
}
 このコードを実行すると以下の画像が作成されます。
MeasureStringGenericTypographic.png
 StringFormatは自分で細かく設定することもできますが、特にこだわりがないのであればGenericTypographicを利用する方が簡単です。
 MeasureStringメソッドでサイズ計算時にStringFormatも指定します。
 このとき最大幅も指定する必要があります。
 注意点はDrawStringメソッドでテキスト描画を行う際にもStringFormatを指定する必要があることです。
 StringFormatを指定することで書式に従い余計な余白を作らずにテキストが描画されます。
 

テーマ : プログラミング
ジャンル : コンピュータ

【Graphics】 塗りつぶしを行う

 今回は塗りつぶしについて説明します。
 以下のサンプルコードは矩形、楕円、扇形で塗りつぶしを行うサンプルです。
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace Graphics3
{
    class Program
    {
        static void Main(string[] args)
        {
            var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Image.png");
            using (var bitmap = new Bitmap(260, 110))
            using (var graphics = Graphics.FromImage(bitmap))
            using (var bgBrush = Brushes.White)
            using (var fillBrush = Brushes.Blue)
            {
                // 背景色
                graphics.FillRectangle(bgBrush, graphics.VisibleClipBounds);

                // 矩形塗りつぶし
                graphics.FillRectangle(fillBrush, 10, 10, 50, 30);

                // 楕円塗りつぶし
                graphics.FillEllipse(fillBrush, 100, 10, 50, 30);

                // 扇形塗りつぶし
                graphics.FillPie(fillBrush, 200, 10, 50, 30, 90, 180);

                // アンチエイリアス処理
                graphics.SmoothingMode = SmoothingMode.AntiAlias;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

                // 矩形塗りつぶし
                graphics.FillRectangle(fillBrush, 10, 70, 50, 30);

                // 楕円塗りつぶし
                graphics.FillEllipse(fillBrush, 100, 70, 50, 30);

                // 扇形塗りつぶし
                graphics.FillPie(fillBrush, 200, 70, 50, 30, 90, 180);

                bitmap.Save(path, ImageFormat.Png);
            }
        }
    }
}
 このコードを実行すると以下の画像が作成されます。
FillImage.png
 解りにくいですが上の段がアンチエイリアス処理なしの場合、下の段がアンチエイリアス処理を行った場合の図形です。

 塗りつぶしを行うにはFillXxxメソッドを使用して色と塗りつぶし範囲を指定します。
 塗りつぶしの場合もDrawXxxメソッドと同様の方法でアンチエイリアス処理が可能です。

 図形を描画する際にはDrawXxxメソッド、塗りつぶしを行う場合はFillXxxメソッドを使用して図形描画をしていく形になります。
 次回は文字の描画について説明する予定です。

テーマ : プログラミング
ジャンル : コンピュータ

カレンダー
10 | 2023/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
全記事表示リンク

全ての記事を表示する

カテゴリ
タグリスト

月別アーカイブ
04  10  11  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09 
最新記事
リンク
最新コメント
検索フォーム
Amazon