kkdxghlctlcxxtidyuum Ответов: 3

Как я могу гарантировать, что только один r/l клик будет добавлен в мой список?


Эй :)

Мне нужна некоторая помощь с небольшим количеством кода, я уже некоторое время борюсь с этим и был бы рад, если бы кто-то мог мне помочь. Таким образом, когда пользователь (я сам, поскольку я не распространяю) щелкает правой кнопкой мыши или щелкает левой кнопкой мыши, либо "10000", либо "10001" соответственно добавляются в список. Однако, как вы можете видеть, почему в приведенном ниже коде целые числа, указывающие на правый или левый щелчок (10000/10001), перечислены несколько раз, потому что каждый раз, когда таймер тикает, r/l щелчок записывается, если кнопки нажаты. Даже когда я обычно щелкаю мышью, она будет выводить "10000" 6 раз, например, потому что интервал таймера очень быстрый (10 мс).

Поэтому в основном мне нужно убедиться, что добавляется только одно из этих целых чисел (т. е. отображается только фактическое событие нажатия на кнопки мыши r/l, а не запись, если оно нажимается каждые 10 мс.
Вот код, который у меня есть до сих пор:
<pre>    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vkey As Long) As Integer
    Declare Sub mouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Integer, ByVal dx As Integer, ByVal dy As Integer, ByVal cButtons As Integer, ByVal dwExtraInfo As Integer)
    Public Const MOUSEEVENTF_LEFTDOWN = &H2
    Public Const MOUSEEVENTF_LEFTUP = &H4
    Public Const MOUSEEVENTF_RIGHTDOWN = &H8
    Public Const MOUSEEVENTF_RIGHTUP = &H10
    Dim Mouse_LeftClick As Boolean
    Dim Mouse_RightClick As Boolean

 
Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer.Tick

        Mouse_LeftClick = GetAsyncKeyState(Keys.LButton)

        If Mouse_LeftClick Then

            Mouse.Items.Add("10000")

        Else

        End If

        Mouse_RightClick = GetAsyncKeyState(Keys.RButton)

        If Mouse_RightClick Then

            Mouse.Items.Add("10001")

        Else

        End If

    End Sub


Вот примерно и подводит итог, надеюсь, вы понимаете мою проблему и заранее большое спасибо! :) Кроме того, я пытаюсь лучше освоить этот язык, если вы заметите что-то неправильное в том, как я отформатировал код, Пожалуйста, скажите мне (например, слишком много пробелов, легко ли это понять)!

Спасибо!

Что я уже пробовал:

Я попытался сделать так, чтобы в первых 10 или около того элементах списка мог существовать только 1 клик, но это просто непрактично, особенно учитывая скорость таймера. :|

GKP1992

Почему вы используете таймер?Тиковое событие, а не событие щелчка мыши?

[no name]

Привет :)

Спасибо за ваше предложение! Однако я не знаю, какой элемент моей формы должен иметь событие mouse_click, поскольку моя форма довольно сложна тем, что к ней прикреплено несколько дочерних окон (wordpad, excel). Если я нажму на любое из этих дочерних окон, я не нажму ни на один элемент, и, таким образом, mouse_click не будет работать (я не думаю, что это будет в любом случае). Timer_tick, с другой стороны, делает список кликов по дочерним окнам.

Возможно, вы правы, но я попробовал ваше предложение и не смог заставить его работать, хотя спасибо!

3 Ответов

Рейтинг:
14

Ralf Meier

То, что вы можете сделать, это (на основе nSuggestion GKP1992) :
- переопределите метод OnControlAdded-вашей формы
- поймать MouseClick-событие от каждого элемента управления формы (каждый добавленный элемент управления)
- внутри MouseClick-Eventhandler добавьте информацию в свой список

Public Class Form1

    Protected Overrides Sub OnControlAdded(e As ControlEventArgs)
        Dim myControl As Control = e.Control
        AddHandler myControl.MouseClick, AddressOf MouseClickHandler
        MyBase.OnControlAdded(e)
    End Sub

    Private Sub MouseClickHandler(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
        If e.Button = MouseButtons.Left Then ListBox1.Items.Add("Left")
        If e.Button = MouseButtons.Right Then ListBox1.Items.Add("Right")
     End Sub

end class


[no name]

Привет Ральф :)

Это очень хорошо работает для любых объектов формы и намного проще, чем мой предыдущий код (спасибо за знания), однако, поскольку мне нужно, чтобы щелчки мыши записывались при нажатии на внешний процесс (который установлен как дочерний в моем родительском окне), это, к сожалению, не работает. Мой предыдущий код действительно работает с дочерней формой, однако, как я уже объяснял, он записывает несколько кликов, а не только один, как в функции таймера. У тебя есть какие-нибудь идеи? Рейтинг, в любом случае.

Большое спасибо за вашу помощь и Ваше время,
hbf2

Ralf Meier

Привет Хеллбой,
спасибо за Ваш голос.
Возможно, я мог бы помочь вам еще раз, но в данный момент я понятия не имею, что вы имеете в виду под "внешним процессом (который установлен как ребенок в моем родительском окне)". Пожалуйста, объясните это или лучше приведите мне пример ...

[no name]

Эй, Ральф, спасибо за твое терпение. Под этим я подразумеваю приложение, отличное от моей фактической формы, встроенное в мое пространство формы. Это достигается с помощью этого кода:
--------------------------------------------------------------------------------------------------------

&ЛТ;атрибут DllImport("user32.dll")&ГТ; общие setparent осуществляет функции(hWndChild бывал в качестве указателя IntPtr, бывал hWndNewParent в качестве указателя IntPtr) Как IntPtr
Конечная Функция
&ЛТ;атрибут DllImport("user32.dll")&ГТ; общие функции SendMessage(как byval в качестве указателя IntPtr hwnd элемента, бывал Сообщение Как целое, бывал параметр wparam как целое, как byval lparam должен как целое) Как Целое Число
Конечная Функция
Private Const WM_SYSCOMMAND As Integer = &H112
Private Const SC_MAXIMIZE As Integer = &HF030

Private Sub SetChildTimer_Tick(sender As Object, e As EventArgs) обрабатывает SetChildTimer.Галочка
Dim ClientProcess As Process = Процесс.GetProcessesByName("Блокнот").Метода firstordefault

Если ClientProcess-Это Не Ничто, То

SetParent(ClientProcess.MainWindowHandle, ClientContainer.Ручка)
SendMessage(ClientProcess.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)

Конец, Если

Сетчайлдтаймер.Включено = Ложь
Конец Подводной Лодки

--------------------------------------------------------------------------------------------------------

Это позволит установить блокнот в качестве дочернего элемента vb.net форма после того, как таймер тикнул.

Вот примерная картинка: https://i-msdn.sec.s-msft.com/dynimg/IC118780.gif
(из MSDN - не злонамеренный)
Таким образом, хотя дочерняя форма встроена и стала частью родительского приложения, она все еще остается внешним процессом. Он ограничивается границами форм, но не становится фактическим элементом формы, и поэтому код, который вы любезно разместили, не будет работать.

Спасибо!

PS: Если вам нужно знать имя процесса, когда вы помогаете мне с кодом, то его дескриптор - "WPS Spreadsheets (32 bit)", а имя процесса - "et.exe"

Ralf Meier

ОК... Я понимаю, что вы имеете в виду ... и мне очень жаль ... для этого я не знаю решения, потому что (как вы написали) Блокнот на самом деле не принадлежит вашей форме, и поэтому я не могу уловить события из него.
Но вы также должны понимать, что это приложение, возможно, зацепляет сами события, и поэтому вы не получите правильную информацию "снаружи". Так что, если я прав, Ваш метод таймера также потерпит неудачу ...

Но скажите мне, пожалуйста : для чего вам это нужно на самом деле ?

[no name]

Hello, sorry for my late reply, I don't expect you to reply to this promptly either xD. The timer method does capture the mouse click. If you look at the code, it captures all mouse clicks, not only the ones that occur inside my form, but also outside of the form. The problem is, each time the timer ticks (every 50ms or so), the mouse click is recorded - so it records the actual time in which to click is held down, I don't want it to do that, I want it to record the actual event of clicking, that way only a single "10000" is returned to the listbox. Some, in capturing the mouse clicks [essentially] the method works, it just needs honing - it must only capture the action of clicking once.

Ralf Meier

ОК... так почему же вы сравниваете фактическое состояние кнопок мыши с последним состоянием ваших кнопок мыши (с вашим методом)? Если есть разница (в направлении "вверх"), вы сохраняете результат в своем списке (и только тогда).

Ralf Meier

Смотрите мое новое решение ...

Рейтинг:
10

Ralf Meier

На основе предложения, которое я сделал в решении 2, был создан новый фрагмент кода :

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vkey As Long) As Integer

Dim Mouse_LeftClick As Boolean
Dim Mouse_RightClick As Boolean
Dim Mouse_LeftClick_Last As Boolean
Dim Mouse_RightClick_Last As Boolean


Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

    Mouse_LeftClick = GetAsyncKeyState(Keys.LButton)
    If Mouse_LeftClick And Not Mouse_LeftClick_Last Then
        ListBox1.Items.Add("Left")
    End If
    Mouse_LeftClick_Last = Mouse_LeftClick

    Mouse_RightClick = GetAsyncKeyState(Keys.RButton)
    If Mouse_RightClick And Not Mouse_RightClick_Last Then
        ListBox1.Items.Add("Right")
    End If
    Mouse_RightClick_Last = Mouse_RightClick

End Sub


Рейтинг:
0

Peter_in_2780

Если вы застряли с использованием тика таймера, то вам нужно запомнить кнопки мыши от одного тика к другому. Затем вы добавляете "событие мыши" только в том случае, если оно новое, то есть кнопка нажата сейчас, но не была нажата в прошлый раз.

Псевдокод:

static oldstate = impossible_value

timer_tick:
  newstate = getmousestate()
  if ((newstate != oldstate) && (oldstate != impossible_value))
    process_the_new_state()  <<<< do your thing here
  oldstate = newstate  <<<< remember for next time


[no name]

Я, вероятно, неправильно истолковал ваш комментарий, но несколько щелчков мыши должны быть записаны, я не уверен, как это сделать. Оценка независимо от того, для вашего времени. :)

Peter_in_2780

Я обновил свое решение с помощью псевдокода. Попробуй это сделать.