C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[11]: 取得するマウスの座標をクライアント領域内に限定するには [1]


(過去ログ 117 を表示中)

[トピック内 24 記事 (21 - 24 表示)]  << 0 | 1 >>

■68817 / inTopicNo.21)  Re[12]: 取得するマウスの座標をクライアント領域内に限定するには
  
□投稿者/ yoto (16回)-(2013/11/19(Tue) 10:56:51)
No68815 (しま さん) に返信
> ■No68813 (yoto さん) に返信

> だってそうしているから。
> 起点 before_p の値は固定なので、終点 p が次々に変わる度に放射状に線を引くのは当り前のことだと思います。
> before_p をどう使いたかったのか説明して欲しいと思います。
> 若し、Mouse_MovePoints に n 点あって、i番目の点から i+1 番目の点に線を引く場合、 before_p は i 番目の点で
> p が i+1 番目の点として線を引きたいのならどうすべきなのか考えてみましょう
> (0 <= i < i+1 < n の関係があるとする)
> そして、次の点に移ったときには before_p と p との関係はどうあって欲しいのでしょうか?
> before_p は i+1 番目の点で、p が i+2 番目の点であって欲しいのでしょうか?

 自分としては、 0 <= i−1 < i <…< nの関係のなかにおいて、i点にあったらbefore_pはi−1点を表すように使おうと考えていました。
 そして、pがi点目である。
 直線を描く際にはbefore_pが始点で、pが終点になるような関係にして
 連続して線が描けるようにしたいと考えております


引用返信 編集キー/
■68818 / inTopicNo.22)  Re[13]: 取得するマウスの座標をクライアント領域内に限定するには
□投稿者/ しま (42回)-(2013/11/19(Tue) 11:38:42)
No68817 (yoto さん) に返信
> ■No68815 (しま さん) に返信
>>■No68813 (yoto さん) に返信
>
>>だってそうしているから。
>>起点 before_p の値は固定なので、終点 p が次々に変わる度に放射状に線を引くのは当り前のことだと思います。
>>before_p をどう使いたかったのか説明して欲しいと思います。
>>若し、Mouse_MovePoints に n 点あって、i番目の点から i+1 番目の点に線を引く場合、 before_p は i 番目の点で
>>p が i+1 番目の点として線を引きたいのならどうすべきなのか考えてみましょう
>>(0 <= i < i+1 < n の関係があるとする)
>>そして、次の点に移ったときには before_p と p との関係はどうあって欲しいのでしょうか?
>>before_p は i+1 番目の点で、p が i+2 番目の点であって欲しいのでしょうか?
>
>  自分としては、 0 <= i−1 < i <…< nの関係のなかにおいて、i点にあったらbefore_pはi−1点を表すように使おうと考えていました。
>  そして、pがi点目である。
>  直線を描く際にはbefore_pが始点で、pが終点になるような関係にして
>  連続して線が描けるようにしたいと考えております
>
だったら、そのような動きをするためにはどのようにコードをかけばいいのか考えてみましょう
例えば、直線を引いた後で
before_p = p;
とすれば、p が i+1 番目の時は before_p は i+1 番目の値を保持することになりませんか?
なら、 p が i+2 番目の点を指す時には before_p は 望むもの i+1 番目の点を指すことになるのではないでしょうか?
引用返信 編集キー/
■68820 / inTopicNo.23)  Re[14]: 取得するマウスの座標をクライアント領域内に限定するには
□投稿者/ an (3回)-(2013/11/19(Tue) 14:03:31)
before_p関係については、しまさんがフォローしてくれていますので、
自分は最後に提示してくれたソースコードのフォローを。

-----

No68813 (yoto さん) に返信

> 他にもDrawLines(Pen pen, Point[] points);なども試してみたのですがうまくいかず、

どう「うまくいかず」なのでしょうか?

> 以下にDrawLinesを組みこんでみたプログラムのソースコードを記述します。

とあるので、とりあえずコピペして実行してみましたが、
実行途中でエラーになっりました。
「うまくいかず」というのは、このエラーのことを事を指しているのでしょうか?

実行エラーになった理由はメンバPtの配列が少ない要素数([6])で宣言されていたため、
すぐに範囲外の要素にアクセスしてエラーが発生していると思われます。

仮に要素数を1000にしたところ、すぐにはエラーが発生しませんでしたので、
その状況で動作を確認したところ、
左上を起点になっている線が1本余計に描かれていたのですが、
これが、「うまくいかず」のことなのでしょうか?

仮に前者であれば上記のとおり要素数の問題です。
仮に後者であればPtを配列で定義していることでしょうか?

後者について、少し具体的に説明します。
配列Ptを定義時にすべての要素についてxおよびyには0が設定されています。
ドラッグ中に配列Ptにはタイマーイベント発生分だけ値が設定されますが、
すべての配列Ptの要素に値が設定されるわけではないので、
xおよびyに0が設定されている要素が残っています。
その状況でDrawLinesメソッドの引数に配列Ptを渡すので、
左上を起点(xおよびyに0の点)となる線が作成されるのではないでしょうか?
(画像系のクラスは一切使用したことがないので、
 今までの経験則から予想して記述していますので、間違っているかもしれません。)

これを解決するのであれば、他のPointと同様にList<Point>として宣言し
余計な点は記録されないようにすればよいと思います。
(っていうかPtではなくMove_MousePointsを使えばよさそう???)

ちなみにList<Point>の型をDrawLinesメソッドには直接使用できないので、
List<>のToArrayメソッドにて変換が必要となるようです。
また、複数の点の間に線を引くので、List<Point>の要素が2個以上ないと
エラーになるようですので、注意が必要です。

ただ、この対応では、
 (1)ドラッグ開始→(2)ドラッグ解除→(3)マウス移動→(4)ドラッグ開始
という動作をした際に、
(3)の動作時の線等は描かれませんが、
(4)開始時に(2)からの点が残ってしまうという問題があるように思えます。
これが問題となるようであれば、どこかのタイミングに初期化をいれるか、
ジャグ配列的な考え(List<List<Point>>?)で対応する等、工夫が必要かと思います。
またはNo68778のJittaさんの方式も有用かと。
(根本的に何が正しいか、どうしたいかが完全に読み取れていないので・・・)

それとも他のケースで「うまくいかず」なのでしょうか?


※「うまくいかず」では他の人には伝わりにくいので
 具体的にどううまくいかないのか記載しましょう。


また、DrawLineメソッドからDrawLinesメソッドへの変更は
どういった経緯からでしょうか?
DrawLinesメソッドの方が便利そうといったことであれば、
それはそれで構わないと思いますが、
本当に今回のケースで使用できるかどうかを検証が必要だと思います。
もし、十分に検証されていれば、上記のような問題は出ないと思います。
今回のようなケースの場合、
作成しているプログラムに直接新しい処理を追加するのではなく、
DrawLinesメソッドのためのプロジェクトを1つ作成して
引数をいろいろ変えてみて試すような検証が必要だと思います。
(逆に作成しているプログラム側での値がどのように変化しているか
 というのもデバッグ等で理解する必要もありますが。)




他にもいろいろ伝えたいこと・聞きたいことはありますが、
まずは問題点があいまいなので・・・。

引用返信 編集キー/
■68834 / inTopicNo.24)  Re[11]: 取得するマウスの座標をクライアント領域内に限定するには
□投稿者/ Jitta (93回)-(2013/11/20(Wed) 22:39:38)
Jitta さんの Web サイト
No68813 (yoto さん) に返信
 ちょっとよそ見してたらまた進んでる(^-^;;;;

 この間、『プログラムはこうして作られる』という本を見つけました。
http://www.shuwasystem.co.jp/products/7980html/3925.html
この本、初学者が読むにはとてもいいと思います。
「プログラムとは、そもそもなんなのか」、から始まって、
「プログラムを作るために、どのように考えるのか」ということが、
かなりしつこく、、、考えるように求められます。
息抜きがてら、読んでみることを勧めます。

 さて、まずは、C# から離れてみましょう。
前の投稿で私は、「質問するのではなく、説明してください」と書きました。
実は、プログラムも同じです。
プログラムというのは、
あなたがしたいことを、
ある文法に沿って、
コンピュータに説明すること、です。
おそらく、コンピュータよりも、人間に説明することの方が慣れているでしょう。
コンピュータは、言葉を杓子定規に解釈します。
人間は、足りない情報を周りから補いながら想像して解釈します。
ですから、まずは人間に説明して、補足を得ましょう。

 どういうことか。まずは、自分がコンピュータの動きをトーレスできるように、
自分に分かる言葉でプログラムを書きましょう。

 私のコードの Record メソッドを、日本語にしますね。

private void Record(bool force = false)
{
    カーソル位置を、クライアント領域にして pos に設定する。
    picture の領域で Rectangle インスタンスを作り、rect に設定する。
    もし、rect は pos を含んでおらず、記録を強制しないなら、
    {
        メソッドから返る。
    }

    もし、targetLine が設定されているなら、
    {
        picture から Graphics インスタンスを作って g に設定し、次の範囲の間だけ使う。
        {
            g を使って、pos の位置を中心に楕円を描く。
            もし、targetLine に1つ以上要素があるなら、
            {
                g を使って、targetLine の最後の要素から pos まで線を描く。
            }
        }

        pictureBox1 を再描画する。
        targetLine に pos を追加する。
    }
}


 yotoさんの、 No 68803 のコードの Chase_MousePoint メソッドを日本語にします。

private void Chase_MousePoint()//円と軌跡を描く
{
    Bitmap クラスの bmp2 を宣言し、bmp1 と等しくする。
    bmp2 から Graphics インスタンスを作って g に設定する。

    画像座標でのマウスポインタの位置を sp に設定する。
    画面座標 sp をクライアント座標(ピクチャボックス座標)に変換して cp に設定する。

    もし、cp 座標が、(0, 0) より大きいなら、
    {
        もし、cp 座標が、(600, 400) より小さいなら、
        {
            dp を cp と等しくなるように設定する。
            Move_MousePoints に、dp から Point 構造体を生成して追加する。
            MousePoints に、dp から Point 構造体を生成して追加する。
        }
    }

    MoveMousePoints リストから要素を p に取り出して繰り返し、
    {
        g を使って、p の位置を中心に四角形を描く。
        g を使って、p の位置を中心に楕円を描く。
    }

    DarkRed の Pen インスタンスを作って pen に設定する。
    pen の幅を 5 に設定する。
    pen の終端を矢印にする。
    g を使って、before_p から dp まで線を描く。

    もし、cp 座標が、(0, 0) より大きいなら、
    {
        もし、cp 座標が、(600, 400) より小さいなら、
        {
            before_p を cp と等しくなるように設定する。
        }
    }

    g の使用を終える。
    pictureBox1 を再描画する。
}


で、日本語にして、気がつきました。

> 点が増える毎に全部再描画しているので、
> どんどん遅くなっていきますよね?

と書いて、毎回描き直しているのは線だとして進めてきましたが、これは間違いで、

>    MoveMousePoints リストから要素を p に取り出して繰り返し、
>    {
>        g を使って、p の位置を中心に四角形を描く。
>        g を使って、p の位置を中心に楕円を描く。
>    }

ここの部分のことだったのですが、これは、円を描く、の方ですね。
すみません。

 さて、これで、やっていることの違いが、よくわかるようになったのではないでしょうか。
今回は、コードから日本語に直しましたが、まず日本語を作ってからコードに直せば、
より意図通りの動作をするプログラムになるのではないでしょうか。


 それから、Pen オブジェクトは、Dispose が必要ではないでしょうか。
クラスの説明を見て、IDisposable インタフェースを実装しているなら、Dispose を呼びましょう。

引用返信 編集キー/

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -