Visual Basic 中学校 掲示板 投稿内容
タグのない投稿を抽出 統計 RSS

Visual Basic 中学校 > 投稿一覧 >

マウスをなぞった軌跡を描画する 解決済み

タグの編集...

投稿者 dative   (社会人)   投稿日時 2022/6/28 11:34:42
息の長い 良質コンテンツありがとうございます。
タイプミスかもという ものを見つけたかもしれません。
何かの際に、ご確認ください。

マウスをなぞった軌跡を描画する

private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        foreach (var stroke in Strokes)
        {
            //ストロークに含まれるすべてのPointを線で結んだ図形を生成
            var path = new System.Drawing.Drawing2D.GraphicsPath(stroke.ToArray(), Enumerable..Repeat<byte>(1, stroke.Count).ToArray());
            e.Graphics.DrawPath(drawPen, path); //生成した図形を描画
        }



Enumerable.Repeat<byte>(1, stroke.Count).ToArray());

ピリオド 2個で掲載されていますが?


投稿者 (削除されました)   ()   投稿日時 2022/6/28 12:55:26
(削除されました)

投稿者 dative   (社会人)   投稿日時 2022/6/28 13:04:05
ひょっとして 私の環境が いけないのでしょうか?
HTLタグが 表示されています。
Google Chrome バージョン: 102.0.5005.115(Official Build) (64 ビット)

マウスをなぞった位置にリアルタイムに四角形を描画し、マウスを離すとその位置に四角形を追加する

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        //マウスを離した場合
        if (isMouseDown)
        {
            var activeRect = this.CalcActiveRect(mouseDownPosition, mouseDragPosition);
            if (activeRect.Width * activeRect.Height > 0)
            {
                //面積がある場合、この四角形を描画対象に追加する。
                var ppath = new System.Drawing.Drawing2D.GraphicsPath/span>();
                path.AddRectangle(activeRect);
                paths.Add(path);
            }
            isMouseDown = false;
        }
 
        pictureBox1.Invalidate(); //pictureBoxを強制的に再描画する/span>
    }



var ppath →  var path

/span> は、不要。編集アプリか、ブラウザか 何かの不具合。

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/28 13:32:20
なるほど、dative さんの仰る通り、確かにタイプミスのようですね。
引用元が提示されていないので、何を指しているのか探してしまいました…。(^^;
https://www.umayadia.com/cssample/sample0201/Sample275WinFormMouseToDraw.htm

> タイプミスかもという ものを見つけたかもしれません。
るきおさん宛の記事内容の指摘であれば、投稿時の区分を
「コミュニティ」にした方が良いかと思います。
まぁ、C# のコードではあるので、「技術」と言えば技術なんですが。

投稿時の区分や社会的身分って、忘れ去られやすいんですよね…。
先日も、[高校生]だったAdoさんが、翌日は[社会人]として投稿されたりしていました。

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/28 14:01:08
> ピリオド 2個で掲載されていますが?
そのコードについてさらに言えば、pictureBox1_Paint 内の
 var path = new System.Drawing.Drawing2D.GraphicsPath(…);
の部分を using した方が良さそうです。

//ストロークに含まれるすべてのPointを線で結んだ図形を生成
using (var path = new System.Drawing.Drawing2D.GraphicsPath(stroke.ToArray(),
         Enumerable.Repeat<byte>(1, stroke.Count).ToArray()))
{
    e.Graphics.DrawPath(drawPen, path); //生成した図形を描画
}


一方、同ページの最初にある pictureBox1_MouseClick 内の
 var path = new System.Drawing.Drawing2D.GraphicsPath();
というよく似たコードがありますが、こちらは using してはいけません。

投稿者 dative   (社会人)   投稿日時 2022/6/29 06:04:57
長らく ご無沙汰しております。
魔界の仮面弁士 様よりの ご回答 久々にいただきます。
分類のご指摘ありがとうございます。気づかなかった。
コードレヴュー大変参考になります。ありがとうございます。

投稿者 るきお(管理者)   (社会人)   投稿日時 2022/6/29 23:17:22
dativeさんの環境がおかしいわけではないですね。
HTMLエディターとして使っているExpression Webの仕様なのかバグなのかときどきおかしくなってしまうのですよね。
Expression Webはもう終了した製品なのでだましだまし使っています。新バージョン出してほしいです…。今どきこんなやりかたでWebサイトを作っている人は少数派みたいです。昔は普通だったんですけどこうやって化石化していくんですね。

…とExpression Webにすべての責任をなすりつけてしまいましたが、私の確認漏れでもありますね。usingの件も含めて。

投稿者 dative   (社会人)   投稿日時 2022/6/30 07:51:35
るきお様 長くご無沙汰しております。レスありがとうございます。
暫くぶりで こちらへ 参りましたのは、
VS2022:C# 8.0 への、移行にあたって、移行済み、検証済み、コード、できれば、数行の物がないかな
と探していて、こちらのコード例を使用させていただきました。
(VS2019へ .NET Framework 4.8 入れていないの気づかず。なんでだ??と やりました、ww)
CP/M , DOSでEDLINE,WORDSTAR,PAINT,DRAW系テストコード位は自分で書け!で育った身には
隔世の感じがする、素敵なコードでした。ありがとうございます。

マウス、グラフィックス 関連URL例
https://www.umayadia.com/cssample/sample0300/Sample316WinFormAnimeMouseCursor.htm?pos=3073.60009765625
https://www.umayadia.com/cssample/sample0201/Sample275WinFormMouseToDraw.htm

「C# 7.3 では使用できません。8.0以上の言語バージョンをお使いください。」エラーの対処方法
(この例では、記述場所重要かもです。)
https://yayaochannel.com/?p=951

投稿者 dative   (社会人)   投稿日時 2022/6/30 09:57:45
ありがとうございました。

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/30 12:42:53
> VS2022:C# 8.0 への、移行にあたって、移行済み、検証済み、コード、できれば、数行の物がないかな
.NET Framework を使う限りは、基本的には C# 7.3 どまりなんですよね…。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/configure-language-version

LangVersion を更新すれば、.NET Framework であっても一部の新機能を使えますけれども、
Span<T> とかを使いたいなら、.NET Framework よりも .NET 6 の方がパフォーマンス的にお奨め。
ちなみにプレビュー版では、C# 11.0 まで利用できます。


寂しい事に VB の進化が止まってしまったため、今は自分も C# 派なのですが、
近年追加された機能の中で、個人的に最近のお気に入りなのがこのあたり。
 init-only property (C# 9.0)
 raw string literal (C# 11.0)
 deconstruction (C# 7.0)


// .NET Standard 2.1 や .NET Core 2.0 以上
var codePages = new Dictionary<int, string> {
    [65001] = "UTF-8" ,
    [932] = "Shift_JIS"
};
foreach (var (code, langName) in codePages)  // デコンストラクタによる分解 (C# 7.0 以降)
{

}


.NET Framework の場合、KeyValuePair にはデコンストラクタが無いので
上記がエラーになりますが、拡張メソッドでデコンストラクタを補えば、
.NET Framework でも上記コードが使えます。(VS2017 以降)

static class KeyValuePairExtensions
{
    public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> pair, out TKey key, out TValue value)
        => (key, value) = (pair.Key, pair.Value);
}


上記は .NET Framework 4.7 向けに書いていますが(ValueTuple 構文)、
少々手直しすれば、.NET Framework 2.0 以上でも利用可能です。
(2.0 / 3.0 だと拡張メソッドを使うためにもう一手間必要なので、基本的には 3.5 以上向け)

まぁ、KeyValuePair ぐらいであれば、デコンストラクタ無しでも困らないのですけれどね。

投稿者 daive   (社会人)   投稿日時 2022/6/30 17:36:16
嬉しい書き込みありがとうございます。
VBの進化 停止は、BASIC好きな私も、寂しくおもいます。
MSなので、一縷の望みはあるかな、ないかな。
ただ、開発言語は うんぬんかんぬん という時代でもなくなったので、
幸せな時代だと思います。いきなり、PL/M覚えろとか、4TH、5’TH覚えろとか
されなくなって、必要があっての事に変わりました。

あ、学生時代の思い出、
講師「COBOL なんざ、何時までも使ってると
    落ちこぼれるぞー、時代についてけー
 :
数十年たちましたが、今でも、「COBOLは永遠ですw」

BASICだって。。。

投稿者 daive   (社会人)   投稿日時 2022/6/30 18:16:06
ハンドルネームまでミスっているの、
今気が付きました。
×:dative 
〇:daive
該当記事:2件
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=30764
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=30760

投稿者 daive   (社会人)   投稿日時 2022/7/7 00:49:38
マウスをなぞった位置にリアルタイムに四角形を描画し、マウスを離すとその位置に四角形を追加し、後で追加された四角形をクリックすると色が変わる
https://www.umayadia.com/cssample/sample0201/Sample275WinFormMouseToDraw.htm?pos=2978.39990234375#A5

このサイトでの お礼を兼ねて
↑の、るきお様のソースを、ちょろちょろと改造して、、
パパっと、1440要素(1日=1440分)の 横バー自由指定、重なり無が できます。
前提:
フォームサイズ、1920、1080
イメージボックスのサイズ:横:1440、縦:50としてください。
textBox1~3 追加してください。
botton1~3 追加して、Clickを、適切な、ソースの箇所へ割り付けてください。
  削除、読出、書出
POPupとなるフォーム、呼出し名称で作成してください。
※私の追加した追加部分は、良いコードではありません。思いつくまま簡単に書きました。
 ロジックから煮詰めなおしてください。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace マウス操作で図形を描画する
{
    public partial class Scd1440 : UserControl
    {
        List<Polygon> polygons = new List<Polygon>();

        Point mouseDownPosition; //ドラッグを開始したマウスの位置
        Point mouseDragPosition; //現在ドラッグ中のマウスの位置
        bool isMouseDown; //マウスのボタンが押されているか
        Pen selectPen; //ドラッグ中の四角形の描画に使用するペン

        const int RD = 0;
        const int WR = 1;
        bool DelFLG = false;
        FormPOP fPOP = new FormPOP();
        FormPOPerr1 ePOP1 = new FormPOPerr1();
        int[] ontime = new int[1443];  //[1440]:0、[1441]:前日より継続、[1442]:翌日へ継続、[0]~[1439]:00:00~23:59
        String GRnm = @"D:\ZENON\OPCscheduler\マウス操作で図形を描画する\Scadule1440.txt";
        //01:コメント
        //02:0~1439,0,前日継続FLG,翌日継続FLG
        //03:

        public Scd1440()
        {
            InitializeComponent();

            //イベントの結びつけ
            //フォームデザイナーでイベントを結び付けている場合は不要です。
          //  this.Shown += Scd1440_Shown;
            pictureBox1.Paint += pictureBox1_Paint;
            pictureBox1.MouseDown += pictureBox1_MouseDown;
            pictureBox1.MouseMove += pictureBox1_MouseMove;
            pictureBox1.MouseUp += pictureBox1_MouseUp;
            //
            selectPen = new Pen(Color.Blue, 1);
            selectPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

            if (textBox3.Text == "")
            {
                textBox3.Text = GRnm;
            }
        }

[/CODE]


投稿者 daive   (社会人)   投稿日時 2022/7/7 00:51:25
        private void Scd1440_Shown(object sender, EventArgs e)
        {
            //ドラッグ中の四角形の描画に使用するペンを作成。青い点線のペンにする。
            selectPen = new Pen(Color.Blue, 1);
            selectPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            //e.Graphics.Clear(Color.White); //背景を白にする,LemonChiffon
            e.Graphics.Clear(Color.LemonChiffon);
            //
            var Rect = new Rectangle();
            Rect.X = 0;
            Rect.Width = 1;
            Rect.Y = 0;
            Rect.Height = 5;
            for (int i = 0; i <= 1440; i = i + 6)
            {
                Rect.X = i;
                Rect.Y = 0;
                e.Graphics.DrawRectangle(Pens.Black, Rect);
                Rect.X = i;
                Rect.Y = 44;
                e.Graphics.DrawRectangle(Pens.Black, Rect);
            }
            Rect.Height = 10;
            for (int i = 0; i <= 1440; i = i + 30)
            {
                Rect.X = i;
                Rect.Y = 0;
                e.Graphics.DrawRectangle(Pens.Black, Rect);
                Rect.X = i;
                Rect.Y = 40;
                e.Graphics.DrawRectangle(Pens.Black, Rect);
            }

            //追加されている図形を描画する。
            foreach (var polygon in polygons)
            {
                if (polygon.IsSelected)
                {
                    //e.Graphics.FillRectangle(Brushes.Yellow, polygon.Rect); //黄色で塗りつぶし
                    e.Graphics.FillRectangle(Brushes.Blue, polygon.Rect);
                }
                else
                {
                    //e.Graphics.FillRectangle(Brushes.Cyan, polygon.Rect); //水色で塗りつぶし
                    e.Graphics.FillRectangle(Brushes.Red, polygon.Rect); //赤色で塗りつぶし
                }
                e.Graphics.DrawRectangle(Pens.Blue, polygon.Rect); //青い枠線
            }

            if (Control.MouseButtons != MouseButtons.Left)
            {
                //マウスの左ボタンが押されていない場合何もしない
                return;
            }

            //ドラッグを開始したマウスの位置(mouseDownPosition)と現在ドラッグ中のマウスの位置(mouseDragPosition)
            //から、描画すべき四角形の座標を計算する。
            var activeRect = CalcActiveRect(mouseDownPosition, mouseDragPosition);

            //ドラッグ中の四角形を描画
            e.Graphics.DrawRectangle(selectPen, activeRect);
        }






投稿者 daive   (社会人)   投稿日時 2022/7/7 00:54:46
[CODE]

        private Rectangle CalcActiveRect(Point startPosition, Point endPosition)
        {
            var activeRect = new Rectangle();
            activeRect.X = Math.Min(mouseDownPosition.X, mouseDragPosition.X);          //pos X
            activeRect.Y = 0;  //Math.Min(mouseDownPosition.Y, mouseDragPosition.Y);          //pos Y
            activeRect.Width = Math.Abs(mouseDragPosition.X - mouseDownPosition.X);     //size X
            activeRect.Height = 50;  // Math.Abs(mouseDragPosition.Y - mouseDownPosition.Y);    //size Y
            //----------------------------------------

            //----------------------------------------
            return activeRect;
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            //マウスのボタンが押された場合、
            mouseDownPosition = e.Location;
            isMouseDown = true;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            //マウスを移動した場合
            mouseDragPosition = e.Location;
            pictureBox1.Invalidate(); //pictureBoxを強制的に再描画する
        }
[CODE]


投稿者 daive   (社会人)   投稿日時 2022/7/7 00:57:13
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            //マウスを離した場合
            if (isMouseDown)
            {
                var activeRect = this.CalcActiveRect(mouseDownPosition, mouseDragPosition);
                if (activeRect.Width * activeRect.Height > 0)
                {
                    int[] ontimebk = new int[1443];
                    Array.Copy(ontime, ontimebk, ontime.Length);
                    bool flg = false;
                    //------------------------------------------
                    //データ範囲、00:00~23:59設定
                    //------------------------------------------
                    if (activeRect.X < 0)
                    {
                        activeRect.Width = activeRect.Width + activeRect.X;
                        activeRect.X = 0;
                    }
                    if (activeRect.X > 1440)
                    {
                        activeRect.Width = activeRect.Width - activeRect.X;
                        activeRect.X = 1440;
                    }
                    if ((activeRect.X + activeRect.Width) > 1440) { activeRect.Width = 1440 - activeRect.X; }
                    for (int i = activeRect.X; i <= (activeRect.X + activeRect.Width); i++)
                    {
                        if (ontime[i] == 0)
                        {
                            ontime[i] = 1;
                        }
                        else
                        {
                            flg = true;  //定義済みと重なり 

                        }
                    }
                    if (flg == false)
                    {
                        //面積がある場合、この四角形を描画対象に追加する。
                        polygons.Add(new Polygon { Rect = activeRect });

                    }
                    else
                    {
                        Array.Copy(ontimebk, ontime, ontimebk.Length);
                        //ePOP1.Show();
                    }
                }
                else
                {
                    //面積がない場合、これはクリックである。
                    Polygon selectedPolygon = null;

                    //クリックされた位置に四角形を存在するか調べる。
                    //※同じ位置に複数の四角形がある可能性があるので最後に見つかったものを
                    //変数selectedPolygonにセットしておく。
                    foreach (var polygon in polygons)
                    {
                        polygon.IsSelected = false;
                        if (polygon.Rect.Contains(e.Location))
                        {
                            selectedPolygon = polygon;
                            textBox1.Text = polygon.Rect.X.ToString();
                            textBox2.Text = (polygon.Rect.X + polygon.Rect.Width).ToString(); //polygon.Rect.Y.ToString();
                            //textBox1.Text = textBox1.Text + " / " + polygon.Rect.Width.ToString();
                            //textBox2.Text = textBox2.Text + " / " + polygon.Rect.Height.ToString();


                        }
                    }





投稿者 daive   (社会人)   投稿日時 2022/7/7 00:59:09
                    //四角形があった場合、IsSelecteをTrueにしておく。
                    //→この目印があることで Paintイベント内で特別扱いする。
                    if (selectedPolygon != null)
                    {
                        if (DelFLG == true)
                        {
                            //
                            for (int i = selectedPolygon.Rect.X; i <= (selectedPolygon.Rect.X + selectedPolygon.Rect.Width); i++)
                            {
                                ontime[i] = 0;
                            }
                            //削除FLG=TRUEの場合、面積がある場合、この四角形を削除する。
                            polygons.Remove(selectedPolygon); // Rect = activeRect });

                        }
                        else
                        {
                            selectedPolygon.IsSelected = true;
                            fPOP = new FormPOP();
                            fPOP.Show();
                            //
                            fPOP.Start.Text = selectedPolygon.Rect.X.ToString();
                            fPOP.End.Text = selectedPolygon.Rect.Y.ToString();
                            fPOP.Start.Text = fPOP.Start.Text + " / " + selectedPolygon.Rect.Width.ToString();
                            fPOP.End.Text = fPOP.End.Text + " / " + selectedPolygon.Rect.Height.ToString();
                            //
                            fPOP.Start.Text = textBox1.Text;
                            fPOP.End.Text = textBox2.Text; //polygon.Rect.Y.ToString();
                            //DateTime DTS;
                            //DateTime DTE;
                            //DTS = DateTime.Parse(textBox1.Text);
                            //DTE = DateTime.Parse(textBox2.Text);
                            //fPOP.Start.Text = DTS.ToString("hh:mm");
                            //fPOP.End.Text = DTS.ToString("hh:mm");

                            // TimeSpanのインスタンスを生成。時分は0でOK
                            var span = new TimeSpan(0, int.Parse(textBox1.Text), 0);
                            // フォーマットする
                            var hhmmss = span.ToString(@"hh\:mm");
                            fPOP.Start.Text = hhmmss;

                            // TimeSpanのインスタンスを生成。時分は0でOK
                            span = new TimeSpan(0, int.Parse(textBox2.Text), 0);
                            // フォーマットする
                            hhmmss = span.ToString(@"hh\:mm");
                            fPOP.End.Text = hhmmss;
                        }
                    }
                }
                isMouseDown = false;
            }





投稿者 daive   (社会人)   投稿日時 2022/7/7 01:02:01
[CODE]

            pictureBox1.Invalidate(); //pictureBoxを強制的に再描画する
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            File(RD, GRnm);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            File(WR, textBox3.Text);
        }

        void File(int mode, string path)
        {
            switch (mode)
            {
                case RD: //RD
                    System.IO.StreamReader sr = new System.IO.StreamReader(path, System.Text.Encoding.GetEncoding("shift_jis"));
                    //内容をすべて読み込む
                    string str = sr.ReadToEnd();
                    //閉じる
                    sr.Close();
                    //読込文字列を作業配列へ
                    string[] crlf = { "\r\n" };
                    string[] DTr1 = str.Split(crlf, StringSplitOptions.None);
                    //
                    string[] DTr2 = DTr1[2].Split(',');
                    int[] ontimebk = new int[1443];
                    for (int i = 0; i < (ontimebk.Length - 1); i++)
                    {
                        if (DTr2[i] == "0")
                        {
                            ontimebk[i] = 0;
                        }
                        else
                        {
                            ontimebk[i] = 1;
                        }
                    }

                    //読込作業配列→使用配列
                    Array.Copy(ontimebk, ontime, ontimebk.Length);
                    //ontimeの内容で描画
                    ontimeDsp();

                    break;
                case WR: //WR
                    string DTw = "";
                    DTw = DTw + ";" + DateTime.Now.ToString("yyyy/mm/dd hh:mm:ss") + "\r\n";
                    DTw = DTw + ";Scadule 1440,0 to 1439:00:00 to 23:59,1441:前日継続FLAG,1442:翌日継続Flg" + "\r\n";
                    for (int i = 0; i < (ontime.Length - 2); i++)
                    {
                        DTw = DTw + ontime[i] + ",";
                    }
                    DTw = DTw + ontime[ontime.Length - 1] + "\r\n";
                    //
                    System.IO.StreamWriter sw = new System.IO.StreamWriter(path, false, System.Text.Encoding.GetEncoding("shift_jis"));
                    //TextBox1.Textの内容を書き込む
                    sw.Write(DTw);
                    //閉じる
                    sw.Close();
                    break;
            }

[CODE]