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

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

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

No.92988 の関連記事表示

<< 0 >>
■92988  キーボードを押した時に二重実行を防止するには
□投稿者/ けーえんす -(2019/11/12(Tue) 15:47:23)

    分類:[.NET 全般] 

    キーボードの矢印キーを押すと、Trackbarが移動するとともに、ある重い処理が実行されるプログラムを書いています。
    一回ずつキーを押した場合には問題ないのですが、
    矢印キーを押しっぱなしにした時に、キーを離してもしばらく処理が何度も実行されるという現象が起きています。

    これを回避するために、ブーリアン変数で排他的に処理できるようにしてあるのですが、
    それでもやはりうまくいきません、


    コードは以下の通りです。

    恐らく、2回目以降のキーの実行はArrowKeyMovementが実行される前の段階でキュー待ちような状態になっているのではないかと思います。


    どうすれば良いでしょうか?


    AddHandler TrackBar1.KeyDown, AddressOf CursorMovementKeyDown





    Private Sub CursorMovementKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)

    e.Handled = ArrowKeyMovement(e.KeyCode)

    End Sub

    Dim FrameChangingBool As Boolean = False


    Function ArrowKeyMovement(keyCode As Keys) As Boolean

    If FrameChangingBool = False Then

    FrameChangingBool = True

    Select Case keyCode
    Case Keys.Left

    Dim SetValue As Integer = TrackBar1.Value - 1

    If SetValue >= TrackBar1.Minimum Then

    TrackBar1.Value = SetValue

    End If

    FrameChangingBool = False

    Return True
    Case Keys.Right

    Dim SetValue As Integer = TrackBar1.Value + 1

    If SetValue <= TrackBar1.Maximum Then

    TrackBar1.Value = SetValue

    End If

    FrameChangingBool = False
    Return True

    Case Else
    FrameChangingBool = False
    Return False
    End Select

    Else

    Select Case keyCode
    Case Keys.Left, Keys.Right
    Return True
    Case Else
    Return False
    End Select

    End If

    End Function



    Private Sub TrackBar1_ValueChanged(sender As Object, e As EventArgs) Handles TrackBar1.ValueChanged

    ’ 重い処理


    End Sub
親記事 /過去ログ161より / 関連記事表示
削除チェック/

■92995  Re[1]: キーボードを押した時に二重実行を防止するには
□投稿者/ ぼーちゃん -(2019/11/12(Tue) 17:51:20)
    ValueChangedイベントハンドラ内でValueChangedイベントハンドラをRemove
    KeyUpイベントハンドラ内でAddするのはどうですか
    
    
        'ValueChanged, KeyDown, KeyUpイベントハンドラはデザイナから自動生成
    
        Private KeyDownCancel As Boolean = False
    
        Private Sub TrackBar1_ValueChanged(sender As Object, e As EventArgs) Handles TrackBar1.ValueChanged
            Console.WriteLine("ValueChanged")
            RemoveHandler TrackBar1.ValueChanged, AddressOf TrackBar1_ValueChanged
            Console.WriteLine("重い処理")
        End Sub
    
        Private Sub TrackBar1_KeyDown(sender As Object, e As KeyEventArgs) Handles TrackBar1.KeyDown
            Console.WriteLine("KeyDown")
            e.Handled = KeyDownCancel
            KeyDownCancel = True
        End Sub
    
        Private Sub TrackBar1_KeyUp(sender As Object, e As KeyEventArgs) Handles TrackBar1.KeyUp
            Console.WriteLine("KeyUp")
            AddHandler TrackBar1.ValueChanged, AddressOf TrackBar1_ValueChanged
            KeyDownCancel = False
        End Sub
記事No.92988 のレス /過去ログ161より / 関連記事表示
削除チェック/

■92997  Re[1]: キーボードを押した時に二重実行を防止するには
□投稿者/ KOZ -(2019/11/13(Wed) 05:53:43)
    No92988 (けーえんす さん) に返信
    > 恐らく、2回目以降のキーの実行はArrowKeyMovementが実行される前の段階でキュー待ちような状態になっているのではないかと思います。
    
    メッセージループを止めるとキーボードを押した等のメッセージはキューに貯まります。
    ループが再開する前にメッセージを PeekMessage で刈り取るといいかと。
    
    Imports System.Threading
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        Private Sub TrackBar1_ValueChanged(sender As Object, e As EventArgs) Handles TrackBar1.ValueChanged
            Debug.Print("重い処理開始")
            Thread.Sleep(10000)
            Debug.Print("重い処理終了")
            CancelInput()
        End Sub
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure MSG
            Public hwnd As IntPtr
            Public Msg As Integer
            Public WParam As IntPtr
            Public LParam As IntPtr
            Public time As Integer
            Public x As Integer
            Public y As Integer
        End Structure
    
        Private Const WM_KEYFIRST As Integer = &H100
        Private Const WM_KEYLAST As Integer = &H108
        Private Const PM_REMOVE As Integer = &H1
        Private Const WM_MOUSEFIRST As Integer = &H200
        Private Const WM_MOUSELAST As Integer = &H20E
    
        <DllImport("User32.dll", CharSet:=CharSet.Auto)>
        Private Shared Function PeekMessage(ByRef msg As MSG, hwnd As IntPtr, msgMin As Integer, msgMax As Integer, remove As Integer) As Boolean
    
        End Function
    
        Private Sub CancelInput()
            Dim msg As New MSG
            While PeekMessage(msg, IntPtr.Zero, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)
    
            End While
            While PeekMessage(msg, IntPtr.Zero, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)
    
            End While
        End Sub
    
    End Class
    
記事No.92988 のレス /過去ログ161より / 関連記事表示
削除チェック/

■93000  Re[1]: キーボードを押した時に二重実行を防止するには
□投稿者/ まりもん -(2019/11/13(Wed) 10:10:05)
    ValueChangedイベントで重い処理を行う設計がよくないのではないでしょうか?
    キーボードからの入力で重い処理を行うことを排他したとしても、マウスで操作した場合にValueChangedイベントが連続で発声することになるのではないですか?
記事No.92988 のレス /過去ログ161より / 関連記事表示
削除チェック/

■93003  Re[2]: キーボードを押した時に二重実行を防止するには
□投稿者/ けーえんす -(2019/11/13(Wed) 11:36:02)
    > KOZさん

    ありがとうございます。
    このコードでうまくいきました。

    ちなみに、毎回実行ごとに、キーボードからの処理をキャンセルするわけなので、
    連続実行したい場合には、処理速度が落ちませんかね?

    CancelInputを
    MouseUpに入れれば良いかと思い入れてみたのですが、
    MouseUpだとうまくキャンセルすることができませんでした。
記事No.92988 のレス /過去ログ161より / 関連記事表示
削除チェック/

■93004  Re[3]: キーボードを押した時に二重実行を防止するには
□投稿者/ KOZ -(2019/11/13(Wed) 14:07:17)
    No93003 (けーえんす さん) に返信
    > ちなみに、毎回実行ごとに、キーボードからの処理をキャンセルするわけなので、
    > 連続実行したい場合には、処理速度が落ちませんかね?
    
    キーリピートのみ抑止であれば
    
        Private _IsKeyDown As New Dictionary(Of Keys, Boolean)
    
        Private Sub TrackBar1_KeyDown(sender As Object, e As KeyEventArgs) Handles TrackBar1.KeyDown
            Dim state As Boolean
            If Not _IsKeyDown.TryGetValue(e.KeyCode, state) Then
                state = False
            End If
            e.Handled = state
            _IsKeyDown(e.KeyCode) = True
        End Sub
    
        Private Sub TrackBar1_KeyUp(sender As Object, e As KeyEventArgs) Handles TrackBar1.KeyUp
            _IsKeyDown(e.KeyCode) = False
        End Sub
    
    マウスもドラッグ中は処理せず、ボタンを離したとき実行するなら
    
        Private _MouseIsDown As Boolean
        Private _MouseDownValue As Integer
    
        Private Sub TrackBar1_MouseDown(sender As Object, e As MouseEventArgs) Handles TrackBar1.MouseDown
            If e.Button.HasFlag(MouseButtons.Left) Then
                _MouseDownValue = TrackBar1.Value
                _MouseIsDown = True
            End If
        End Sub
    
        Private Sub TrackBar1_MouseUp(sender As Object, e As MouseEventArgs) Handles TrackBar1.MouseUp
            If e.Button.HasFlag(MouseButtons.Left) Then
                If _MouseDownValue <> TrackBar1.Value Then
                    _MouseIsDown = False
                    HevyProc(TrackBar1.Value)
                End If
            End If
        End Sub
    
        Private Sub TrackBar1_ValueChanged(sender As Object, e As EventArgs) Handles TrackBar1.ValueChanged
            If Not _MouseIsDown Then
                HevyProc(TrackBar1.Value)
            End If
        End Sub
    
        Private Sub HevyProc(trackBarValue As Integer)
            Debug.Print("重い処理開始 value={0}", trackBarValue)
            Thread.Sleep(1000)
            Debug.Print("重い処理終了")
        End Sub
    
    こんな感じですかね。
    
記事No.92988 のレス /過去ログ161より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -