PDA

View Full Version : استفاده از چند کلید...



Saman_12
دوشنبه 30 اردیبهشت 1392, 13:21 عصر
سلام.
چند روز پیش بدنبال این بودم که کاربر بتونه با چند کلید (مثلا ctrl + shift + D + D0) برنامه رو فعال کنه یا حالا هر کار دیگه ای (پس میشه خارج از فرم هم استفاده کرد!)...

Imports System.Threading

Public Class ClsGKS

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

Public Event Pressed(timeout As Int32, redo As Boolean, oncepress As Boolean)

Public Property Keyslist As Keys()
Public Sub New(Optional Keys() As Keys = Nothing)

Keyslist = Keys
End Sub

Public Sub StartCapture(Optional timeout As Int32 = 0, Optional redo As Boolean = True, Optional oncepress As Boolean = True)

Dim TGetKS As New Thread(AddressOf GetKS)

TGetKS.IsBackground = True
TGetKS.Start({timeout, oncepress, redo})
End Sub

Private Sub WaitOn()

For i As Int32 = 0 To Keyslist.Length - 1

Thread.Sleep(1)
If GetAsyncKeyState(Keyslist(i)) Then i = 0
Next
End Sub

Private Sub GetKS(args As Object)

Dim timeout As Int32 = args(0)
Dim oncepress As Boolean = args(1)
Dim redo As Boolean = args(2)

Dim IsKeyspress As New Boolean
Dim Pressedlist As New ArrayList
Dim Starttime As Date = Nothing
Dim Endtime As Date = Nothing

Do Until IsKeyspress

Thread.Sleep(1)
Starttime.AddMilliseconds(1)

For i As Int32 = 0 To Keyslist.Length - 1

If GetAsyncKeyState(Keyslist(i)) AndAlso Not Pressedlist.Contains(i) Then

Pressedlist.Add(i)
If Pressedlist.Count = 1 Then Starttime = Date.Now
End If
Next

If Pressedlist.Count = Keyslist.Length Then

Endtime = Date.Now

If timeout = 0 Then Starttime = Endtime
If Not (Endtime - Starttime).TotalMilliseconds > timeout Then

IsKeyspress = True : RaiseEvent Pressed(timeout, redo, oncepress)

If oncepress Then WaitOn()
If redo Then StartCapture(timeout, redo, oncepress)
Else

WaitOn()
Pressedlist.Clear()
End If
End If
Loop
End Sub

End Class



اینم همون بالایی هست یه نمور تغییرش دادم :


Imports System.Threading


Public Class GKS


Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Keys) As Boolean


Private _keyspresscallback As ContextCallback
Public Sub New(ByVal KeysPressCallback As ContextCallback)


_keyspresscallback = KeysPressCallback
End Sub


Public Event KeysPress(keysl As List(Of Keys))


<MTAThread()> _
Public Sub CaptureKeys(keys As List(Of Keys), Optional oncepress As Boolean = False, Optional timeout As Int32 = 1500, Optional checktime As Int32 = 250)


Dim KeysListed As New List(Of Keys)
Dim StWatch As New Stopwatch


Dim TimerCallback As New TimerCallback(AddressOf _capturekayes)
Dim NewTimer As New Timer(TimerCallback, {keys, oncepress, timeout, StWatch, KeysListed}, 0, checktime)
End Sub


Private Sub _capturekayes(args As Object)


Dim keysl As List(Of Keys) = args(0)
Dim oncepress As Boolean = args(1)
Dim timeout As Int32 = args(2)
Dim StWatch As Stopwatch = args(3)
Dim keyslisted As List(Of Keys) = args(4)


If StWatch.ElapsedMilliseconds >= timeout And Not timeout = 0 Then keyslisted.Clear() : StWatch.Reset()
If keyslisted.Count < keysl.Count Then


For Each key As Keys In keysl


If GetAsyncKeyState(key) And Not keyslisted.Contains(key) Then


keyslisted.Add(key)
If keyslisted.Count = 1 Then StWatch.Start()
End If
Next
ElseIf keyslisted.Count = keysl.Count Then


_keyspresscallback.Invoke(keyslisted)
keyslisted.Clear()


If oncepress Then


For i = 0 To keysl.Count - 1


If GetAsyncKeyState(keysl(i)) Then i = 0 : keyslisted.Clear() : StWatch.Reset()
Next
End If


StWatch.Reset()
End If
End Sub
End Class


حاصلش شد کد بالا. گفتم دوستان بی بهره نمانند...(البته استاید دیگه جسارت رو ببخشید. باید از شما بهره برد...)
طریقه استفاده اش هم که کاملا واضح (و بسی ضایع) است وبه نظر نمیاد مشکل خاصی باشه!

در جهت رفع ابهام :
کافیه در ابتدا یه کلاس به پروژه اظافه کنید و اینا رو کپی کنید.
حالا هر جا که دوست دارید یه نمونه از کلاس تعریف کنید و کلید ها رو هم زمان یا بعدا بهش بدید :

Dim gks As New ClsGKS({Keys.ControlKey, Keys.ShiftKey, Keys.D, Keys.D0})

توجه کنید که میتونید هر چقدر کلید دوست دارین تعریف کنید ولی به نظرم از چهار تا بیشتر اذیت کردنه!

حالا یه ساب تعریف کنید که وقتی کلید ها فشرده شدن کد دلخواه شما رو اجرا کنه.(توجه کنید این ساب با یه ترد دیگه اجرا میشه پس هواستون به Invoke کردن باشه!) :

Private Sub pressed()

If Me.InvokeRequired Then

Me.Invoke(New MethodInvoker(AddressOf pressed))
Else

Me.Show()
Me.Focus()
End If
End Sub

و در آخر هم هندل این ساب رو بدین دست کلاس :

AddHandler gks.Pressed, AddressOf pressed

رسیدیم سر اصل مطلب اینجا شما ساب کپچر رو صدا میکنید .
این ساب سه تا ارگامنت داره که آشنایید با هاشون (نیستید هم میشید!)
1. timeout : مدت زمانی که میخواید کاربر بعد از فشردن اولین کلید وقت داشته باشه تا بقیه رو وارد کنه که عادیش صفر هست یعنی فرقی نمیکنه تو چه فاصله زمانی باشه.
2.redo : اگه true باشه تشیخص دوباره هم اتفاق میفته یعنی فقط برای اولین بار کلید ها کار میکنن اگه false باشه.
3.oncepress: این هم اگر true باشه کاربر تا وقتی دستش رو اون کلید هاست فقط یک بار کار میکنن یعنی اگر کلید های ترکیبی رو نگه داره و تشیخص داده بشن باید کلید هارو رها کنه واسه دفعی بعد ,که تنها وقتی redo=true باشه کار میکنه.اگه هم false باشه که تا وقتی کاربر دستش رو کلید هاست اون سابی که تعریف کردین مدام اجرا میشه.
(4.) توی اون یه نمور تغییر یه checktime اظافه شده که فاصله زمانی چک کردن کلید هاست مث یه تایمر(البته خود تایمره!) :

gks.StartCapture(3000)

bagion
دوشنبه 30 اردیبهشت 1392, 19:03 عصر
سلام دوست عزیز
لطف میکنی روش استفادشو برای تازه کارا بزاری؟
ممنون

Saman_12
چهارشنبه 01 خرداد 1392, 11:16 صبح
مث اینکه همه بلد بودن و بدرد کسی نخورد:افسرده:.