フォーム座標の設定と取得
投稿者 るきお  (社会人)
投稿日時
2020/9/22 15:59:57
何の機能を使っているか、何をプログラムしようとしているか、で最適な答えは変わってきます。
とりあえず、Windowsフォームアプリケーションで Graphicsクラスの機能を使って描画していて、とにかく左下が原点になれば何でも良いということで回答してみます。
(この前提が変わると回答もまったく違う回答になる場合があります。)
Graphicsクラスは TranslateTransformメソッドで原点を指定することができますので、簡単に原点を変更できます。
たとえば、e.Graphics.TranslateTransform(100, 200) と書くと、これ以降は、それまでの点(100, 200)が今後の原点になります。
フォームの左下の座標は (0, Me.ClientSize.Height)なので、e.Graphics.TranslateTransform(0, Me.ClientSize.Height) と記述すると、それ以降はフォームの左下が原点になります。ユーザーがマウスでフォームのサイズを変更したときにはこのTranslateTransformを再実行する必要があります。
もう1つ、質問には書いてありませんでしたが、イヨさんはおそらく Y軸で上方向がプラスである座標系を扱いたいのではないかと推測します。これも簡単にできます。
e.Graphics.ScaleTransform(1, -1) と記述すると、その後は、Y軸が反転して上方向がプラスになります。
サンプルを紹介します。
TranslateTransform の行と ScaleTransformの行をコメントにすると、通常の座標系になるので、実行結果を比べてみると何が起こっているかわかると思います。
座標系を反転させた状態でDrawStringで文字を描画すると文字も反転してしまいます。文字を描画するときには適さないかもしれません。
文字だけ反転させないようにするには、反転を反転させるような処理が必要になり面倒です。反転を反転させるくらいなら、はじめから反転させないほうが楽です。この必要を感じるならば私はY軸を反転させないで別のアプローチでイヨさんが実現したいことを実現させるのが良いと思います。実現したいことが何なのかわからないので、それがどういうことなのかはなんともわかりませんが。
とりあえず、Windowsフォームアプリケーションで Graphicsクラスの機能を使って描画していて、とにかく左下が原点になれば何でも良いということで回答してみます。
(この前提が変わると回答もまったく違う回答になる場合があります。)
Graphicsクラスは TranslateTransformメソッドで原点を指定することができますので、簡単に原点を変更できます。
たとえば、e.Graphics.TranslateTransform(100, 200) と書くと、これ以降は、それまでの点(100, 200)が今後の原点になります。
フォームの左下の座標は (0, Me.ClientSize.Height)なので、e.Graphics.TranslateTransform(0, Me.ClientSize.Height) と記述すると、それ以降はフォームの左下が原点になります。ユーザーがマウスでフォームのサイズを変更したときにはこのTranslateTransformを再実行する必要があります。
もう1つ、質問には書いてありませんでしたが、イヨさんはおそらく Y軸で上方向がプラスである座標系を扱いたいのではないかと推測します。これも簡単にできます。
e.Graphics.ScaleTransform(1, -1) と記述すると、その後は、Y軸が反転して上方向がプラスになります。
サンプルを紹介します。
Public Class Form1
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
'この2行をコメントにすると通常の座標系になります。
e.Graphics.TranslateTransform(0, Me.ClientSize.Height) '左下(つまり、0,Me.ClientSize.Height)を新しい原点にする。
e.Graphics.ScaleTransform(1, -1) 'Y軸方向を反転させる。つまり上方向がプラスになる。
'背景を黒にする
e.Graphics.Clear(Color.Black)
'三角形
e.Graphics.DrawLine(Pens.LightBlue, 300, 20, 200, 193)
e.Graphics.DrawLine(Pens.LightBlue, 200, 193, 400, 193)
e.Graphics.DrawLine(Pens.LightBlue, 400, 193, 300, 20)
'円A(青)
e.Graphics.FillEllipse(Brushes.Blue, 290, 10, 20, 20)
e.Graphics.DrawString("A", Me.Font, Brushes.LightCyan, 295, 15)
e.Graphics.DrawString("x=300, y=20", Me.Font, Brushes.LightCyan, 312, 15)
'円B(赤)
e.Graphics.FillEllipse(Brushes.Red, 190, 183, 20, 20)
e.Graphics.DrawString("B", Me.Font, Brushes.LightCyan, 195, 188)
e.Graphics.DrawString("x=200, y=193", Me.Font, Brushes.LightCyan, 190, 208)
'円C(緑)
e.Graphics.FillEllipse(Brushes.Green, 390, 183, 20, 20)
e.Graphics.DrawString("C", Me.Font, Brushes.LightCyan, 395, 188)
e.Graphics.DrawString("x=400, y=193", Me.Font, Brushes.LightCyan, 390, 208)
End Sub
End Class
TranslateTransform の行と ScaleTransformの行をコメントにすると、通常の座標系になるので、実行結果を比べてみると何が起こっているかわかると思います。
座標系を反転させた状態でDrawStringで文字を描画すると文字も反転してしまいます。文字を描画するときには適さないかもしれません。
文字だけ反転させないようにするには、反転を反転させるような処理が必要になり面倒です。反転を反転させるくらいなら、はじめから反転させないほうが楽です。この必要を感じるならば私はY軸を反転させないで別のアプローチでイヨさんが実現したいことを実現させるのが良いと思います。実現したいことが何なのかわからないので、それがどういうことなのかはなんともわかりませんが。
投稿者 イヨ  (社会人)
投稿日時
2020/9/22 17:00:35
るきお様
ご返信有難うございます。
質問の言葉足らずですいません。
コードをコピペして遊んでみました。
リンクのコードの使い方がわかりました。
るきお様が書いてくれたコードはまだ自分が使ったことor知らない言葉も書いてあり
とても参考になりました。
自分は下記のように反転させた状態で
ユーザーホームをカーソルクリックして座標系を取得したいです。
Dim sp As System.Drawing.Point = System.Windows.Forms.Cursor.Position
Dim cp As System.Drawing.Point = Me.PointToClient(sp)
Dim x As Integer = cp.X
Dim y As Integer = cp.Y
Label1.Text = "X:" & x & "Y:" & y & ""
> e.Graphics.TranslateTransform(0, Me.ClientSize.Height) '左下(つまり、0,Me.ClientSize.Height)を新しい原点にする。
>e.Graphics.ScaleTransform(1, -1) 'Y軸方向を反転させる。つまり上方向がプラスになる。
Graphicsクラスにしか適用にならないのでしょうか?
宜しくお願いいたします。
投稿者 るきお  (社会人)
投稿日時
2020/9/22 18:11:46
そういうことでしたら、自分で座標を変換する関数を作成して、その都度呼び出すのが良いと思います。
下記の例では、VB(.NET)の座標系を学校座標系(左下が原点、Y軸は上方向がプラス)に変換する関数 PointToSchoolを作成し呼び出すことで、Labelに学校座標系を表示します。
>Graphicsクラスにしか適用にならないのでしょうか?
そうなんです。最初の投稿で紹介した TranslateTransformメソッドとScaleTransformメソッドは、Graphicsクラスを使う場合にしか役に立ちません。
下記の例では、VB(.NET)の座標系を学校座標系(左下が原点、Y軸は上方向がプラス)に変換する関数 PointToSchoolを作成し呼び出すことで、Labelに学校座標系を表示します。
Private Sub Form1_Click(sender As Object, e As EventArgs) Handles Me.Click
Dim sp As System.Drawing.Point = System.Windows.Forms.Cursor.Position
Dim cp As System.Drawing.Point = Me.PointToClient(sp)
Dim schoolP As System.Drawing.Point = Me.PointToSchool(cp)
Dim x As Integer = schoolP.X
Dim y As Integer = schoolP.Y
Label1.Text = "X:" & x & "Y:" & y & ""
End Sub
''' <summary>
''' 座標を学校座標系に変換します。
''' </summary>
''' <returns></returns>
Private Function PointToSchool(p As Point) As Point
Dim x As Integer = p.X
Dim y As Integer = Me.ClientSize.Height - p.Y
Return New Point(x, y)
End Function
>Graphicsクラスにしか適用にならないのでしょうか?
そうなんです。最初の投稿で紹介した TranslateTransformメソッドとScaleTransformメソッドは、Graphicsクラスを使う場合にしか役に立ちません。
投稿者 イヨ  (社会人)
投稿日時
2020/9/23 08:30:10
るきお様
コード確認しました。
Function PointToSchoo があったなんて、、!
>そうなんです。最初の投稿で紹介した TranslateTransformメソッドとScaleTransformメソッドは、Graphicsクラスを使う場合にしか役に立ちません。
自分はてっきり勘違いしていました。
やりたかったことができてすっきりしました!
これで座標系が取れますありがとうございます。mom
コード確認しました。
Function PointToSchoo があったなんて、、!
>そうなんです。最初の投稿で紹介した TranslateTransformメソッドとScaleTransformメソッドは、Graphicsクラスを使う場合にしか役に立ちません。
自分はてっきり勘違いしていました。
やりたかったことができてすっきりしました!
これで座標系が取れますありがとうございます。mom
投稿者 るきお  (社会人)
投稿日時
2020/9/28 20:18:51
解決してよかったです。
>Function PointToSchoo があったなんて、、!
私が作った関数なので無理もありません。
Private Function PointToSchool のところで名前を定義しています。
たとえば、ここを Private Function xxxxx に修正すると、関数名は xxxxx になります。
※「カーソルのトラッキングについて」(http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=30546)の方にも同じようなことを補足しました。
>Function PointToSchoo があったなんて、、!
私が作った関数なので無理もありません。
Private Function PointToSchool のところで名前を定義しています。
たとえば、ここを Private Function xxxxx に修正すると、関数名は xxxxx になります。
※「カーソルのトラッキングについて」(http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=30546)の方にも同じようなことを補足しました。
投稿者 イヨ  (社会人)
投稿日時
2020/9/30 08:58:47
ご返信ありがとうございます
>私が作った関数なので無理もありません。
初心者丸出しですいません///
ちょっとづつ勉強していきます。
教えてくださり有難うございます
>私が作った関数なので無理もありません。
初心者丸出しですいません///
ちょっとづつ勉強していきます。
教えてくださり有難うございます
座標の取得についてVBでは現在左上に座標原点(0.0)と設定してあります。
こちらを左下に設定するにはどうすればいいのでしょうか?
それっぽいことはネットに書いてありましたコードをコピペしてみたりしたりいろいろやっていますが
うまくいきません。
https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=9659&forum=7
宜しくお願いいたします。OrZ