20190507のC#に関する記事は11件です。

ABC125 - C - GCD on Blackboard(300点)

問題概要

問題へのリンク

$N$ 個の整数 $A_1$,$A_2$,...,$A_N$が並んでいる。$N$個の整数からある一つの値を任意の値に書き換える。
書き換えた後の $N$ 個の整数の最大公約数の最大値を求めよ。

制約条件

  • 入力は全て整数である。
  • $2≤N≤10^5$
  • $1≤A_i≤10^9$

考えたこと

この問題において「ある値を書き換える」という行為は「ある値を排除する」と同義。最大公約数の最大値を求めるので書き換える値はその値を排除した$N-1$個の整数の最大公約数の倍数である任意の値に書き換えればよいので。

例えば入力例1だと 7 6 8 で答えは7を書き換えて2となります。この時7をどんな値に書き換えるかは2の倍数であればなんでもいいわけです。

となると、$N$個の整数の値についてその値がない場合の最大公約数をそれぞれ求めて、最大値を求めればよい。これを毎回最大値を求めていたら計算時間は圧倒的にオーバーするので、累積和的なのりで、ある値 $A_i$ に対して区間$0$ ~ $i-1$と$i+1$ ~ $n-1$の最大公約数をそれぞれ予め求めておく。

こうすれば計算量 $O(N)$ で答えを求めることが可能。

累積和的な考え方についてはTwitterで共有されていた以下の図がすごくわかりやすいです。
https://twitter.com/armeria_betrue/status/1122134567765233665

image.png
image.png

解答

c.cs
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args) {
        int n = int.Parse(Console.ReadLine());
        List<int> a = Console.ReadLine().Split().Select(int.Parse).ToList();
        Console.WriteLine(solve(n, a));
    }
    static int solve(int n, List<int> a) {
        int[] lgcd = new int[n-1];
        lgcd[0] = a[0];
        for(int i = 1; i < n-1; i ++) {
            lgcd[i] = Gcd(a[i],lgcd[i-1]);
        }
        a.Reverse();
        int[] rgcd = new int[n-1];
        rgcd[0] = a[0];
        for(int i = 1; i < n-1; i ++) {
            rgcd[i] = Gcd(a[i],rgcd[i-1]);
        }
        a.Reverse();
        int[] ans = new int[n];
        ans[0] = rgcd[n-2];
        ans[n-1] = lgcd[n-2];
        for(int i = 1; i < n-1; i ++) {
            ans[i] = Gcd(lgcd[i-1], rgcd[n-2-i]);
        }
        return ans.Max();
    }
    static int Gcd(int a, int b) {
        if (a < b) return Gcd(b, a);
        while (b != 0) {
            var tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

一部のHTMLタグだけ許可する

はじめに

Webアプリケーションの要求仕様に、利用者が投稿する文章に、ある程度の装飾ができるようにしたいというものがあると思う。
まぁ、いまどきならMarkdownとかあるのだけど、入力したHTML形式のデータから、許可できるタグ(と属性)だけ抜き出すというプログラムを考えてみた。

参考程度にはなると思う

アーキテクチャ(基本方針)

基本方針はXMLDocumentオブジェクトなど、タグの構造(DOM)を分解するライブラリに掛けることで、DOMの名前と値(と属性)に分離して、特定の名前(と属性)だけをタグとして出力する。

  1. データをDOM化する
  2. nodeごとに再帰する
  3. node.Nameが許可するものだけタグとして出力
  4. node.Attributesを回して、許可タグの許可属性のみ出力する(属性が必要な場合)
  5. 子供のノードがなくなったら(#textノードになると思う)、node.ValueをHTML/XMLエスケープして出力
  6. 子供のノードがあれば、2へ戻る

こんな感じ

テスト結果

test.png

こんな感じ。・・・まぁまぁ、いい感じだと思う。

利用しているライブラリ「SGMLReader」の関係上、入力データ全体をHTMLタグで囲んでいる。

サンプルコードについて

サンプルはC#/.NET Frameworkだけど、JavaとかでPHPには移植しやすいと思う。

サンプルはHTML形式の解析にSGMLReaderを使った。
標準のSystem.Xml.XmlDocuemtクラスだと、HTMLでは有効だけど、XMLではダメな形式のやつとかだと例外が出たりして厳密過ぎて面倒なので、ある程度よきに計らってくれるSGMLReaderにしてみたけど、好きなXML解析ライブラリを使えばよいと思う。

サンプルは、Bタグと、Iタグと、FONTタグのCOLORとSIZE属性だけ許可するようにしているので、そのswichブロック(56行目あたり)を、改造すればよいと思う。

サンプルは、単純なfor文だけど、Linqやラムダ式とかで、並列実行できるようにすれば、処理速度は上がると思うので、実際に使う際は、そういう改造をした方がよいと思う。

サンプルは、HTMLエスケープとしてSystem.Security.SecurityElement.Escape()メソッドを使っているけど、System.Net.WebUtility.HtmlEncode()メソッドなどの方が適切かもしれない。

サンプルコードについて(属性値がURLの場合のチェック)

例えば、AタグのHREF属性とか、属性値がURLの場合、javascript:...とかで任意のスクリプトが動作するかもしれないので、そういう属性を許可する場合は、サンプルコードには記述されていないが、属性値の入力チェックが必要だ。
まぁ、大まかな方向性としては先頭一致で「https://」と「http://」のみ許可。とか、先頭に「/./」または「./」を付与とかでいいと思う。

サンプルコードについて(XXE)

実際にこういう方針でプログラムを組む場合、入力データをDOMとして読み込むのだから、XXE攻撃には対処しておく必要がある。
XXE攻撃については、XXE基本編なり、XXEで検索すればよいと思う。

サンプルコード(Program.cs)

SGMLReaderを参照設定すること

using System;
using System.IO;
using System.Xml;
namespace StripHTMLs{
    class Program{
        static void Main(string[] args){
            StreamReader reader = new StreamReader(new FileStream(args[0], FileMode.Open, FileAccess.Read));
            String motoData = reader.ReadToEnd();
            Console.WriteLine("FileName: " + args[0]);
            Console.WriteLine("Input Data is: ");
            Console.WriteLine(motoData);
            Console.WriteLine("========================");
            Console.WriteLine("ans is");

            Sgml.SgmlReader tempSgmlReader = new Sgml.SgmlReader();
            tempSgmlReader.DocType = "HTML";
            tempSgmlReader.IgnoreDtd = true;

            StringReader tempStringReader = new StringReader(motoData);
            tempSgmlReader.InputStream = tempStringReader;

            XmlDocument myXmlDocument = new XmlDocument();
            myXmlDocument.Load(tempSgmlReader);

            try{
                String str = "";
                XmlNodeList myXmlNodeList = myXmlDocument.ChildNodes;
                for(int i=0;i<myXmlNodeList.Count;i++){
                    str += EscapeHTML(myXmlNodeList[i]);
                }
                Console.WriteLine(str);
            }catch (Exception ee){
                Console.Error.WriteLine(ee.ToString());
            }
        }

        private static String EscapeHTML(XmlNode node) {
            // B and I and Font/Color/Size permit only
            String ansStr = "";
            String tagStart = "";
            String tagEnd = "";
#if DEBUG
            Console.WriteLine("node.name:" + node.Name);
            Console.WriteLine("node.value:" + node.Value);
            Console.WriteLine("node.HasChildNodes:" + node.HasChildNodes.ToString());
#endif
            //
            switch (node.Name.ToLower()) { 
                case "b":
                    tagStart = "<b>";
                    tagEnd = "</b>";
                    break;
                case "i":
                    tagStart = "<i>";
                    tagEnd = "</i>";
                    break;
                case "font":
                    tagStart = "<font";
                    tagEnd = "</font>";
                    XmlAttributeCollection xmlAttributeCollection = node.Attributes;
                    foreach(XmlAttribute attr in xmlAttributeCollection){
                        switch (attr.Name.ToLower()) {
                            case "color":
                            case "size":
                                tagStart += " " + attr.Name + "=\"" + System.Security.SecurityElement.Escape(attr.Value) + "\"";
                                break;
                        }
                    }
                    tagStart += ">";
                    break;
            }
            if (node.HasChildNodes == true){
                XmlNodeList list = node.ChildNodes;
                for (int i = 0; i < list.Count; i++) {
                    ansStr += EscapeHTML(list[i]);
                }
            }else {
                ansStr = System.Security.SecurityElement.Escape(node.Value);
            }
            return tagStart + ansStr + tagEnd;
        }
    }
}

サンプルコードの修正

不許可なタグは、エスケープするのが、適切かもしれない。
そういう場合は、タグ(ノード)の名前のswitch文のところに、
以下の感じのコードを入れるといいかもしれない。

default:
  if (node.Name.StartsWith("#") == false) { 
    // "#"で始まらないノードのみ
    tagStart = "<" + node.Name;
    tagEnd = System.Security.SecurityElement.Escape("</" + node.Name + ">");
    XmlAttributeCollection xmlAttributeCollection0 = node.Attributes;
    foreach (XmlAttribute attr in xmlAttributeCollection0){
      tagStart += " " + attr.Name + "=\"" + System.Security.SecurityElement.Escape(attr.Value) + "\"";
    }
    tagStart = System.Security.SecurityElement.Escape(tagStart + ">");
  }
  break;

これでも、元データを適切に再現しているかというと、以下の点で、そうではなかったりするので、入力されたデータを改変しないという情報処理の基本からは外れてしまうのが、心残り

  • 元データに閉じタグのない場合は、閉じタグが出現してしまう
  • 属性値の順番が for文で一致しているといいけど、保証されていないと思う

サンプルコードの修正の蛇足 ~タグ内部での属性のエスケープ~

これは無理かと思う。

つまり、許可タグの中の不正な属性は、出力されたデータからは排除するしかないと思う。
これも、入力されたデータを改変しないという情報処理の基本からは外れてしまうけど・・・これはさすがにしょうがないのではないかという部分ではないかと思う

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

OXYPlotで"System.InvalidOperationException"の例外が発生したときの対応

OXYPlotでリアルタイムにグラフを更新していると以下の画像のような例外がplotmodelから発生することがあります。
OXYPlot.JPG

この例外を発生させないようにするには、以下のようにInvalidatePlotにfalseを設定します。

InvalidatePlot(false)

以前の記事から少しアップデートです。プログラムの最後の行が変更点です。

プログラム例

PlotViewRefreashExample.cs
var myPlotModel = new PlotModel(); //PlotModelの生成
myPlotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = 0.0, Maximum = 1.0 }); //x軸の設定
myPlotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Minimum = 0.0, Maximum = 1.0 }); // y軸の設定

plotView1.Model = myPlotModel; // plotView1はPlotViewコントロール

LineSeries myLine = new LineSeries(); //データインスタンスを生成

myPlotModel.Series.Add(myLine); //データをPlotModelへバインド

for(int i = 0; i < 10; i++)
{

   myLine.Points.Add(new DataPoint(i, i)); //データの変更

   plotView1.Invalidate(); // PlotViewが更新される

   myPlotModel.Axes.Clear(); // 軸の変更のため、以前の設定をクリア
   myPlotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = 0.0, Maximum = i }); //x軸の設定
   myPlotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Minimum = 0.0 , Maximum = i }); //y軸の設定
   myPlotModel.InvalidatePlot(false); // -- 変更点 ---
}

InvalidatePlotの値はtrueでもfalseでも問題無いようです。

ちなみにですが、リアルタイム更新は5msecくらいでもプログラム的には可能です。しかし、FPSの観点から60FPS(約16msec間隔)にとどめておく方が良いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ImportedLinqのススメ ~C#でも他の言語にあるMaxByやFlattenを!~

プログラミングにおいて、配列、リスト、シーケンスなどのコレクションを扱う機会は非常に多いです。「プログラミング言語でコレクションがどれくらい扱いやすいか」は重要な点だと筆者は考えます。

さてC#には、コレクション関連の言語機能として「LINQ」が、10年以上前、C# 3.0の頃からあります。そんなLINQですが、後発のプログラミング言語のコレクション機能と比べると、不足している部分があると筆者は考えました。

そんな考えから筆者は「ImportedLinq」というライブラリを作成しました。

この投稿では、「ImportedLinq」作成の背景と使用例を紹介します。

こんなことしたいけど、LINQじゃできない

このようなクラスを使って説明します。ゲームでのロジックをイメージしてください。

class Monster
{
    public int Level { get; private set; }
    /* 略 */
}

モンスターのリストがあります。この中から一番高いレベルの値を求めます。どんなコードを書けばいいでしょうか?

IReadOnlyList<Monster> monsterList = LoadMonsterList();
int maxMonsterLevel = ???;

このような場合、LINQのMaxメソッドを使うことで、非常に簡潔に、次のコードのように1行で書くことができます。

IReadOnlyList<Monster> monsterList = LoadMonsterList();
int maxLevel = monsterList.Max(it => it.Level);

このように、LINQを使えば、短く、読みやすいコードで実装できます。


モンスターのリストがあります。この中から「一番レベルの高いやつ」を探します。どんなコードを書けばいいですか?

IReadOnlyList<Monster> monsterList = LoadMonsterList();
Monster maxLevelMonster = ???;

先ほどと似たような問題ですが、違いに注目してください。見つけたいのは、「一番高いレベル」ではなく、「一番高いレベルを持ったモンスターの要素」です。

実は、これを実現できるLINQのメソッドは残念ながらありません。


さて、解決策・コードを紹介する前に、次の例を示します。

モンスターのリストがあります。表示のために、先頭から8個ごとにグループ分けし、リストのリストを作りたいです。 どんなコードを書けばいいでしょうか?

IReadOnlyList<Monster> monsterList = LoadMonsterList();

// 型は
// List<List<Monster>>?
// IEnumerable<IList<Monster>?
// IEnumerable<IReadOnlyList<Monster>?
var monsterListOfList = ???

残念ながら、これも一発でかけるC#・LINQのメソッドはありません。


次の例です。

モンスターのリストのリストがあります。 これを平滑化し、IEnumerable<Monster>なmonstersを作りたいです。どんなコードを書けばいいでしょうか?

List<List<Monster>> monsterListOfList = LoadMonsterListOfList();
IEnumerable<Monster> monsters = ???

これはLINQを使って一行で書けます。

List<List<Monster>> monsterListOfList = LoadMonsterListOfList();
IEnumerable<Monster> monsters = monsterListOfList.SelectMany(it => it);

SelectManyを使えば、リストのリストの平滑化は実現することできます。ですが、上記のSelectManyのコードは 「平滑化する」という意図が伝わりにくいと思います。


最後の例です。

IEnumerable<Monster>なmonstersがあります。 これが空かどうかを調べたいです。 どんなコードを書けばいいですか?

IEnumerable<Monster> monsters = LoadMonsters();
bool isEmptyMonsters = ???

これもLINQで書けます。しかし、゙注意が必要です。

IReadOnlyList<Monster> monsterList = LoadMonsterList(); // 良い例
bool isEmptyMonsters = !monsterList.Any();

// 悪い例
// DBから読み場合最後まで読むという無駄な処理が必要
// 無限なシーケンスだと終わらない
// bool isEmptyMonsters = monsterList.Count() == 0;

コメントにもある通り、IEnumerable<T>のシーケンスがから空かどうかの判定は、Countではなく、Anyを使うべきです。

LINQおよび配列などのメソッド・プロパティとして「空かどうかを判別する」ためのメンバは存在しません。


  • モンスターのリストから一番高いレベルのモンスターを探したい
  • モンスターのリストを先頭からn個ごとにまとめたい
  • モンスターのリストのリストを平滑して、モンスターのシーケンスを作りたい
  • モンスターのリストが空かどうかを判別したい

ゲーム開発、ウェブ開発、モバイル開発、デスクトップアプリ開発などにおいて、このような処理をやりたい状況があると思います。

  • モンスターのリストから一番高いレベルのモンスターを探したい
  • モンスターのリストを先頭からn個ごとにまとめたい

残念ながらこれらができるLINQはありません。このような処理ができるメソッドがあれば嬉しくないですか?

  • モンスターのリストのリストを平滑して、モンスターのシーケンスを作りたい
  • モンスターのリストが空かどうかを判別したい

これらはLINQで書けますが、もっとわかりやすくならないでしょうか?

他の言語にはある

  • モンスターのリストから一番高いレベルのモンスターを探したい
  • モンスターのリストを先頭からn個ごとにまとめたい
  • モンスターのリストのリストを平滑して、モンスターのシーケンスを作りたい
  • モンスターのリストが空かどうかを判別したい

Java、Kotlin、Scala、Groovy、F#、Haskellなど他のプログラミング言語にはこれらができるコレクション機能があります。

しかし、C#・LINQにはそのようなメソッドがありません。

他の言語のコレクションメソッド群と比べて 、「C#・LINQがちょっと弱いのでは?負けているのでは?」と感じてしまいました。また、もっとC#・LINQをもっと改善したい、拡充したいと思いました。

ということで作った!

ということで作りました!

ImportedLinq」というライブラリです。

『「他の言語のコレクションで一般的だけど、C#・LINQにはないメソッド」を、 他のプログラミング言語から輸入(Imported)して、 C#・LINQにフィットするようにしたコレクションメソッドライブラリ』

です。

ImportedLinqの利用例を紹介!

それでは、「ImportedLinq」の利用例を紹介します。


「MaxBy」を使ってモンスターのリストから、一番高いレベルのモンスターを探すコード。

IReadOnlyList<Monster> monsterList = LoadMonsterList();

// MaxByは一番大きい要素(複数)を探すメソッド
IReadOnlyCollection<Monster> maxLevelMonsters = monsterList.MaxBy(it => it.Level);

「Buffer」を使って モンスターのリストを、8個ごとにグループ分けするコード。

IReadOnlyList<Monster> monsterList = LoadMonsterList();

// Bufferは先頭から指定数ごとにまとめるメソッド
IEnumerable<IReadOnlyList<Monster>> bufferedMonsters = monsterList.Buffer(8);

「Flatten」を使ってモンスターのリストのリストを平滑化し、IEnumerableを作るコード。

List<List<Monster>> monsterListOfList = LoadMonsterListOfList();

// Flattenは、リストのリストなどをIEnumerable<T>に平滑化するメソッド
// 「平滑化するよ」ということがメソッド名から伝わる
IEnumerable<Monster> monsters = monsterListOfList.Flatten();

「IsEmpty」を使ってIEnumerableなmonstersが、空どうかを調べるコード

IEnumerable<Monster> monsters = LoadMonsterList();

// メソッド名が超わかりやすい!
// 無限シーケンスでも終わるし、余分な処理しない 
bool isEmptyMonster = monsters.IsEmpty();

  • モンスターのリストから一番高いレベルのモンスターを探したい
  • モンスターのリストを先頭からn個ごとにまとめたい

上記の処理はLINQを使って書くことができませんが、ImprotedLinqを使えば一発で書くことができます。

  • モンスターのリストのリストを平滑して、モンスターのシーケンスを作りたい
  • モンスターのリストが空かどうかを判別したい

上記の処理は、ImprotedLinqを使えばより読みやすいコードで実装することができます。

「便利なコレクションメソッドの詰め合わせ」ではない

ImportedLinq」は 「便利なコレクションメソッドの詰め合わせ」 ではありません。

『「ImportedLinq」は「他の言語のコレクションで一般的だけど、C#・LINQにはないメソッド」を、 他のプログラミング言語から輸入(Imported)して、 C#・LINQにフィットするようにしたコレクションメソッドライブラリ』です。

「他の言語の便利なコレクションメソッドを、C#でも使いたい」というのが目的です。

また

「他の言語に慣れている人の「C#になんでこのコレクションメソッド無いの」を解決したい」というのも目的です。

今後、他の言語で活用されていて、C#でも活躍する場面がありそうなメソッドがあれば、追加していきたいと思います。

他のコレクションライブラリと比べて

C#におけるコレクションライブラリ、「ImportedLinq」以外にもあります。たとえば次の二つです。

  • Ix.NET
  • MoreLINQ

ImportedLinqはこれらとは目的やモットーが異なります。


Ix.NETはRx.NETのIEnumerable版です。

Ix.NETはRx.NETにないメソッドは入りません。「こんなメソッドがあればいいのに」と思ってもRx.NETになければ入らないのです。


MoreLINQは便利なメソッドがたくさんあるライブラリです。

覚えきれないくらいたくさんあります。しかし、現段階ではFlattenとかIsEmptyなどは実装しないそうです。詳しくは、こちらをご覧ください。


繰り返しになりますが、ImportedLinq

『「他の言語のコレクションで一般的だけど、C#・LINQにはないメソッド」を、 他のプログラミング言語から輸入(Imported)して、 C#・LINQにフィットするようにしたコレクションメソッドライブラリ』

というライブラリです。

使ってみてね!ImportedLinq!

ソースコードはこちら。他のメソッドの紹介もあります!

NuGetはこちら

Unityでの利用は、こちらからunitypackageをダウンロードできます。

使ってみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity:UIElements の使い方(Unity2019新機能)

はじめに

こんにちは、のんびりエンジニアのたっつーです。
ブログを運営しているのでよろしければ見てください。

今回はUnity 2019の新機能、UIElements の使い方を解説してみようと思います。
ぜひ、お付き合いいただければと思います。

UIElementsとは?

従来のエディタ拡張システムの ImGui を置き換える新しいGUIシステムになります。また、将来的にはランタイムのUI(uGUI)もこの UIElements に置き換わるとされています。

aaa.png

開発者がUIレイアウトおよびスタイル設定をすばやく作成および編集できるようにする新しい保持モードのGUIシステムです。
新しいGUIシステムは、UnityのUIの作成と最適化を容易にするために、WebのCSS、jQuery、HTML DOM、およびEventsシステムから概念を借りています。

また、パフォーマンスが向上し、スタイルシートや動的/コンテキストイベント処理などの多くの新機能も提供されます。

パフォーマンスとスケーラビリティを念頭に置いて新しいシステムを構築したので、開発者がUIを構築、変更、および対話することを可能にする従来の包括的なC#APIがあります。
使い慣れたC#API、イベントシステム、CSS、およびXMLのインポート形式により、ユーザーインターフェイスを簡単に構築できます。
UI Elementsは、エディタUIを拡張および作成するためのIMGUIに代わるものであり、将来のリリースではランタイムUIを作成するためにuGUIに代わるものとなるでしょう。
https://blogs.unity3d.com/jp/2019/04/16/introducing-unity-2019-1/#uielements

つまり何が言いたいかと、、、

こうゆう事風にエディタを拡張できます。(今)

image-217.png

こうゆう事がuGUIが将来的にUIElementsでできるようになります。(未来)

8420_main.jpg

UIElements はどんな事に使える?

Unity:UIElements の使い方(Unity2019新機能)をご参照ください。

使い方

ウィンドウの新規作成

非常に簡単に作成できます、まずはEditorフォルダを作成してください。
次に、右クリックから Create > UIElements Editor Window を選択してください。

uielements-001.png

UIElements のウィンドウ作成ウィザードが表示されるので、今回は「TestWindows」と入力しました。
次に、「Open file 〜」をオンにして、「Confirm」ボタンを選択してください。

uielements-002.png

おめでとうございます。
もう新規ウィンドウが作成できました!!

uielements-003.png

作成ウィザードのおかげで、以下の3ファイルがすでに作成されています。

uielements-004.png

ウィンドウを間違えて閉じてしまった場合は、メニューのWindow > UIElements > TestWindows を選択すれば再度表示が行えます。

uielements-005.png

ソースコードを確認してみる。

Unity:UIElements の使い方(Unity2019新機能)をご参照ください。

個別のスクリプトにUIElementsを使う

最後にサンプルで、個別のスクリプトにUIElementsを使ってみようと思います。

上記のサンプルのC#ソースコードを以下のように変更しました、内容としては AAA スクリプトに UIElements を適用するって感じの内容です。

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.UIElements;

[CustomEditor(typeof(AAA))]
public class TestWindows : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();

        // VisualElements objects can contain other VisualElement following a tree hierarchy.
        VisualElement label = new Label("Hello World! From C#");
        root.Add(label);

        // Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/TestWindows.uxml");
        VisualElement labelFromUXML = visualTree.CloneTree();
        root.Add(labelFromUXML);

        // A stylesheet can be added to a VisualElement.
        // The style will be applied to the VisualElement and all of its children.
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/TestWindows.uss");
        VisualElement labelWithStyle = new Label("Hello World! With Style");
        labelWithStyle.styleSheets.Add(styleSheet);
        root.Add(labelWithStyle);

        return root;
    }
}

すごく簡単にAAAスクリプトに UIElements を適用できました。
これでリッチなテキスト・ボタンを設定したり画像を表示したりといろいろできそうですね。

uielements-006.png

以前書いた記事で、インスペクターに画像を表示するをやりましたが。
UIElementsバージョンだともっと簡単に記述できそうですね、時間があれば試してみたいと思います!

懸念点

表現力が高いUIが氾濫して、UIの統一感がなくなるのでは?と思っています。

終わりに

よければ ブログ「初心者向けUnity情報サイト」の方にも色々記載しているのでぜひご参照いただければと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity:アセット(Asset)のインポートの方法(5種類!?)

はじめに

こんにちは、のんびりエンジニアのたっつーです。
ブログを運営しているのでよろしければ見てください。

Unity では、Asset Store や Github で 「~.unitypackage」ファイルをダウンロードして使う事がありますよね。

今回はこの .unitypackage ファイルをインポートして使う方法/Asset Storeでインポートして使う方法をいくつかご紹介させていただきます。

インポートの使い方

インポート方法についてはブログに使い方を記載しましたのでこちらをご参照ください。

インポートの種類

アセットを組み込む方法は実はいくつかありますが、皆さんはいくつわかりますでしょうか?

私が調べた感じでは実は5種類のアセットの組み込み方法が存在します。
5種類ってすごくないですか!?

さっそくそれぞれの方法をご紹介させていただきます。

1.ドラッグアンドドロップ

一番シンプルだと思う手順ですね。~.unitypackage をドラッグアンドロップで Assets のフォルダに配置
するとインポートが行えます。

※この方法はローカルに ~.unitypackage が無いと使えません。

import1.jpg

2.メニューからインポート

次にやるのはメニューからインポートするパッケージを選ぶ豊富です、こちらもポピュラーなやり方で皆さん知っているかと思います。

※この方法はローカルに ~.unitypackage が無いと使えません。

import2.jpg

3.Asset Storeからインポート

次の方法は、Asset Storeウィンドウを開いて、アセットを検索してページを開いてからインポートを実行するやり方です。

※この方法は Asset Store を使う方法として一般的です。
※ちなみにファイルの保存先は以下の保存先に保存されます。
 (C:\Users\%USERNAME%\AppData\Roaming\Unity\Asset Store-5.x)

import3.jpg

4.PackageManager を使う

Unity 2018 移行では PackageManager の機能が追加されました。この機能はUnityの公式パッケージを配布するための方法として実装されているようです。そのためUnityが公式で配布しているアセットはインストールが行えます。

image-212.png

image-213.png

5.manifest.json を記述する

こちらの記事で使っていますが、プロジェクトに保存されている「manifest.json」にURLを追加すると自動的にアセットがインストールされます。
これは PackageManager はUnity公式の配布で利用されていますが、manifest.jsonを変更する事により、第三者でもパッケージの配布が行えることを指します。(Unity的にはこの使い方はグレー・・・?)

Package > manifest.json に保存されているファイルを編集するので、エクスプローラーで探してエディタで開きましょう。

image-114.png

テキストファイルの先頭に「”com.beans.deform”: “https://github.com/keenanwoodall/Deform.git”,」を追加します。

image-115.png

最後に

どうでしたでしょうか、最後の manifest.json を変更する方法は知らない方が多かったのではないでしょうか。
Unity の PackageManager が追加されてから パッケージの管理の複雑さが増した感じがしますがすごく便利なのでぜひ積極的に活用してみましょう!

よければ ブログ「初心者向けUnity情報サイト」の方にも色々記載しているのでぜひご参照いただければと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【.NET 5】 がやってくる!

この記事 is 何?

.NETブログ に投稿された「Introducing .NET 5」という記事を掻い摘んで紹介するなんちゃって翻訳記事です。

TL;DR;

  • .NET Core の次期バージョンから【.NET 5】って名前になるからよろしくね!
  • その兼ね合いで.NET Frameworkなくなるよ!
  • Monoは、もうしばらく残るよ!

.NET - 統一プラットフォーム

現在.NETのプラットフォームには, .NET Core / .NET Framework / Mono という3種類のフレームワークがありますが, 今後これらを統合して .NET という一つのプラットフォームとなります.

.NET 5 以降からは, Windows / Linux / macOC / iOS / Android / tvOS / watchOS / WebAssembly などをターゲットにすることが可能となります.

また, .NET を作成するために .NET CoreMono を使用しています. .NET Framework については, 現時点でその大部分を .NET Core 3.0 に統合が完了しており, 残りもわずかとなっています.

.NET 5 の最初のプレビューは2020年前半を予定しており, 2020年11月のリリースを予定しています.

.NET 5 = .NET Core vNext

.NET プロジェクト.NET Core プロジェクト の次のステップです. .NET 5は主に以下のような点での .NET の向上を目指しています.

  • どんなプラットフォーム上でも動作し, 実行時の挙動や開発者の経験が統一された単一の.NETランタイムとフレームワークを作成する.
  • .NET Core / .NET Framework / Xamarin / Mono を最大限に活かして, .NETの機能を拡張する.
  • .NETの開発者(= Microsoft と コミュニティ) が単一のコードベースからプロダクトを構築することが可能になることで, すべてのシナリオが改善される.

この新しい .NET プロジェクト は, .NETにとって大きな変革となります.
.NET 5 では, 作成するアプリの種類に関係なく, コードファイルとプロジェクトファイルは同じように見えます. これは, 各アプリで同じ ランタイム / API / 言語機能 にアクセス可能であることを意味しています.

また, .NET Core プロジェクト のオープン性やハイパフォーマンスな点などについては, 今後も変わらずに担保されます.

おわりに

原文はもっといろいろなことが記載されていますが, 今回はおそらく大部分の方が気になる点についてのみ抜き出してきました.
.NET Core と Mono の今後についてや, どういった方向でフレームワークが開発されていくのかが気になるかたは, 原文を読んでみてみると良いかもしれません.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

環境依存文字をJIS X 0208の異字体に置換するソフトの作成

CP932の環境依存文字(機種依存文字)をJIS X 0208の異字体・俗字に置き換えるソフトを作ってみる。

予備知識

本記事では、次の理解があるものとして話を進める。

  • 文字符号化方式(エンコーディング)と符号化文字集合(キャラクタセット)の違いを知っている。
  • JIS X 0208符号化文字集合のひとつであり、その文字符号化方式にはShift_JISEUC-JPISO-2022-JPなどがあること。
  • Unicode符号化文字集合のひとつであり、その文字符号化方式にはUTF-8UTF-16などがあること。
  • CP932は、Shift_JIS符号化文字集合をマイクロソフト社が独自に拡張したものであること。

一般に「文字コード」と言われれば文字符号化方式を指すが、厳密には異なる。
もし新人SEがUnicodeUTF-8の違いを質問してきたら、それは「文字コード」が文字符号化方式符号化文字集合で構成されていることを理解していない。

なお、CP932については、
https://qiita.com/kasei-san/items/cfb993786153231e5413
で詳しく解説されているので、本記事では言及しない。

開発のきっかけ

今のeLTAX(地方税の電子申告システム)では、JIS X 0208で定義されていない環境依存文字、半角カナ、JIS第3水準漢字、JIS第4水準漢字を扱えないので、これらを似たような文字に置き換えてしまおうというのが発端。
ちなみに総務省発表によると、扱える文字の不足問題は2019年9月に改善される予定とのことで今後に期待するとしよう。
image.png
なお、e-Tax(国税の電子申告システム)では、JIS X 0221UTF-8で符号化した文字コードを扱えるため上図に示した文字では問題は発生しないが、「?」(の下に。某牛丼チェーンでも使われている文字)のようにサロゲートペアの文字は扱えない。

そもそも異字体・俗字とは何か

異字体・俗字に明確な定義づけがあるわけではない。
同じ意味の漢字ではあるものの、字体が少し異なっているものとし、ここでは、旧字体古字も異字体に含まれると定義する。

ソフトの性質上、人名と地名で使われる漢字に集中するわけだが、まずは該当文字を洗い出し、文字単位で変換辞書を作成するところから始めた。
CP932で拡張された文字が対象なので、JIS X 0208に存在する文字は除外する。

変換される漢字の例

JIS X 0208に存在しないので変換する。

  • 橋 一生 :arrow_forward: 橋 一生
  • 濵﨑 あゆみ :arrow_forward: 浜崎 あゆみ
  • はるか :arrow_forward: はるか
  • 永 英明 :arrow_forward: 永 英明

変換されない漢字の例

旧字体ではあるがJIS X 0208にも存在する漢字なので変換しない。

  • 藤 由貴 :arrow_forward: 藤 由貴
  • 森山 未 :arrow_forward: 森山 未
  • 木 よう子 :arrow_forward: 木 よう子
  • 井 翔 :arrow_forward: 井 翔
  • :arrow_forward:
  • 國學院大 :arrow_forward: 国学院大

中国の人名など

日本国内で流通していない漢字、中国の一部の人名用漢字については、ピンイン、中国語読みのカナ表記、日本語読みのカナ表記のいずれかに変換できるようにした。
日本に伝えられた漢字の読み方(音読み)には、呉音(主に百済人によって伝えられた中国南方系の読み方)、漢音(奈良~平安時代に伝えられた中国北方系の読み方)、唐音(主に鎌倉時代に伝えられた江南浙江地方の読み方)があるが、中国の人名を日本語で読む場合は漢音が多いので、ソフトでは漢音に統一した。

変換できない文字

苗字の棈松(アベマツ)の「」、地名の荢千場(ウホシバ)の「」、苗字と地名の双方に使われている橳島(ヌデシマ)の「」などは、JIS X 0208の中に適当な文字が見つからなかった。「橳」の俗字として「椦」を確認できたものの、典拠が不明な幽霊文字なので採用しなかった。
また、岩手県には霻霳(ホウリョウ)という、JIS X 0208にない文字だけで構成された地名があり「豊隆」と書き換えた文献も確認しているが、ソフトは単語単位ではなく文字単位で見るので「豊隆」には変換されない。

変換が必要なのに変換できなかった文字、つまり辞書に無い文字は、ユーザーの判断に委ねることにした。

ソースコード

C# のソースコードを一部抜粋する。

文字チェック関数

CP932で拡張された文字なら 0 以外を返す。
EncodingにShift_JISを指定しているが、これは .NET Framework に該当するコードページが無いからで、要はCP932と同じである。
.NETCP932Shift_JISを区別する関数としても使えるだろう。

Encoding sjis = Encoding.GetEncoding("Shift_JIS", EncoderFallback.ExceptionFallback, DecoderFallback.ReplacementFallback);
private int getBadChar(char c) {
    byte[] bytes = sjis.GetBytes(c.ToString());
    if (bytes.Length == 1) return 0;  // 半角なら
    if (BitConverter.IsLittleEndian) Array.Reverse(bytes);  // 上位バイトと下位バイトを入れ替える
    int code = BitConverter.ToUInt16(bytes, 0);

    // 文字コードチェック(チェック範囲は下位1バイトが 0x40~0x7e、0x80~0xfc にあるもの)
    if ((code >= 0x81ad && code <= 0x81b7) || (code >= 0x81c0 && code <= 0x81c7) || (code >= 0x81cf && code <= 0x81d9) ||
        (code >= 0x81e9 && code <= 0x81ef) || (code >= 0x81f8 && code <= 0x81fb) || (code >= 0x81fd && code <= 0x824e) ||
        (code >= 0x8259 && code <= 0x825f) || (code >= 0x827a && code <= 0x8280) || (code >= 0x829b && code <= 0x829e)) {
        return code;  // 記号、桁、ラテン
    }
    if ((code >= 0x82f2 && code <= 0x82ff) || (code >= 0x8397 && code <= 0x839e)) {
        return code;  // ひらがな、カタカナ
    }
    if ((code >= 0x83b7 && code <= 0x83be) || (code >= 0x83d7 && code <= 0x83df) || (code >= 0x8461 && code <= 0x846f) ||
        (code >= 0x8492 && code <= 0x849e) || (code >= 0x84bf && code <= 0x889e)) {
        return code;  // ギリシャ文字、キリル文字、特殊文字
    }
    if ((code >= 0x9873 && code <= 0x989e) || (code >= 0xeaa5)) {
        return code;  // 漢字
    }
    return 0;
}

文字変換関数

上述の文字チェック関数で 0 以外を返した文字は、文字変換関数に渡す。
これでJIS X 0208で表現できる文字列となる。定義が無ければ null を返す。

private string replaceChar(char badChar) {
    switch (badChar) {
        case '髙': return "高";
        case '﨑': return "崎";
        case '濵': return "浜";
        case '賴': return "頼";
        case '瀨': return "瀬";
        case '德': return "徳";
        case '蓜': return "配";
        case '昻': return "昂";
        case '桒': return "桑";
        case '栁': return "柳";
        case '犾': return "犹";
        case '琪': return "棋";
        case '裵': return "裴";
        case '魲': return "鱸";
        case '羽': return "羽";
        case '焏': return "丞";
        case '祥': return "祥";
        case '曻': return "昇";
        case '敎': return "教";
        case '澈': return "徹";
        case '曺': return "曹";
        case '黑': return "黒";
        case '塚': return "塚";
        case '閒': return "間";
        case '彅': return "薙";
        case '匤': return "匡";
        case '冝': return "宜";
        case '埇': return "甬";
        case '鮏': return "鮭";
        case '伹': return "但";
        case '杦': return "杉";
        case '罇': return "樽";
        case '柀': return "披";
        case '﨤': return "返";
        case '寬': return "寛";
        case '神': return "神";
        case '福': return "福";
        case '礼': return "礼";
        case '贒': return "賢";
        case '逸': return "逸";
        case '隆': return "隆";
        case '靑': return "青";
        case '飯': return "飯";
        case '飼': return "飼";
        case '緖': return "緒";
        case '埈': return "峻";
        case '①': return "(1)";
        case '②': return "(2)";
        case '③': return "(3)";
        case '④': return "(4)";
        case '⑤': return "(5)";
        case '⑥': return "(6)";
        case '⑦': return "(7)";
        case '⑧': return "(8)";
        case '⑨': return "(9)";
        case '⑩': return "(10)";
        case '⑪': return "(11)";
        case '⑫': return "(12)";
        case '⑬': return "(13)";
        case '⑭': return "(14)";
        case '⑮': return "(15)";
        case '⑯': return "(16)";
        case '⑰': return "(17)";
        case '⑱': return "(18)";
        case '⑲': return "(19)";
        case '⑳': return "(20)";
        case 'Ⅰ': return " I ";
        case 'Ⅱ': return " II ";
        case 'Ⅲ': return " III ";
        case 'Ⅳ': return " IV ";
        case 'Ⅴ': return " V ";
        case 'Ⅵ': return " VI ";
        case 'Ⅶ': return " VII ";
        case 'Ⅷ': return " VIII ";
        case 'Ⅸ': return " IX ";
        case 'Ⅹ': return " X ";
        case '㎜': return "mm";
        case '㎝': return "cm";
        case '㎞': return "km";
        case '㎎': return "mg";
        case '㎏': return "kg";
        case '㏄': return "cc";
        case '㎡': return "m2";
        case '㍻': return "平成";
        case '㋿': return "令和";
        case '〝': return "“";
        case '〟': return "”";
        case '№': return "No.";
        case '㏍': return "K.K.";
        case '℡': return "Tel";
        case '㈱': return "(株)";
        case '㈲': return "(有)";
        case '㈹': return "(代)";
        case '㍾': return "明治";
        case '㍽': return "大正";
        case '㍼': return "昭和";
    }
    return null;
}

なお、完成したソフトの方は、オンラインソフトウェア流通サイト Vector で無償配布させていただいた。
興味のある人は使ってみて欲しい。
https://www.vector.co.jp/soft/winnt/business/se518540.html
tool.png
※人名・住所は架空のもの。

参考URL

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NET Core 3.0 の目玉の single exe を preview5 で試してみた

.NET Core 3.0 の目玉の single exe を preview5 で試してみた

.NET Core 3.0 の目玉の single exe がどれくらいのサイズになるのか興味があって、 preview5 で試してみた.
Hello World が 67MB だった.
出来た EXE を .NET Core 3.0 preview が入っていない別のマシンに持っていって動くことは確認できたが、Assembly trimmer 待ちかなあと思わされるサイズである.

C:\Users\user\source\repos\ConsoleApp1>type ConsoleApp1\Program.cs
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

C:\Users\user\source\repos\ConsoleApp1>dotnet publish -r win10-x64 -c Release /p:PublishSingleFile=true
Microsoft (R) Build Engine version 16.0.462+g62fb89029d for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 33.73 ms for C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\ConsoleApp1.csproj.
C:\Program Files\dotnet\sdk\3.0.100-preview5-011568\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(157,5): message NETSDK1057: You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview [C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\ConsoleApp1.csproj]
  ConsoleApp1 -> C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\bin\Release\netcoreapp3.0\win10-x64\ConsoleApp1.dll
  ConsoleApp1 -> C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\bin\Release\netcoreapp3.0\win10-x64\publish\

C:\Users\user\source\repos\ConsoleApp1>dir ConsoleApp1\bin\Release\netcoreapp3.0\win10-x64\publish\
 Volume in drive C has no label.
 Volume Serial Number is 9697-D272

 Directory of C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\bin\Release\netcoreapp3.0\win10-x64\publish

05/06/2019  07:05 PM    <DIR>          .
05/06/2019  07:05 PM    <DIR>          ..
05/06/2019  07:05 PM        70,272,314 ConsoleApp1.exe
05/06/2019  07:05 PM               440 ConsoleApp1.pdb
               2 File(s)     70,272,754 bytes
               2 Dir(s)  79,950,237,696 bytes free
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】クリック(タップ)した場所にボタンが存在するかどうかを判定するメソッド

ボタン判定メソッド

表題のメソッドは以下になります。

    bool IsButtonTap()
    {
        //タップ検知したGameObjectを取得。
        GameObject tapObj = EventSystem.current.currentSelectedGameObject;
        //取得したGameObjectがnullならばfalseを返す。
        if (!tapObj) { return false; }
        //取得したオブジェクトからButtonを取得。
        Button btn = tapObj.GetComponent<Button>();
        //ボタンがnullかどうかを返す。
        return btn;
    }

参考

EventSystem.current.currentSelectedGameObject

この関数で、現在の検知したオブジェクトを取得出来ます。

Object.bool

unityでnullチェックをする際、上の例で言うと「btn!=null」と表記しなくても「btn」と書くだけで同じことが出来てしまいます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

色選びを助けるマン(`・ω・´)

【はじめに】私的に役に立つ

:star:起動時画面

:star:「RGB → 16進数カラーコード」に変換機能の流れ
①「Red」「Green」「Blue」の数値を設定をする!
②「RGB → HexcolorCodes」にチェックを入れる!
③「Create」を押下する!
④設定した色が「Hex color codes」に16進数カラーコードを各RGBに表示!
 また、下のテキストボックスにコピーしやすいように表示!
⑤右の四角に色が表示される!

:star:「16進数カラーコード → RGB」に変換機能の流れ
①「Hex color codes」の各RGBに数値を設定をする!
②「HexcolorCodes → RGB」にチェックを入れる!
③「Create」を押下する!
④設定した色が「RGB」に表示!
⑤右の四角に色が表示される!

:star:「カラーパレット」から「RGB」「16進数カラーコード」に変換機能の流れ
①「Color Dialog」を押下する!
②色を選択する!
③設定した色が「RGB」「16進数カラーコード」に表示!
④右の四角に色が表示される!

【各コントロールのプロパティ】足りてるか不安…

:star:「コントロール:Nameプロパティ:その他のプロパティ」の順で
Form:Pallet:Text(Pallet)
GroupBox:RGBGroupBox:Text(RGB)
GroupBox:HexcolorCodesGroupBox:Text(Hex color codes)
Label:redLabel:Text(Red)
Label:greenLabel:Text(Green)
Label:blueLabel:Text(Blue)
Label:hexadecimalLabel:Text(Hex color codes)
Label:sarpLabel:Text(#), Font(11.25pt)
NumericUpDown:redNumericUpDown:Text(0), TextAlign(Right), Maximum(255), ForeColor(Red)
NumericUpDown:greenNumericUpDown:Text(0), TextAlign(Right), Maximum(255), ForeColor(Green)
NumericUpDown:blueNumericUpDown:Text(0), TextAlign(Right), Maximum(255), ForeColor(Blue)
RichTextBox:hexcolorCodesRichTextBox:ReadOnly(True), BackColor(White), ScrollBars(None), BorderStyle(FixedSingle)
CheckBox:RGBCheckBox:Text(RGB → HexcolorCodes)
CheckBox:hexcolorCodesCheckBox:Text(HexcolorCodes → RGB)
Button:createButton:Text(Create)
Button:dialogButton:Text(Color Dialog)
Panel:colorPanel:BorderStyle(FixedSingle)
ColorDialog:colorDialog:なし

【コード】カキカキしまっせ

Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp6
{
    public partial class Pallet : Form
    {
        public Pallet()
        {
            InitializeComponent();
        }

        /// <summary>
        /// RGBまたは16進数カラーコードから値を取得し、色をパネルに表示
        /// </summary>
        /// <param name="sender">イベント発行元</param>
        /// <param name="e">イベント情報</param>
        private void createButton_Click(object sender, EventArgs e)
        {
            // 「RGB → HexcolorCodes」にチェック時
            if (RGBCheckBox.Checked == true && hexcolorCodesCheckBox.Checked == false)
            {
                // RGB の値を取得
                int R = (int)redNumericUpDown.Value;
                int G = (int)greenNumericUpDown.Value;
                int B = (int)blueNumericUpDown.Value;

                //設定した色をパネルに表示
                DrawingPanel(R, G, B);

                // 16進数カラーコードで表示
                CreateHexadecimal(R, G, B);
            }
            // 「HexcolorCodes → RGB」にチェック時
            else if (RGBCheckBox.Checked == false && hexcolorCodesCheckBox.Checked == true)
            {
                // 16進数カラーコードを取得し、16進数を10進数に変換
                var R = Int32.Parse(redTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                var G = Int32.Parse(greenTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                var B = Int32.Parse(blueTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                // 設定した色をパネルに表示
                DrawingPanel(R, G, B);

                // RGB で表示
                CreateRGB(R, G, B);
            }
            else
            {
                // チェックボックスの選択に不備があることをメッセージボックスで警告
                MessageBox.Show(@"Please check either ""RGB → HexcolorCodes"" or ""HexcolorCodes → RGB""");
            }
        }

        /// <summary>
        /// カラーダイアログから色を取得し、色をパネルに表示。または、RGB、16進数カラーコードに値を表示
        /// </summary>
        /// <param name="sender">イベント発行元</param>
        /// <param name="e">イベント情報</param>
        private void dialogButton_Click(object sender, EventArgs e)
        {
            // カラーダイアログを表示
            DialogResult dialogResult = colorDialog.ShowDialog();

            // カラーダイアログからRGB の値を取得
            int R = colorDialog.Color.R;
            int G = colorDialog.Color.G;
            int B = colorDialog.Color.B;

            // 設定した色をパネルに表示
            DrawingPanel(R, G, B);

            // 16進数カラーコードで表示
            CreateHexadecimal(R, G, B);

            // RGB で表示
            CreateRGB(R, G, B);
        }

        /// <summary>
        /// 設定したRGB の色をパネルに表示
        /// </summary>
        /// <param name="R">赤色の値</param>
        /// <param name="G">緑色の値</param>
        /// <param name="B">青色の値</param>
        private void DrawingPanel(int R, int G, int B)
        {
            // パネルに設定された色を表示
            colorPanel.BackColor = Color.FromArgb(R, G, B);

            // RGBを16進数に変換し、16進数カラーコードを「hexcolorCodesRichTextBox」に表示
            hexcolorCodesRichTextBox.Text = "#" + $"{R:x2}" + $"{G:x2}" + $"{B:x2}";

            // 「hexcolorCodesRichTextBox」に表示されたの文字を色分け
            hexcolorCodesRichTextBox.Select(1, 0);
            hexcolorCodesRichTextBox.SelectionLength = 2;
            hexcolorCodesRichTextBox.SelectionColor = Color.Red;
            hexcolorCodesRichTextBox.Select(3, 0);
            hexcolorCodesRichTextBox.SelectionLength = 2;
            hexcolorCodesRichTextBox.SelectionColor = Color.Green;
            hexcolorCodesRichTextBox.Select(5, 0);
            hexcolorCodesRichTextBox.SelectionLength = 2;
            hexcolorCodesRichTextBox.SelectionColor = Color.Blue;
        }

        /// <summary>
        /// RGB を表示
        /// </summary>
        /// <param name="R">赤色の値</param>
        /// <param name="G">緑色の値</param>
        /// <param name="B">青色の値</param>
        private void CreateRGB(int R, int G, int B)
        {
            // 設定されたRGBをRGBグループの各RGBに表示
            redNumericUpDown.Value = R;
            greenNumericUpDown.Value = G;
            blueNumericUpDown.Value = B;
        }

        /// <summary>
        /// 16進数カラーコードを表示
        /// </summary>
        /// <param name="R">赤色の値</param>
        /// <param name="G">緑色の値</param>
        /// <param name="B">青色の値</param>
        private void CreateHexadecimal(int R, int G, int B)
        {
            // 設定されたRGBをHex color codesグループの各RGBに表示
            redTextBox.Text = $"{R:x2}";
            greenTextBox.Text = $"{G:x2}";
            blueTextBox.Text = $"{B:x2}";
        }
    }
}

もっと簡略的にできそうだけど、浮かばない (((;^ω^)))

【おわり】チャンチャン♪

最近やっとメソッドを理解したから使ってみた:metal_tone2:
使い方が合ってるかは、わからないが……
いろいろ指摘して欲しい ∑d(≧▽≦*)OK!!

HTMLやCSSを使う時に色の試しをしたくて作ってみたが、地味に助かる(´▽`)♪
これはこれで良いが
「地味に助かる(´▽`*)♪」じゃなく。ちゃんと助けてぇぇぇぇぇぇええええええええええええ

配色に悩むことが多いからそこもフォローできるようにしたい!
色味が決まらないと心に花が咲かないというかーうんうん:sparkles:ワクo(゚ー゚o)(o゚ー゚)oワク:sparkles:
そこらへんも、ブチかましていけたら
続きとしてQiitaに書こうと思うこの頃の俺だぁ:sunglasses:

以上、「色選びを助けるマン(`・ω・´)」でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む