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

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

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.97964 の関連記事表示

<< 0 >>
■97964  WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/13(Fri) 18:41:58)

    分類:[.NET 全般] 

    いつもお世話になっております。
    VB.NETに関する質問です。

    フォーム内でマウスクリックがされたこと示すウィンドウメッセージを、WndProcを使って取得したいのですが
    どうすればよいでしょうか?
    出来れば「押下した瞬間」ではなく「押下されている状態」を取得できるようにしたいです。

    ご教授お願い致します。

    Public Class Form1
    Protected Overrides Sub WndProc(ByRef m As Message)
    MyBase.WndProc(m)
    'ここで状態を取得したい
    End Sub
    End Class
親記事 /過去ログ170より / 関連記事表示
削除チェック/

■97965  Re[1]: WndProcによるマウス押下状態取得
□投稿者/ とっちゃん -(2021/08/13(Fri) 23:47:36)
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97966  Re[2]: WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/14(Sat) 17:39:56)
    とっちゃんさん回答ありがとうございます。

    フォームの表示・非表示を行うとマウスイベントが正常に取得できないケースがあります。

    ※フォーム1(スタートアップ時表示)
    Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    SetDesktopBounds(0, 0, 640, 480)
    Form2.Show()
    Form2.Hide()
    Form2.SetDesktopBounds(640, 0, 640, 480)
    End Sub

    Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    Hide()
    Form2.Show()
    End Sub

    Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    Stop
    End Sub
    End Class

    ※フォーム2
    Public Class Form2
    Private Sub Form2_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    Stop
    End Sub
    End Class

    MouseUpイベントが取得出来ればよいのですが、上記コードではマウスボタンを離した時のイベントがどちらのフォームでも発生しません。
    そのためTimerコントロールを用いてウィンドウメッセージを取得するしかないと思い、質問いたしました。


    > もし、API が使いたいのだ!ということであれば、GetAsyncKeyState API で判定できます(マウスの左ボタンなら、VK_LBUTTON)。
    > ・GetAsyncKeyState API
    > https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate?WT.mc_id=DT-MVP-32182

    上記URLではC++のコードしか記載されていませんが、VB.NETの場合はどのように書けばよろしいでしょうか?
    お手数をお掛けしますが、回答お願いいたします。

記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97967  Re[3]: WndProcによるマウス押下状態取得
□投稿者/ KOZ -(2021/08/14(Sat) 18:23:31)
    No97966 (プログラマー さん) に返信
    > MouseUpイベントが取得出来ればよいのですが、上記コードではマウスボタンを離した時のイベントがどちらのフォームでも発生しません。
    > そのためTimerコントロールを用いてウィンドウメッセージを取得するしかないと思い、質問いたしました。

    (1) Form1 の上でマウスボタンを押す
    (2) Form1 を隠して Form2 を表示
    (3) マウスボタンが離されたイベントを取得

    ということでしょうか?

    (2) の後で、Form1 でも Form2 のどちらでもいいのですが、Capture プロパティを True にすれば、MouseUp イベントが発生します。
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97969  Re[4]: WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/14(Sat) 20:09:37)
    KOZ さん回答ありがとうございます。

    > (1) Form1 の上でマウスボタンを押す
    > (2) Form1 を隠して Form2 を表示
    > (3) マウスボタンが離されたイベントを取得
    >
    > ということでしょうか?

    はい、そのような操作を想定しています。


    > (2) の後で、Form1 でも Form2 のどちらでもいいのですが、Capture プロパティを True にすれば、MouseUp イベントが発生します。

    Hideで非表示にした場合ですとイベントが発生しましたが、以下のように記述するとCaptureをTrueにしてもイベントが発生しません。
    最初の質問ではソースを簡略化してましたが、実際は以下の方法での表示・非表示を想定しています。失礼いたしました。
    この場合でもMouseUpイベントを取得することは可能でしょうか?

    Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    SetDesktopBounds(0, 0, 640, 480)
    Form2.Show()
    Form2.Opacity = 0
    Form2.ShowInTaskbar = False
    Form2.SetDesktopBounds(640, 0, 640, 480)
    End Sub

    Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    Opacity = 0
    ShowInTaskbar = False
    Form2.Opacity = 100
    Form2.ShowInTaskbar = True
    Capture = True
    End Sub

    Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    Stop
    End Sub
    End Class
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97976  Re[5]: WndProcによるマウス押下状態取得
□投稿者/ 魔界の仮面弁士 -(2021/08/15(Sun) 12:48:32)
    No97969 (プログラマー さん) に返信
    >> (1) Form1 の上でマウスボタンを押す
    >> (2) Form1 を隠して Form2 を表示
    >> (3) マウスボタンが離されたイベントを取得
    >> ということでしょうか?
    > はい、そのような操作を想定しています。

    No97964 時点では「押下されている状態」を取得とありましたが、
    No97969 時手では「離されたイベント」を取得ということで、
    質問内容が変化していますね。(^^;

    マウスボタンが離されたタイミングを取得するのが目的なら、
    WM_INPUT メッセージを処理する手法もあります。
    https://j.mp/3jSFlNu


    しかしこの場合、自前で API 宣言を連ねるよりも、
    SharpDX.RawInput を NuGet 参照するのが手っ取り早いでしょう。

    Imports SharpDX.RawInput
    Public Class Form1
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      Device.RegisterDevice(SharpDX.Multimedia.UsagePage.Generic, SharpDX.Multimedia.UsageId.GenericMouse, DeviceFlags.None)

      SetDesktopBounds(0, 0, 640, 480)
      Form2.Show()
      Form2.Opacity = 0
      Form2.ShowInTaskbar = False
      Form2.SetDesktopBounds(640, 0, 640, 480)
     End Sub

     Private Sub RawInput_MouseInput(sender As Object, e As MouseInputEventArgs)
      If e.ButtonFlags.HasFlag(MouseButtonFlags.LeftButtonUp) Then
       RemoveHandler Device.MouseInput, AddressOf RawInput_MouseInput

       Stop
      End If
     End Sub

     Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
      If e.Button.HasFlag(MouseButtons.Left) Then
       Opacity = 0
       ShowInTaskbar = False
       Form2.Opacity = 100
       Form2.ShowInTaskbar = True
       AddHandler Device.MouseInput, AddressOf RawInput_MouseInput
      End If
     End Sub
    End Class


    > Hideで非表示にした場合ですとイベントが発生しましたが、以下のように記述するとCaptureをTrueにしてもイベントが発生しません。

    MouesDown 時と MouseUp 時とで、キャプチャしたウィンドウのハンドルが異なるため、
    Capture プロパティが期待動作しなくなっています。

    ShowInTaskBar はフォーム生成前に呼び出し、そのあとは変更すべきではありません。
    これはフォーム起動時に呼び出される CreateParams プロパティの ExStyle で利用される設定値だからです。

    Windows API 側の制限により、この値はハンドル生成時にしか指定できないため、
    フォーム生成後に切り替えた場合は、現在のウィンドウ ハンドルが作り直されることになります。

    Debug.WriteLine(Me.Handle)
    Me.ShowInTaskbar = False
    ' Me.RecreateHandle() 'ShowInTaskbar の変更により、内部的に RecreateHandle が呼ばれる
    Debug.WriteLine(Me.Handle) 'それにより、ウィンドウハンドルが別の値になる
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97985  Re[6]: WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/17(Tue) 18:26:22)
    魔界の仮面弁士さん回答ありがとうございます。

    > No97964 時点では「押下されている状態」を取得とありましたが、
    > No97969 時手では「離されたイベント」を取得ということで、
    > 質問内容が変化していますね。(^^;

    「離された瞬間」を取得するより、Timerコントロールを用いて一定間隔ごとに「押下されている状態」をチェックする方が確実だと思い質問しましたが・・・
    確かにおっしゃる通りです。失礼いたしました。

    > しかしこの場合、自前で API 宣言を連ねるよりも、
    > SharpDX.RawInput を NuGet 参照するのが手っ取り早いでしょう。

    このようなやり方があったのですね。

    > MouesDown 時と MouseUp 時とで、キャプチャしたウィンドウのハンドルが異なるため、
    > Capture プロパティが期待動作しなくなっています。
    >
    > ShowInTaskBar はフォーム生成前に呼び出し、そのあとは変更すべきではありません。
    > これはフォーム起動時に呼び出される CreateParams プロパティの ExStyle で利用される設定値だからです。
    >
    > Windows API 側の制限により、この値はハンドル生成時にしか指定できないため、
    > フォーム生成後に切り替えた場合は、現在のウィンドウ ハンドルが作り直されることになります。

    詳しく説明していただきありがとうございます。
    この点を考慮して書き直してみます。

    この質問は解決済みとさせていただきます。
    ご回答くださった方々有難うございました。
記事No.97964 のレス / END /過去ログ170より / 関連記事表示
削除チェック/

■97968  Re[3]: WndProcによるマウス押下状態取得
□投稿者/ とっちゃん -(2021/08/14(Sat) 19:49:32)
    No97966 (プログラマー さん) に返信

    >>もし、API が使いたいのだ!ということであれば、GetAsyncKeyState API で判定できます(マウスの左ボタンなら、VK_LBUTTON)。
    >>・GetAsyncKeyState API
    >>https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate?WT.mc_id=DT-MVP-32182
    >
    > 上記URLではC++のコードしか記載されていませんが、VB.NETの場合はどのように書けばよろしいでしょうか?
    > お手数をお掛けしますが、回答お願いいたします。
    >
    >
    Control.MouseButtons では判定できませんでしたか?
    それとも、「APIが使いたいのだ!」ということでしょうか?

    後者であれば、改めて書いてもらえばと思います。
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97970  Re[4]: WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/14(Sat) 20:21:01)
    No97968 (とっちゃん さん) に返信

    > Control.MouseButtons では判定できませんでしたか?

    MouseMoveイベント内に以下のコードを記述しましたが、判定できませんでした。

    If e.Button = MouseButtons.Left Then
    Stop
    End If

    改めてAPIを用いた処理を教えていただきたいです。
    よろしくお願いします。
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97971  Re[5]: WndProcによるマウス押下状態取得
□投稿者/ とっちゃん -(2021/08/14(Sat) 21:21:10)
    No97970 (プログラマー さん) に返信
    > ■No97968 (とっちゃん さん) に返信
    >
    >>Control.MouseButtons では判定できませんでしたか?
    >
    > MouseMoveイベント内に以下のコードを記述しましたが、判定できませんでした。
    >
    > If e.Button = MouseButtons.Left Then
    > Stop
    > End If
    >
    > 改めてAPIを用いた処理を教えていただきたいです。
    > よろしくお願いします。

    MouseEventArgs のメンバーの e.Button ではなく、Control.MouseButtons という Control クラスのスタティック(Shared)プロパティです。

    一度こちらの「リファレンス」に目を通してみてください。
    https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.control.mousebuttons?WT.mc_id=DT-MVP-32182&view=netframework-4.8

記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97972  Re[6]: WndProcによるマウス押下状態取得
□投稿者/ プログラマー -(2021/08/15(Sun) 06:07:58)
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/

■97974  Re[7]: WndProcによるマウス押下状態取得
□投稿者/ 魔界の仮面弁士 -(2021/08/15(Sun) 10:36:13)
    No97972 (プログラマー さん) に返信
    >>MouseEventArgs のメンバーの e.Button ではなく、Control.MouseButtons という Control クラスのスタティック(Shared)プロパティです。
    > MouseUpイベントが発生しないので、上記リファレンス通りの書き方をしても正常に動作しませんでした。

    MouseUp イベントを使う必要があるなどとは、誰も言っていませんよ。

    もちろん MouseDown や MouesUp 中でも利用できますが、
    No97965 でも書かれているように、いつでもどのタイミングでも利用できます。
    たとえば WndProc 中や Timer_Tick あるいは Button_Click や PictureBox_Paint でも呼び出せます。

     'Left, Middle, Right, XButton1, XButton2
     Dim leftButtonPressing As Boolean = MouseButtons.HasFlag(MouseButtons.Left)

    この System.Windows.Forms.Control クラスの MouseButtons プロパティとは
    内部的には GetKeyState API を呼び出すだけの処理です。

    これと既に紹介されている GetAsyncKeyState API との違いですが、
    GetKeyState が、Windows Message 取得時のキー入力状態を取得するものであるのに対し、
    GetAsyncKeyState が、IRQ (ハードウェア割り込み)レベルでのキー取得となっています。

    ほとんどの場合は MouseButtons で事足りるとは思いますが、高負荷状態などで
    メッセージループを捌き切れていない状態(それは大抵、作りこみがマズイという
    ことでもあるのですが)の場合、MouseButtons では期待する結果が得られないかもしれません。

    仮に MouseButtons で拾えないケースにおいても、GetAsyncKeyState であれば、
    現在のマウスボタンやキーボード状態を得ることができるでしょう。宣言例はこちら。
    http://kchon.blog111.fc2.com/blog-entry-137.html
    https://www.chuken-engineer.com/entry/2019/06/20/000247

    この時、マウスボタンを表す定数値として
     Public Const VK_LBUTTON As Integer = 1 '← No97965 にて紹介済み
     Public Const VK_RBUTTON As Integer = 2
     Public Const VK_MBUTTON As Integer = 4
     Public Const VK_XBUTTON1 As Integer = 5
     Public Const VK_XBUTTON2 As Integer = 6
    を利用できますが、これらは同値が System.Windows.Forms.Keys 列挙体として
     Keys.LButton
     Keys.RButton
     Keys.MButton
     Keys.XButton1
     Keys.XButton2
    として定義済みのため、あえて定数を切りなおさずとも、これらを利用して呼び出すこともできます。


    ただしこうした呼び出しは、セキュリティ系のソフトによって検出されやすくなります。

    たとえば Timer 等で常時監視するような操作は、危険性のあるソフトウェア(たとえばキーロガーなど)と
    誤解されてしまい、ブロックや駆除対象になりえます。その点は注意が必要でしょう。
記事No.97964 のレス /過去ログ170より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -