マウスカーソル位置の指定

タグの編集
投稿者 hk  (学生) 投稿日時 2025/5/21 15:46:57
vb.net2019 FrameWorks3.5
メインフォームからサブフォームを開く際、
サブフォーム側のLoadイベントで以下の関数を走らせて、指定したコントロール上にマウスカーソルが移動するようにしました。
Public Shared Sub MouseCursorMoveToControl(ctrl As Control)
            Dim iWidth = ctrl.Width \ 2
            Dim iHeight = ctrl.Height \ 2
            Dim point = ctrl.PointToScreen(New Point(iWidth, iHeight))
            Cursor.Position = point
 End Sub
1度目は想定通りの挙動をするのですが、2度目以降マウスカーソルが移動しなくなります。

メインフォームからサブフォーム開く際は、UsingからのShowDIalogで開いています。
この時、FormStartPositionをManualにしていることが関係していることはわかったのですが、
どうしてもForm位置を指定したいです。
何かいい方法はないでしょうか?
また、何故2度目以降から移動しなくなるのか解説できる方がいたら教えて欲しいです。
投稿者 とくま  (社会人) 投稿日時 2025/5/22 09:29:48
>マウスカーソルが移動するようにしました。
>どうしてもForm位置を指定したいです。
カーソル位置を指定するプログラムを書いて、フォーム位置が変わらないという文章が書かれているようです。
何を言いたいのか分かりませんが、フォーム位置を指定するプログラムを書けばいいのでは?

>また、何故2度目以降から移動しなくなるのか解説できる方がいたら教えて欲しいです。
カーソル位置は何度実行しても移動しました。問題なさそうです。
投稿者 hk  (学生) 投稿日時 2025/5/22 11:20:40
>カーソル位置を指定するプログラムを書いて、フォーム位置が変わらないという文章が書かれているようです。
>何を言いたいのか分かりませんが、フォーム位置を指定するプログラムを書けばいいのでは?
FormStartPositionをManualに設定して、フォーム位置を指定すると2回目以降のForm呼び出しから
マウスカーソルが指定コントロール上に移動してくれません。
FormStartPositionをManual以外に設定すると、何度実行しても移動しました。

>また、何故2度目以降から移動しなくなるのか解説できる方がいたら教えて欲しいです。
>カーソル位置は何度実行しても移動しました。問題なさそうです。
FormStartPositionをManualでも問題無く動作しますか?
私のプログラムでは2回目以降動作は動作しませんでした。。
投稿者 とくま  (社会人) 投稿日時 2025/5/22 14:35:17
>vb.net2019 FrameWorks3.5
2019でデフォルトの.NET Frameworkは4.8のはずなので、3.5までダウングレードしているということですよね。
.NET Framework3.5のリリースは2007年とかなので、大きな不具合はもう殆ど対応済みだと思います。

この手のバグで良くあるのは、インスタンスの管理ができていないPGを書いてしまっている場合ですが、
ShowDialogはDisposeを呼ばないとインスタンスが残るものの、Usingが呼び出すので問題なさそう。
この時点で1度目と2度目で動作が違うようなPGを組む方が困難になります。

となると座標の解釈を最初から間違って覚えてしまっているとか、自分でも覚えてない設定をデザイナで
やってしまってるとか。座標系は最大化とかしちゃうと正しく取れなくなったりはするので、初期表示の
WindowStateとか変えてると不具合を起こさせるのは可能かもしれない。

書いてない情報をエスパーするのは難しいので、新規プロジェクトで最小限の再現するコードを作るのが
早道かなぁ。あとは座標を画面やConsole.WriteLineで書き出して地道にデバッグしてみてください。
https://atmarkit.itmedia.co.jp/ait/articles/0511/18/news137.html

新規プロジェクトでフォームデザイナは全てデフォルト設定。以下のコードのみで動作確認してみてください。
こちらの環境では特に問題になりそうな動きはしませんでした。
'Form1 
Public Class Form1
    Private _ClickCount As Integer = 0
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        _ClickCount = _ClickCount + 1
        Using frm As New Form2
            frm.StartPosition = FormStartPosition.Manual
            frm.Top = 200 + 50 * _ClickCount
            frm.Left = 400 + 50 * _ClickCount
            frm.ShowDialog()
        End Using
    End Sub
End Class

'Form2 
Public Class Form2
    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Class1.MouseCursorMoveToControl(Me.TextBox1)
    End Sub
End Class

'Class1 
Public Class Class1
    Public Shared Sub MouseCursorMoveToControl(ctrl As Control)
        Dim iWidth = ctrl.Width \ 2
        Dim iHeight = ctrl.Height \ 2
        Dim point = ctrl.PointToScreen(New Point(iWidth, iHeight))
        Cursor.Position = point
    End Sub
End Class

投稿者 hk  (学生) 投稿日時 2025/5/22 19:51:23
新規プロジェクトでいただいたコードが正常に動作することを確認しました。
また、デバックでは、正常にマウスカーソルが移動するのが確認できました。
ですが、やはり実行すると2回目以降はマウスカーソルが移動しません。
処理が追いついてないのかとThreading.Thread.Sleepで遅らせてみましたが変化はありませんでした。

コードに問題がないことが確認できただけでも助かりました!
丁寧な説明ありがとうございます!もう少し原因を探ってみます!

投稿者 hk  (社会人) 投稿日時 2025/5/23 07:34:32
_iShowCnt += 1
Dim pt = New Point(Me.Location.X + 20 + _iShowCnt,
                              Me.Location.Y + 200)
|
If _iShowCnt = 2 Then _iShowCnt = 0

とくまさんからアドバイスいただいたClick回数をカウントしてサブフォームのロケーション位置を前回から少しずらすようにしたところ、
正常に動作するようになりました!!

それならばと、最初に強制的にマウス位置を変更してみましたが、こちらは効果がありませんでした。
Public Shared Sub MousePointerMoveToControl(ctrl As Control)
            Cursor.Position = New Point(0, 0)

            Dim iWidth = ctrl.Width \ 2
            Dim iHeight = ctrl.Height \ 2
            Dim point = ctrl.PointToScreen(New Point(iWidth, iHeight))

            Cursor.Position = point
End Sub

とても勉強になりました!
本当にありがとうございます!