20210608のC#に関する記事は13件です。

[WPF] Binding復習① `{Binding Path=.}`でDataContextそのものにバインドする

もくじ やりたいこと 職場で、画面のxamlを見ていたら a.xaml <TextBlock Text="{Binding}"/> とか a.xaml <TextBlock Text="{Binding Path=.}"/> というのが出てきてなにこれ?なにをBindingしてるのか?となった。 調べたい。 しらべたこと MSの公式の 上記によると、 {Binding}は{Binding Path=.}と同じ。 {Binding}は、DataContextそのものを指す。 つまり、{Binding}も{Binding Path=.}も、DataContextそのものを指す。 ということらしい。 試してみる。 試したコード MainWindow.xaml <Window x:Class="WpfApp4.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp4" mc:Ignorable="d" Title="MainWindow" Height="350" Width="400"> <!-- コードビハインドで「this.DataContext = ColorList;」で色のListをDataContextにしてる --> <StackPanel> <TextBlock Text="{Binding}"/> <TextBlock Text="{Binding Path=.}"/> <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <ListBox ItemsSource="{Binding Path=.}" IsSynchronizedWithCurrentItem="True" Margin="10"/> </StackPanel> </Window> MainWindow.xaml.cs using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; using System.Windows.Media; namespace WpfApp4 { public partial class MainWindow : Window, INotifyPropertyChanged { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion public ObservableCollection<SolidColorBrush> ColorList { get { return colorList; } set { colorList = value; OnPropertyChanged(nameof(ColorList)); } } public ObservableCollection<SolidColorBrush> colorList = new ObservableCollection<SolidColorBrush>(); public MainWindow() { InitializeComponent(); ColorList.Add(new SolidColorBrush(Colors.Blue) { Opacity = 0.5 }); ColorList.Add(new SolidColorBrush(Colors.Red) { Opacity = 0.7 }); ColorList.Add(new SolidColorBrush(Colors.Green) { Opacity = 0.9 }); ColorList.Add(new SolidColorBrush(Colors.Yellow) { Opacity = 1.0 }); ColorList.Add(new SolidColorBrush(Colors.Purple) { Opacity = 0.2 }); this.DataContext = ColorList; } } } 動かすと、2つのListには全く同じものがでる。 その他 DataContextの中にあるプロパティにバインドしようと思うと、下記のようになる。 (いちばんよく見る書き方) this.DataContext = this; MainWindow.xaml <Window x:Class="WpfApp4.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp4" mc:Ignorable="d" Title="MainWindow" Height="350" Width="400"> <StackPanel> <TextBlock Text="{Binding ColorList}"/> <TextBlock Text="{Binding Path=ColorList}"/> <ListBox ItemsSource="{Binding ColorList}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <ListBox ItemsSource="{Binding Path=ColorList}" IsSynchronizedWithCurrentItem="True" Margin="10"/> </StackPanel> </Window> 【注意】 ItemsSource="{Binding Path=.ColorList}"とは書けないっぽい。 所感 {Binding}は{Binding Path=.}と同じ、とか、 書き方を省略できるのは、慣れたら便利かもしれないが、初心者からしたら敷居が上がってとっつきにくい原因の一つのような気がする。 あと、ある程度慣れてきても、よく使う書き方以外は忘れていってしまい、また調べなおすことになる気がする。(現に{Binding}はたしか調べるの2回目)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[WPF] Binding復習② リストで今選択している項目を`{Binding Path=/}`でバインドする

もくじ やりたいこと 職場で、画面のxamlを見ていたら a.xaml <TextBlock Text="{Binding Path=/}"/> みたいな感じで、{Binding Path=/}というのが出てきてなにこれ?となった。 調べたい。 しらべたこと その1 Path=/は、コレクションの選択項目を参照しろ、ということになる。 参考: ++C++; // 未確認飛行 C ブログ 確かめてみる。 試したコード その1 MainWindow.xaml.cs using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; using System.Windows.Media; namespace WpfApp4 { public partial class MainWindow : Window, INotifyPropertyChanged { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion public ObservableCollection<SolidColorBrush> ColorList { get { return colorList; } set { colorList = value; OnPropertyChanged(nameof(ColorList)); } } public ObservableCollection<SolidColorBrush> colorList = new ObservableCollection<SolidColorBrush>(); public MainWindow() { InitializeComponent(); // 色のリストを作成(ListBoxのItemsSourceにバインドする) ColorList.Add(new SolidColorBrush(Colors.Blue) { Opacity = 0.5 }); ColorList.Add(new SolidColorBrush(Colors.Red) { Opacity = 0.7 }); ColorList.Add(new SolidColorBrush(Colors.Green) { Opacity = 0.9 }); ColorList.Add(new SolidColorBrush(Colors.Yellow) { Opacity = 1.0 }); ColorList.Add(new SolidColorBrush(Colors.Purple) { Opacity = 0.2 }); this.DataContext = ColorList; } } } MainWindow.xaml <Window x:Class="WpfApp4.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp4" mc:Ignorable="d" Title="MainWindow" Height="350" Width="400"> <!-- コードビハインドで「this.DataContext = ColorList;」で色のListをDataContextにしてる --> <StackPanel> <TextBlock Text="{Binding Path=.}"/> <ListBox ItemsSource="{Binding Path=.}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <ListBox ItemsSource="{Binding Path=.}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <TextBlock Text="{Binding Path=/}" Background="{Binding Path=/}"/> </StackPanel> </Window> 結果画面 一番上(最後にListにAddしたパープル)を選んだ時 テキストブロックには、プロパティColorListのうち、ListBoxで選択された項目がBindingされてる。 TextにBindingした方には、カラーコードが出て、BackgroundにBindingした方にはその色が表示されている。 ポイント 画面にはListBoxを2つ出していて、両方とも同じListにBindingしていて、かつIsSynchronizedWithCurrentItemをTrueにしている。 こうすると、両方のListBoxの選択項目がシンクロする。 また、その下のTextBlockで{Binding Path=/}と書くことにより、ListBoxがItemsSourceにBindingしてるリストの中の、選択してる項目がBindingされることになる。 ListBoxの片方だけIsSynchronizedWithCurrentItemをFalseにすると、2つのListBoxの選択項目がシンクロしなくなる。 またFalseにしたほうで項目を選んでも、TextBlockに反映されなくなる。 しらべたこと その2 個人的にというか、自分のまわりでは、DataContextにListを直接入れたりすることはほぼやったことがなく、大体の場合、DataContextにはViewModelのクラスが入ってたり、Window(とかUserControl)のクラス自身が入ってたりする。 そういう場合にも、/が使えるのか確かめる。 試したコード その2 Bindingの部分を{Binding Path=ColorList/}という感じで、MainWindowクラスの中のColorListの選択されてるやつということにした。 一部MainWindow.xaml.cs this.DataContext = this;// Windowのクラス自身をDataContextにする 一部MainWindow.xaml <TextBlock Text="{Binding ColorList}"/> <ListBox ItemsSource="{Binding ColorList}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <ListBox ItemsSource="{Binding ColorList}" IsSynchronizedWithCurrentItem="True" Margin="10"/> <TextBlock Text="{Binding Path=ColorList/}" Background="{Binding Path=ColorList/}"/> 結果の画面は全く同じ。 ここからさらに、 MainWindow.xaml <TextBlock Text="{Binding Path=ColorList/Opacity}" Background="{Binding Path=ColorList/}" Opacity="{Binding Path=ColorList/Opacity}"/> てな感じで「選択されてる項目のさらに中のプロパティ」みたいなこともできる。 参考 このMS MS公式ドキュメントの、 下記にあたる部分。 この部分の説明がわかるようでよくわからなかったのだが、試してみるとなるほどという感じ。 この説明でいうところの「コレクション ビュー」というのは、ListをバインディングしているListBoxなどのことを言ってるのだと思う。(たぶん)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ゲームのマスターデータのフォーマットはcsvよりtsvがオススメ

概要 モバイルゲームを開発する際は、ExcelやGoogleスプレッドシートなどでマスターデータを管理し、csvとしてエクスポートしてgit管理するといった運用をわりと見かけます。 最近、クライアント/サーバー間でやりとりするマスターデータのフォーマットをcsvからtsvに変えたところ、とても使い勝手が良かったため紹介します。 tsvとは タブを区切り文字として使用したデータ形式。 csvはカンマを区切り文字とするが、そのカンマ(,)がタブ(\t)になったもの。 具体的には以下のようなテキストデータとなる。 csv name,hp,atk スライム,10,2 ゴブリン20,4 tsv name\thp\tatk スライム\t10\t2 ゴブリン\t20\t4 tsvのメリット 言語やライブラリへの依存がとても少なく、シンプルにパースすることができる わりと最近のシステムだとcsvファイルとして普通に読み込める コードサンプル C#でtsvを出力 var line = string.Join("\t", fields); C#でtsvをパース var fields = line.Split('\t'); PHPでtsvを出力 $line = implode('\t', $fields); PHPでtsvをパース $fields = explode('\t', $line); tsvのデメリット 文字列中にタブを使用したい時は別の文字列に置換する必要がある マスターデータでタブを文字列として使用したいシチュエーションはあまりないが… 古いシステムだと読み込めないものがある csvのメリット とても一般的に使用されている 以下略 csvのデメリット tsvのようにシンプルにパースすることができない 後述のようにダブルクォーテーションを考慮する必要がある 文字列としてカンマを使用したい時はダブルクォーテーションで囲う必要がある ダブルクォーテーションを使用している箇所と使用していない箇所が混在しがち tsvに比べてロジックが複雑なためパースコストが高い シンプルにカンマ区切りでパースするだけならtsvとコストは変わらないが、マスターデータでキャラクターの説明文にカンマを使用するなど、カンマを文字列として使用したいシチュエーションがわりとあるため ライブラリによっては細部の対応オプションが異なる まとめ tsvからcsvへの変換は容易なため、非エンジニアがマスターデータを参照する時はcsvとして扱いつつ、クライアント/サーバー間のやりとりはtsvとして扱うなど、柔軟に使い分けられると双方のメリットが最大限に活かせるのではないかと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity ゲームのリトライ(現シーンの再読み込み)

0.0 はじめに 現在アクティブになっている(プレイ中の)シーン(Scene)をもう一度読み込む方法です。 ゲームオーバーになった際のリトライやリプレイの処理を実装する方法です。 備忘録としてまとめます。 1.0 スクリプト 下記のみです。 Test.cs SceneManager.LoadScene (SceneManager.GetActiveScene().name); SceneManager.GetActiveScene().nameで現在アクティブなシーンの名前を取得しています。 その名前のシーンをSceneManager.LoadScene()で呼んでいます。 ?ポイント SceneManagerを使うためには下記が必要になりますのでご注意。 using UnityEngine.SceneManagement;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコードを作成して印刷してみた (QRCodeEncoderDecoderLibrary.dll)

dllのダウンロード http://thomas.cranky.jp/qr/QRCodeEncoderDecoderLibrary.dll 例1 引数をそのまま印刷 makeQR.cs using System; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static void Main(string[] args) { string str; str = @"" + args[0]; QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(str); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); QRCodeImage.Save(@".\\outQR.png", System.Drawing.Imaging.ImageFormat.Png); } } コンパイル c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe が出来上がる。 makeQR.exe hoge 例2. 画像を印刷する例 画像を印刷する例 makeQR.cs using System; using System.Windows.Forms; using System.Drawing; public class printtest { public static void Main(string[] args) { // 印刷 System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile("outQR.png"); //画像を描画する e.Graphics.DrawImage(img, e.MarginBounds); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } フォルダがなければ作成 QRコード出力時にフォルダが無ければ作成 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static void Main(string[] args) { string QRbody, QRfilename; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody, QRfilename); } public static void generateQR(string QRbody, string QRfilename) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } } QRコード出力し印刷(通常使うプリンター) QRコード出力し印刷(通常使うプリンター) makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷 printingText = @"QRの内容: " + args[0]; printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } プリンター名を指定して印刷 プリンター名を指定して印刷 https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.printing.printersettings.printername?view=net-5.0 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷 printingText = @"QRの内容: " + args[0]; printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); // プリンターを指定して印刷 string PrinterName; // PrinterName = @"Microsoft XPS Document Writer"; PrinterName = @"Microsoft Print to PDF"; pd.PrinterSettings.PrinterName = PrinterName; if (pd.PrinterSettings.IsValid) { pd.Print(); } else { MessageBox.Show(@"指定されたプリンターは見つかりません。" + PrinterName); } } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } 設定ファイルに対応 設定ファイルに対応 makeQR.iniの作成 makeQR.ini # PrinterName="Microsoft XPS Document Writer" PrinterName="Microsoft Print to PDF" printingText="印字内容" c:\QR-output\QR-〇〇.pngを生成し印刷する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using System.Text; using System.Text.RegularExpressions; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string baseDir = @"c:"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static string PrinterName = @"Microsoft XPS Document Writer"; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(baseDir + @"\QR-output"); QRfilename = baseDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷設定 printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); // INIファイルから設定読み込み getIniFile(); // プリンターを指定して印刷 pd.PrinterSettings.PrinterName = PrinterName; // 印刷内容 printingText += @" " + args[0]; if (pd.PrinterSettings.IsValid) { pd.Print(); } else { MessageBox.Show(@"指定されたプリンターは見つかりません。" + PrinterName); } } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } public static void getIniFile() { StreamReader sr = new StreamReader(baseDir + @"\QR\makeQR.ini", Encoding.GetEncoding("Shift_JIS")); // 一行づつ読み込み while (sr.Peek() > -1) { string line = sr.ReadLine(); if (Regex.IsMatch(line, "^PrinterName=")) { Match match = Regex.Match(line, @"^PrinterName=""(.*)"""); PrinterName = match.Groups[1].Value; } if (Regex.IsMatch(line, "^printingText=")) { Match match = Regex.Match(line, @"^printingText=""(.*)"""); printingText = match.Groups[1].Value; } } sr.Close(); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe 1
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコード出力し印刷 (設定ファイルに対応)

makeQR.iniの作成 makeQR.ini # PrinterName="Microsoft XPS Document Writer" PrinterName="Microsoft Print to PDF" printingText="印字内容" c:\QR-output\QR-〇〇.pngを生成し印刷する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using System.Text; using System.Text.RegularExpressions; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string baseDir = @"c:"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static string PrinterName = @"Microsoft XPS Document Writer"; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(baseDir + @"\QR-output"); QRfilename = baseDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷設定 printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); // INIファイルから設定読み込み getIniFile(); // プリンターを指定して印刷 pd.PrinterSettings.PrinterName = PrinterName; // 印刷内容 printingText += @" " + args[0]; if (pd.PrinterSettings.IsValid) { pd.Print(); } else { MessageBox.Show(@"指定されたプリンターは見つかりません。" + PrinterName); } } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } public static void getIniFile() { StreamReader sr = new StreamReader(baseDir + @"\QR\makeQR.ini", Encoding.GetEncoding("Shift_JIS")); // 一行づつ読み込み while (sr.Peek() > -1) { string line = sr.ReadLine(); if (Regex.IsMatch(line, "^PrinterName=")) { Match match = Regex.Match(line, @"^PrinterName=""(.*)"""); PrinterName = match.Groups[1].Value; } if (Regex.IsMatch(line, "^printingText=")) { Match match = Regex.Match(line, @"^printingText=""(.*)"""); printingText = match.Groups[1].Value; } } sr.Close(); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe 1
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコード出力し印刷 (プリンター名を指定)

プリンター名を指定して印刷 c:\QR-output\QR-〇〇.pngを生成し印刷する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷 printingText = @"QRの内容: " + args[0]; printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); // プリンターを指定して印刷 string PrinterName; // PrinterName = @"Microsoft XPS Document Writer"; PrinterName = @"Microsoft Print to PDF"; pd.PrinterSettings.PrinterName = PrinterName; if (pd.PrinterSettings.IsValid) { pd.Print(); } else { MessageBox.Show(@"指定されたプリンターは見つかりません。" + PrinterName); } } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe 1 次
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコード出力し印刷

c:\QR\QR-〇〇.pngを生成し印刷する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷 printingText = @"QRの内容: " + args[0]; printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe 1 makeQR.exe 2 makeQR.exe 3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコード出力し印刷 (通常使うプリンターで印刷)

c:\QR-output\QR-〇〇.pngを生成し印刷する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static string QRfilename = ""; public static string printingText; public static Font printFont; public static void Main(string[] args) { string QRbody; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody); // 印刷 printingText = @"QRの内容: " + args[0]; printFont = new Font("MS Pゴシック", 12); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void generateQR(string QRbody) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile(QRfilename); //画像を描画する //e.Graphics.DrawImage(img, e.MarginBounds); // 幅全体に描画する場合。 // 20, 10 の位置に表示 e.Graphics.DrawImage(img, 20, 10, img.Width, img.Height); // サイズ指定する場合 //文字 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs makeQR.exe 1 makeQR.exe 2 makeQR.exe 3 次
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クリーンアーキテクチャをミニマルで実装可能な形にした Simple Clean Architecture という考え方

これは、ソフトウェアアーキテクチャの一つである Clean Architectureを、開発現場での実運用(特にC#, Unityでの開発)に合わせて調整した Simple Clean Architecture の解説記事です。(英語版はこちら) なぜアーキテクチャが必要なの? ソフトウェアは、どんな実装でもできます。あなたが個人開発をする限り、そしてあなたがコードのすべてを把握できている限り、どんな実装をするのも自由です。ただし、実際にビジネスの現場で、複数人で大規模なコードをみんなで作り上げていくときに、問題が出てきます。あなたの書いた天才的なコードは、他の人から見ると理解に時間がかかり、バグを誘発しやすい難解なものになっているかもしれません。アーキテクチャの使命は、ソフトウェアの構造にルールを課すことで、コードに一貫性をもたせ、これにより開発スピードとクオリティを上げることです。 特に Simple Clean Architectureは実際のビジネス、とくにスタートアップのような不確実性が高い中で最速で結果を出していく必要がある開発現場のため、下記をゴールとして考えて設計しています。 ・複数のメンバーが参加しても、全員が似たような実装になるような規則を用いることで既読性/メンテナンス性を維持する ・複数のメンバーが参加しても、疎結合で相互依存の少ない実装にすることでお互いの変更が干渉しあわないようにする Simple Clean Architecturetとは? Simple Clean Architecture (SCA) は、Clean Architectureの考え方をベースに、実際の実装方法のレベルまでルールを具体化させたものです。Clean Architecture自体は「設計指針」に近いため、実際の実装の方法は1つではありません。SCAは、Clean Architectureのエッセンスを利用しながら、冗長な部分は省き、また、実装上必要になる「Dependency Injection (依存注入)」と「Reactive Programming」の考え方を足すことで「実装ルールに落とし込んだアーキテクチャ」の形になっています。 とはいえ、Clean Architectureの考え方はコンポーネントを疎結合に保つために非常に重要な基本概念です。下記のようなページを参照することをおすすめします。 https://qiita.com/kz_12/items/bc79102247b86626fc72 https://gist.github.com/mpppk/609d592f25cab9312654b39f1b357c60 また、前述の通り、SCAは Dependency Injection (DI) と Reactive Programming の考え方を取り入れています。これらはソフトウェアアーキテクチャというより、アーキテクチャを実際の実装に落としたときの実現手段(デザインパターン)の1つ、ツールのような立ち位置です。 これらも、SCA特有のものではなく、ソフトウェア構成として一般的なものですので、基礎知識を調べてみることをおすすめします。 ・Dependency Injection https://qiita.com/hshimo/items/1136087e1c6e5c5b0d9f ・Reactive Programming イベント駆動型プログラミングが考え方としては近いです。 https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 https://ninjinkun.hatenablog.com/entry/introrxja おさらいすると、Simple Clean Architecture (SCA) とは ・Clean Architectureで概念として示されているものを、必要最小限のエッセンスを取り出して実装可能なルールに落とし込んだもの ・実装のためのツールとして、Dependency Injection(DI) と、Reactive Programming(RP)を導入している というものになります。 Simple Clean Architectureの構成 下記の図は、Clean Architectureで調べるとまず出てくる図です。Uncle Bobの原典で使われている図です。 Clean Architectureはあくまでコード・コンポーネント間の依存関係を少なくすることでプロジェクトをきれいに保つための行動指針ですので、「この実装じゃなきゃダメ!」というものはありません。だからこそ人によって理解や実装形態が千差万別になっています。 SCAではClean ArchitectureのSOLID原則を元に、特に下記の考え方を重要と考えます。 ・外側のレイヤーから1つ内側のレイヤにのみしか依存してはいけない ・依存関係は必ずインターフェイスを通じて行い、DIによって依存解決する ・内側から外側への情報の伝播はイベント駆動で行うことで、依存関係を無くす また、Clean Architectureではいろいろな登場人物が登場しますが、SCAではその中から下記のみを取り出して使用します。 ・Entity ・Usecase ・Gateway ・Presenter ・View それぞれの特徴を見ていきましょう。 Entity Clean Architectureでは最も中心のレイヤーにある要素です。なので、上位のレイヤーのどれにも依存関係を持ってもいけません。Entityは、「最も基本となるビジネスルールのカプセル化」を担当します。オブジェクトとして扱われる最小単位の要素や、ビジネスルールの特徴上必要になる計算処理などが含まれます。DDD(ドメイン駆動設計)を知っている方には、「EntityはDDDにおける Entity, ValueObject, Domainserviceをまとめたもの」とも言えます。 「基本となる要素のクラスの定義をするレイヤーで、他の上位レイヤーに対して依存してはいけないんだな」と考えてもらえれば十分です。 Usecase Clean Architectureでは中心から二番目のレイヤー、「Application Business Rules」にある要素です。「アプリケーション固有のビジネスルール(いわゆるビジネスロジック)」を記述する役割をもちます。UsecaseはEntityの操作をすることが役割です。ただし、Entityを直接操作するだけでなく、「データベースからEnityとして定義されたデータをGatewayを通じて取得し、処理する」といった処理部分もUsecaseの担当となります。そのため、UsecaseはGatewayのInterfaceに依存することができます。また、UsecaseはInterfaceを通じてPresenterから呼ばれることになります。 Gateway Clean Architectureでは中心から三番目のレイヤー、「Interface Adapters」にある要素です。Interface Adaptersは「ビジネスルールとUIやDBなどのアプリの外の世界とをつなげる」役割をもったコンポーネントが所属するレイヤーです。Gatewayはこのうち、DBや外部ライブラリとのインタラクションを担当するコンポーネントです。 例えばデータベースからEntityで定義したデータを取得する IDBGateway というインターフェイスを定義したとします。 public interface IDBGateway{ int GetValue(string key); void SetValue(string key, int value); } このとき、実際の実装方法としてはDBとしてMySQLを使っても、PostgreSQLを使っても、それは実装者の自由です。これらの実装方法の違いは、例えば IDBGateway を継承した MySqlGateway : IDBGateway や、 PostgreSqlGateway : IDBGateway として実装できます。重要なのは、この実体の修正が他のレイヤーに影響を与えないことです。DIがインスタンスする対象を MySQLGateway から PostgreSqlGateway に変えるだけでこの変更ができることになります。このDIの考え方は他のコンポーネント(UsecaseとPresenter)でも同じです。 Presenter Clean Architectureでは中心から三番目のレイヤーで、「ビジネスルールと外の世界をつなげる」役割をもった「Interface Adapters」にある要素です。Gatewayと同じレイヤーに所属し、UI (View) とのインタラクションを担当します。Presenterはインターフェイスを通じてUsecaseを参照することができます。Viewからの入力をUsecaseに伝えてビジネスロジックを駆動させ、UsecaseからのEntityの更新をViewに伝えます。ここで「Viewに伝える」ための方法として、Reactive Programmingを使用します。PresenterがEntityの更新をPublishするReactive Propertyを備えることで、Viewへの依存なしにUIを更新することができます。 View Clean Architectureでは一番外側の「Frameworks & Drivers」レイヤーに属します。UIの操作、すなわちUIを介したアクションのInputと、更新されたEntityのOutputを担当します。 ViewはPresenterにインターフェイスを介して依存することができます。ViewからPresenterへのアクションはPresenterの関数を呼ぶことで実現します。一方、Viewの更新は、ViewがPresenterが提供するReactive Propertyを購読することで実現します。Presenterの値の更新をイベントとしてコールバックで取得することで、Viewがコールバックを通して表示を更新する。という動作を実現します。これにより、ViewとPresenterが密結合になることを防ぎ、新しいViewの追加を容易にします。Viewはレイヤーの最外にいるため、他の要素に依存することはできません。 以上を図にまとめると、コンポーネント間の関係は下記のようになります。 UnityでのSimple Clean Architectureの実装 SCAは特定の開発言語、プラットフォームに限定されたアーキテクチャではありません。大規模開発でコンポーネント間を疎結合に保ちたい場合、SCAの考え方を適用することはできると考えます。 一方で、最も実践上で相性が良いのがUnityでのプロジェクトに対する使用です。Unity上でのアプリケーション開発は、アーキテクチャ無しの場合、下記のような悪夢を容易に実現できます。 ・とあるMonobehaviourが別のMonobehaviourに依存し、どれかを修正したらすべて動かなくなる ・Monobehaviourへの依存関係 (変数の代入) を public や [serializefield] を使い、Inspectorから代入して行っていて、誰かの変更ですべての参照が吹っ飛んだ ・新しいオブジェクトを追加するためにシーンファイル (.unity) を複数人で編集し、gitでマージする際にコンフリクトした これらは、Unityのエディタからの操作やMonobehaviourに依存しすぎた結果起きるものです。できるだけC#の世界でコードを整理しておき、シーンへのコンポーネントの追加やMonobehaviourの参照を少なくすることで、大規模開発での混乱を少なくすることができます。 具体的には、UnityでのSCAの実装は下記のようになります。 ・SCAに基づき、コンポーネントをレイヤーごとに分ける ・Monobehaviourを継承できるのは「View と Presenter のみ」に限定する ・UniRXを使ってReactive Programmingを実現する ・Extenjectを使って依存注入し、Unityシーンをできるだけ編集せずに機能拡張を実現する 下記はコンポーネント間のデータの流れを示します。 ここでは Gatewayは割愛しています。GatewayはUnityに依存しない純粋なC#の世界のクラスのためです。重要なのは「ViewはPresenterしか参照せず、PresenterはUsecaseしか参照しない」ことです。これを実現するために、 PresenterからViewのような逆方向の情報伝播はReactive Programmingを積極的に使い、外側のレイヤーが情報をイベントドリブンに取る実装になります。 SCA for Unityの各コンポーネントにおけるルールをまとめると、下記のようになります。 ・View  ・Viewはインターフェイスを通じてPresenterに依存できる  ・Viewは他のViewに依存できない  ・ViewはUsecase, Gatewayに依存できない  ・ViewはMonobihaviourを継承できる ・Presenter  ・Presenterはインターフェイスを通じてUsecaseに依存できる  ・PresenterはView, Gatewayに依存できない  ・PresenterはMonobihaviourを継承できる  ・Presenterは他のPresenterにインターフェイスを通じて依存してもよい(が、できるだけ避ける) ・Usecase  ・Usecaseはインターフェイスを通じてGatewayに依存できる  ・UsecaseはView, Presenterに依存できない  ・UsecaseはMonobihaviourを継承できない  ・Usecaseは他Usecaseにインターフェイスを通じて依存してもよい(が、できるだけ避ける) ・Gateway  ・Gatewayはインターフェイスを通じGatewayに依存できる  ・GatewayはView, Presenter, Usecaseに依存できない  ・GatewayはMonobihaviourを継承できない  ・Gatewayは他Gatewayにインターフェイスを通じて依存してもよい(が、できるだけ避ける) SCA for Unityの実装サンプルをgithubで公開しているので、参考にしてみてください。 他のアーキテクチャとの比較 「なんでMVPやMVVMではダメで、SCAを推奨するの?」に対して回答します。それは「MVPやMVVMだとモデルが肥大化するから」です。MVPやMVVMが悪いと言っている訳ではありません。ソフトウェアアーキテクチャは実際のアプリケーションに最適なものを使うべきなので、利点が欠点を上回ればそれで良いと思います。一方で、MVPやMVVMは、前述の通り、役割をきれいに分類していくとビジネスロジック部、つまりモデルのコードサイズが大きくなっていきます。モデルの全体像が把握できているうちは問題ありませんが、プロジェクトが大きくなっていくと「Model間での循環参照、密結合」が顕在化してきます。SCAではモデルに相当する部分はGateway、Usecase、Entityに分かれているので、この「モデルの肥大化」が起きにくなっている点が違いです。言い換えると、「MVPやMVVMのモデルの定義をもう少し細分化したもの」がSCAになります。 「MVPだとコードが整理しきれないけど、Clean Architectureを真面目にやると、RepositoryとかUsecase input portとか、Data Accessとか、細かすぎて逆に複雑になっちゃうよ~」という人達に向けた、「Clean Architectureを簡略化して実装ルールに落とし込んだアーキテクチャ」が Simple Clean Arcitectureになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコード出力時にフォルダが無ければ作成

c:\QR-output\QR-〇〇.pngを生成する例 makeQR.cs using System; using System.IO; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class makeQR { public static string workDir = @"c:\QR-output"; public static void Main(string[] args) { string QRbody, QRfilename; QRbody = @"" + args[0]; Directory.CreateDirectory(workDir); QRfilename = workDir + @"\QR-"+ args[0] +".png"; generateQR(QRbody, QRfilename); } public static void generateQR(string QRbody, string QRfilename) { // QR QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(QRbody); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); // QR save QRCodeImage.Save(QRfilename, System.Drawing.Imaging.ImageFormat.Png); } } compile.bat c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe makeQR.cs 使い方 makeQR.exe 1 makeQR.exe 2 makeQR.exe 3 次
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QRコードを作成して印刷してみた (QRCodeEncoderDecoderLibrary.dll)

参考 さんの記事をそのまま写経した忘備録。 dllのダウンロード http://thomas.cranky.jp/qr/QRCodeEncoderDecoderLibrary.dll sample_qr_encode.cs using System; using System.Windows.Forms; using System.Drawing; using QRCodeEncoderDecoderLibrary; public class sample_qr_encode { public static void Main(string[] args) { string str; str = @"" + args[0]; QREncoder QRCodeEncoder; Bitmap QRCodeImage; QRCodeEncoder = new QREncoder(); byte [] bytesData = System.Text.Encoding.UTF8.GetBytes(str); string Data = System.Text.Encoding.UTF8.GetString(bytesData); QRCodeEncoder.Encode(ErrorCorrection.H, Data); QRCodeImage = QRCodeToBitmap.CreateBitmap(QRCodeEncoder, 4, 8); QRCodeImage.Save(@".\\outQR.png", System.Drawing.Imaging.ImageFormat.Png); } } コンパイル c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /reference:QRCodeEncoderDecoderLibrary.dll ^ /target:winexe sample_qr_encode.cs sample_qr_encode.exe が出来上がる。 sample_qr_encode.exe hoge 参考: 画像を印刷する例 printtest.exe using System; using System.Windows.Forms; using System.Drawing; public class printtest { public static void Main(string[] args) { // 印刷 System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //画像を読み込む Image img = Image.FromFile("outQR.png"); //画像を描画する e.Graphics.DrawImage(img, e.MarginBounds); //次のページがないことを通知する e.HasMorePages = false; //後始末をする img.Dispose(); } } コンパイル c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /target:winexe printtest.cs printtest.exe を実行して、QRコードの画像が印刷できることを確認。 参考: 文字を印刷する例 printtest.cs using System; using System.Windows.Forms; using System.Drawing; public class printtest { static string printingText; static Font printFont; public static void Main(string[] args) { // 印刷 printingText = @"にほんご"; printFont = new Font("MS Pゴシック", 10); System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument(); pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); pd.Print(); } public static void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { // 印刷処理 e.Graphics.DrawString(printingText, printFont, Brushes.Black, 0, 0); } } コンパイル c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^ /target:winexe printtest.cs printtest.exe を実行して、文字が印刷できることを確認。 つづき
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

楽天API C# 商品検索の一覧取得する(2)

楽天APIのつづき 前回記事で楽天APIを使って検索結果の一覧をXML形式で取得したのは良いが、 XML形式の扱いが初めてなのでいろいろと探した結果Xml.Linqというのが どうやら使い勝手が良さそうだと分かりご紹介します。 単純にString型のデータをXML形式でパース(分解)してくれる便利なメソッドが あったのでそれを使います。XDocumentにしてしまえば、あとはSeleniumや AngleSharpと構文は変わらないので適当に処理を書いてしまえば必要な箇所だけ 自由に切り抜きできます。 <mediumImageUrls> <imageUrl>http---------------</imageUrl> <imageUrl>http---------------</imageUrl> <imageUrl>http---------------</imageUrl> </mediumImageUrls> <pointRate>1</pointRate> <shopOfTheYearFlag>0</shopOfTheYearFlag> <affiliateRate>3</affiliateRate> 入れ子構造の処理 上のようにmediumImageUrlsタグは下にimageUrlタグを複数持っています。 しかもこれは商品によっては必ず3つあるとは限らない可変の入れ子構造になっています。 この点はforeachによって柔軟に取り出します。 Element(名前) 今回のXMLの大外のタグは"root"でしたのでXDocumentの先頭はこれを探します。 XElement ROOT = xdoc.Element("root"); Elementの引数がstringなので大文字小文字区別して完全に一致しないと検出できないのが 難点です。まぁ一度作ってしまえば問題ないので最初だけですが。 XMLの構造解析 Getxml.cs using System.Xml.Linq; string HTMLtext;//前回記事のcs参照 //XML解析 XDocument xdoc = XDocument.Parse(HTMLtext); XElement ROOT = xdoc.Element("root"); XElement ITEMS = ROOT.Element("Items"); IEnumerable<XElement> ITEM = ITEMS.Elements("Item"); foreach (XElement e in ITEM) {          //出力パラメータ          //単数(item以下に入れ子構造なし) var item_name = e.Element("itemName"); var item_price = e.Element("itemPrice"); Console.WriteLine(item_name.Value); Console.WriteLine(item_price.Value);          //複数(item以下に入れ子構造あり) foreach (var u in e.Element("mediumImageUrls").Elements("imageUrl")) Console.WriteLine(u.Value); //空白行 Console.WriteLine(); } 検索結果は膨大なデータ量なので分かりにくいですが<Item>商品情報</Item>の間が1つの商品に対応しています。 サムネの画像URLなどもあるのでかなり項目も多いですが人によってほしいデータも違うと思うので最大公約数的にこんな ことになっているのでしょう。下のXMLデータは3件分のデータです。 楽天APIで取得したXMLデータ(元データ) RakutenApi.xml <?xml version="1.0" encoding="UTF-8"?> <root> <Items> <Item> <mediumImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566652.jpg?_ex=128x128</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076592882.jpg?_ex=128x128</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566746.jpg?_ex=128x128</imageUrl> </mediumImageUrls> <pointRate>1</pointRate> <shopOfTheYearFlag>0</shopOfTheYearFlag> <affiliateRate>3</affiliateRate> <shipOverseasFlag>0</shipOverseasFlag> <asurakuFlag>0</asurakuFlag> <endTime></endTime> <taxFlag>0</taxFlag> <startTime></startTime> <itemCaption>龍球7個セット!! まるで本物のようなズッシリした重量感!部屋に飾ってもかっこいい! 忘年会や結婚式でゲーム、パーティーでも使い道はありそうですね! 一星球 【イーシンチウ】 二星球 【アルシンウ】 三星球 【サンシンチウ】 四星球 【 スーシンチュウ】 五星球 【ウーシンチウ】 六星球 【リュウシンチウ】 七星球 【チーシンチュウ】 ◆素材:pvc ◆セット内容:7点、 ◆本体サイズ :約7cm(※±誤差0.3-0.5cm) ◆重量(7個セット):2Kg</itemCaption> <catchcopy>龍球7個セット!!BIGなケース入り</catchcopy> <tagIds> <value>1010450</value> <value>1041708</value> </tagIds> <smallImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566652.jpg?_ex=64x64</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076592882.jpg?_ex=64x64</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566746.jpg?_ex=64x64</imageUrl> </smallImageUrls> <asurakuClosingTime></asurakuClosingTime> <imageFlag>1</imageFlag> <availability>1</availability> <shopAffiliateUrl></shopAffiliateUrl> <itemCode>rapites:10001431</itemCode> <postageFlag>0</postageFlag> <itemName>送料無料【実物大 超リアル 龍球 7点 セット コスチューム用小物 7cm 】キャラクター グッズ 7個セット 忘年会 孫悟空 7個 ボール 置物 コスプレ 龍珠 7個 玉 球 四星球 神龍 ハロウィン ボールセット ドラゴン ボール DORAGON BALL 宝物探し</itemName> <itemPrice>8980</itemPrice> <pointRateEndTime></pointRateEndTime> <shopCode>rapites</shopCode> <affiliateUrl></affiliateUrl> <giftFlag>0</giftFlag> <shopName>PIRATES SHOP 楽天市場店</shopName> <reviewCount>11</reviewCount> <asurakuArea></asurakuArea> <shopUrl>https://www.rakuten.co.jp/rapites/</shopUrl> <creditCardFlag>1</creditCardFlag> <reviewAverage>4.82</reviewAverage> <shipOverseasArea></shipOverseasArea> <genreId>112938</genreId> <pointRateStartTime></pointRateStartTime> <itemUrl>https://item.rakuten.co.jp/rapites/p-01301/</itemUrl> </Item> <Item> <mediumImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/mangazenkan/cabinet/syncip_0020/to-133_01.jpg?_ex=128x128</imageUrl> </mediumImageUrls> <pointRate>1</pointRate> <shopOfTheYearFlag>0</shopOfTheYearFlag> <affiliateRate>3</affiliateRate> <shipOverseasFlag>1</shipOverseasFlag> <asurakuFlag>1</asurakuFlag> <endTime></endTime> <taxFlag>0</taxFlag> <startTime></startTime> <itemCaption>作者 : 鳥山明 出版社 : 集英社 版型 : 新書版 推定完読時間 : 14時間48分 (漫画全巻ドットコム調べ)あら すじ : 七つ集めれば、どんな願いでも一つだけ叶えてくれる「神龍(シェンロン)」を呼び出すことができる、ドラゴンボール。それ に関わる様々な冒険物語で、人里はなれた山奥に住む尻尾の生えた少年・孫悟空がドラゴンボールを求めて西の都から来た少女・ブルマと出会うところから物語は始まる! ■完全版はこちら ドラゴンボール[完全版] 一緒に買いたい : ドラゴンボール超 ドラゴンボールSD 復刻版ドラゴンボールGTパーフェクトファイル ドラゴンボール超全集 STORY&WORLD GUIDE 銀河パトロール ジャコ ネコマジン [完全版]ドラゴンボール 全巻セットなら、漫画、コミック専門書店の漫画全巻ドットコム</itemCaption> <catchcopy></catchcopy> <tagIds /> <smallImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/mangazenkan/cabinet/syncip_0020/to-133_01.jpg?_ex=64x64</imageUrl> </smallImageUrls> <asurakuClosingTime>12:00</asurakuClosingTime> <imageFlag>1</imageFlag> <availability>1</availability> <shopAffiliateUrl></shopAffiliateUrl> <itemCode>mangazenkan:10000976</itemCode> <postageFlag>0</postageFlag> <itemName>【新品/あす楽】ドラゴンボール[新書版/新装版](1-42巻 全巻) 全巻セット</itemName> <itemPrice>20328</itemPrice> <pointRateEndTime></pointRateEndTime> <shopCode>mangazenkan</shopCode> <affiliateUrl></affiliateUrl> <giftFlag>0</giftFlag> <shopName>漫画全巻ドットコム 楽天市場店</shopName> <reviewCount>44</reviewCount> <asurakuArea>群馬県/埼玉県/千葉県/東京都/神奈川県/富山県/石川県/福井県/山梨県/静岡県/滋賀県/大阪府/兵庫県/奈良県/ 和歌山県/宮城県/山形県/福島県/茨城県/栃木県</asurakuArea> <shopUrl>https://www.rakuten.co.jp/mangazenkan/</shopUrl> <creditCardFlag>1</creditCardFlag> <reviewAverage>4.68</reviewAverage> <shipOverseasArea>オーストリア/オーストラリア/ベルギー/スイス/中国/ドイツ/デンマーク/スペイン/フランス/英国/ギリシャ/香港/インドネシア/インド/イタリア/韓国/モロッコ/マレーシア/オランダ/ニュージーランド/フィリピン/ポーランド/ポルトガル/ロシア/スウェーデン/シンガポール/タイ/トルコ/台湾/ベトナム</shipOverseasArea> <genreId>201998</genreId> <pointRateStartTime></pointRateStartTime> <itemUrl>https://item.rakuten.co.jp/mangazenkan/10000976/</itemUrl> </Item> <Item> <mediumImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_1.jpg?_ex=128x128</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_2.jpg?_ex=128x128</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_3.jpg?_ex=128x128</imageUrl> </mediumImageUrls> <pointRate>1</pointRate> <shopOfTheYearFlag>0</shopOfTheYearFlag> <affiliateRate>4</affiliateRate> <shipOverseasFlag>0</shipOverseasFlag> <asurakuFlag>0</asurakuFlag> <endTime>2021-06-11 01:59</endTime> <taxFlag>0</taxFlag> <startTime>2021-06-04 20:00</startTime> <itemCaption>■メール便発送対応■コスパモデル! 何枚あっても!半袖Tシャツ! 綿100%の天竺素材! 夏には大活躍!夏以外はインナーにも♪ ヘビロテ間違いナシ!! ※メール便発送の為、ラッピングは、ラッピング袋の同梱となります。 ☆ 素材 ☆ 本体:綿100% ゴム編み部分:綿95% ポリウレタン5% ☆ サイズ ☆ 130cm 身長125cm?135cm 140cm 身長135cm?145cm 150cm 身 長145cm?155cm 160cm 身長155cm?165cm ※店頭でも販売している為、稀に在庫が確保できない場合もございます。予めご了承ください。 ※画面環境によっては、画像の色味に多少の差異が生じます。予めご了承ください。 ※沖縄県(本島を除く)・各県の船便地域への宅配便発送は大型便送料となります。</itemCaption> <catchcopy>男の子 キッズ 130cm 140cm 150cm 160cm 春物 夏物</catchcopy> <tagIds> <value>1000331</value> <value>1000332</value> <value>1000333</value> <value>1000859</value> <value>1000873</value> <value>1000877</value> <value>1000881</value> <value>1000885</value> <value>1000886</value> <value>1000902</value> <value>1001077</value> <value>1002298</value> <value>1003434</value> <value>1004015</value> <value>1005802</value> <value>1007663</value> <value>1008853</value> <value>1009107</value> <value>1013424</value> </tagIds> <smallImageUrls> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_1.jpg?_ex=64x64</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_2.jpg?_ex=64x64</imageUrl> <imageUrl>https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_3.jpg?_ex=64x64</imageUrl> </smallImageUrls> <asurakuClosingTime></asurakuClosingTime> <imageFlag>1</imageFlag> <availability>1</availability> <shopAffiliateUrl></shopAffiliateUrl> <itemCode>one-clothing:10018065</itemCode> <postageFlag>0</postageFlag> <itemName>ドラゴンボール超 スーパー Tシャツ 半袖 孫悟空 ベジータ スーパーサイヤ人 fo-ht03【スーパーセール】</itemName> <itemPrice>750</itemPrice> <pointRateEndTime></pointRateEndTime> <shopCode>one-clothing</shopCode> <affiliateUrl></affiliateUrl> <giftFlag>0</giftFlag> <shopName>one clothing</shopName> <reviewCount>4</reviewCount> <asurakuArea></asurakuArea> <shopUrl>https://www.rakuten.co.jp/one-clothing/</shopUrl> <creditCardFlag>1</creditCardFlag> <reviewAverage>4.75</reviewAverage> <shipOverseasArea>ワールドワイド</shipOverseasArea> <genreId>566092</genreId> <pointRateStartTime></pointRateStartTime> <itemUrl>https://item.rakuten.co.jp/one-clothing/fo-ht03/</itemUrl> </Item> <!------------途中省略-----------------> <pageCount>100</pageCount> <TagInformation /> <hits>30</hits> <last>30</last> <count>72287</count> <page>1</page> <carrier>0</carrier> <GenreInformation /> <first>1</first> </root> ソースコードで整形したテキスト 商品名 価格 画像URL(1) 画像URL(2)※ 画像URL(3)※ (空行) getinfo.txt 送料無料【実物大 超リアル 龍球 7点 セット コスチューム用小物 7cm 】キャラクター グッズ 7個セット 忘年会 孫悟空 7個 ボール 置物 コスプレ 龍珠 7個 玉 球 四星球 神龍 ハロウィン ボールセット ドラゴン ボール DORAGON BALL 宝物探し 8980 https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566652.jpg?_ex=128x128 https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076592882.jpg?_ex=128x128 https://thumbnail.image.rakuten.co.jp/@0_mall/rapites/cabinet/imgrc0076566746.jpg?_ex=128x128 【新品/あす楽】ドラゴンボール[新書版/新装版](1-42巻 全巻) 全巻セット 20328 https://thumbnail.image.rakuten.co.jp/@0_mall/mangazenkan/cabinet/syncip_0020/to-133_01.jpg?_ex=128x128 ドラゴンボール超 スーパー Tシャツ 半袖 孫悟空 ベジータ スーパーサイヤ人 fo-ht03【スーパーセール】 750 https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_1.jpg?_ex=128x128 https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_2.jpg?_ex=128x128 https://thumbnail.image.rakuten.co.jp/@0_mall/one-clothing/cabinet/image14/fo-ht03_3.jpg?_ex=128x128 ///途中まで。 ※は商品によっては画像は2枚目以降が無い場合があるので可変です。 終わりに 今回楽天APIを使ってデータの抜き取りにチャレンジしてみましたがHttpClientでドはまりした分を 取り返すべくスムーズに開発ができました。ソフトを作っていくうちに、「これはお金がもらえる技術なのでは?」 と思い始めたのですが誰か金払っても良いよ!って奇特な方いましたらご連絡くださいw データ量が多すぎて抜粋しかできませんでしたが一瞬で100ページのデータが入手できるので 工夫次第では非常に有益な情報を仕入れれると思います。 次はAWS(Amazon Web Service)にチャレンジしたいと思います。 ではまた次回。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む