Moi =)
tässä osoitteessa on esimerkki, kuinka voidaan tehdä moniajoa.
https://www.ohjelmointiputka.net/koodivinkit/
' sisäisen koodin hallinta
Case TICK_INTERNAL
' tänne voi kirjoittaa esim.:
' - ammusten ja pelaajien liikuttelun
' - törmäysten tunnistamisen
' - näppäimistön ja hiiren lukemisenKysymys kuuluukin, kuinka hiiri- ja näppäimistöä luetaan ilman normaaleja MouseClick yms.
' nämä kutsut ovat parempaa DoEventsin hallintaa varten ' mitä sitä turhaan hidasta DoEventsiä kutsumaan, jos sille ei ole tarvetta... Public Const QS_KEY = &H1& Public Const QS_MOUSEMOVE = &H2& Public Const QS_MOUSEBUTTON = &H4& Public Const QS_POSTMESSAGE = &H8& Public Const QS_TIMER = &H10& Public Const QS_PAINT = &H20& Public Const QS_SENDMESSAGE = &H40& Public Const QS_HOTKEY = &H80& Public Const QS_ALLINPUT = (QS_SENDMESSAGE Or QS_PAINT Or QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON Or QS_MOUSEMOVE Or QS_HOTKEY Or QS_KEY) Public Const QS_MOUSE = (QS_MOUSEMOVE Or QS_MOUSEBUTTON) Public Const QS_INPUT = (QS_MOUSE Or QS_KEY) Public Const QS_ALLEVENTS = (QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY) Public Declare Function GetQueueStatus Lib "user32" (ByVal qsFlags As Long) As Long
Tässä mainitaan mahdollisuudesta käyttää GetQueueStatus yms API-kutsuja.
Kuinka tämä siis toimii käytännössä?
Ja hyvää talvilomaa =)
Moikka JoreSoft!
esim. näin "hiiri- ja näppäimistöä luetaan ilman normaaleja MouseClick yms."
(täysin ilman DoEvents-funktion apua ei kyllä pitkälle pärjää...)
Lisää vielä moduuliin...(jos ei jo ole...)
Public Type POINT_API x As Long y As Long End Type Public Declare Function GetCursorPos Lib "user32.dll" ( _ lpPoint As POINT_API) As Long
'formille: labelli
Private Sub Form_Paint()
MainLuuppi
End Sub
Sub MainLuuppi()
Dim koordinaatti As POINT_API
Dim sijainti As Long
Do: DoEvents
If GetQueueStatus(QS_ALLINPUT) Then
Label1.Caption = GetQueueStatus(QS_ALLINPUT)
sijainti = GetCursorPos(koordinaatti)
If Label1.Caption = 262144 And _
koordinaatti.x * Screen.TwipsPerPixelX > _
Me.Left + Me.Label1.Left And _
koordinaatti.x * Screen.TwipsPerPixelX < _
Me.Left + Me.Label1.Left + Me.Label1.Width And _
koordinaatti.y * Screen.TwipsPerPixelY > _
Me.Top + Me.Label1.Top + Me.Label1.Height And _
koordinaatti.y * Screen.TwipsPerPixelY < _
Me.Top + Me.Label1.Top + (Me.Label1.Height * 2) _
Then Exit Do
'koordinaattien suhde laatikkoon on metsikössä,
'jutska olis skaalattava SYSTEM_METRICS muotoon...
'(mutta riittää testaamiseen , en jaksa vääntää)
End If
Loop: End
End SubHeippa taas!
oheinen esimerkki soveltuu ehkä paremmin testaamiseen...
'formille pari labellia...
Private Sub Form_Activate()
MainLuuppi
End Sub
Sub MainLuuppi()
Dim koordinaatti As POINT_API
Dim sijainti As Long
Do: DoEvents
If GetQueueStatus(QS_ALLINPUT) Then
Label1.Caption = GetQueueStatus(QS_ALLINPUT)
sijainti = GetCursorPos(koordinaatti)
If Label1.Caption = 262144 Then
Dim ctl As Control
For Each ctl In Me.Controls
'BorderStyle 2 - Sizable
'formin reunuksen leveys = 50
'formin otsikkopalkin korkeus = 475
'2540 / 1440 = n. 1.76
If CLng(koordinaatti.x / 1.76) >= _
CLng((Me.Left + 50 + ctl.Left) / 1.76 / _
Screen.TwipsPerPixelX) And _
CLng(koordinaatti.x / 1.76) <= _
CLng((Me.Left + 50 + ctl.Left + ctl.Width) / _
1.76 / Screen.TwipsPerPixelX) And _
CLng(koordinaatti.y / 1.76) >= _
CLng((Me.Top + 475 + ctl.Top) / 1.76 / _
Screen.TwipsPerPixelY) And _
CLng(koordinaatti.y / 1.76) <= _
CLng((Me.Top + 475 + ctl.Top + ctl.Height) / _
1.76 / Screen.TwipsPerPixelY) Then
Label2.Caption = ctl.Name
End If
Next
End If
End If
Loop
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
End
End SubEDIT:
BorderStyle 2
formin reunuksen leveys = 4px
reunuksen leveys = 4 * Screen.TwipsPerPixelX
jos Screen.TwipsPerPixelX = 15 on leveys 4 * 15 = 60 Twips
formin otsikkopalkin korkeus = 32px
palkin korkeus = 32 * Screen.TwipsPerPixelY
jos Screen.TwipsPerPixelY = 15 on korkeus 32 * 15 = 480 Twips
Heippa taas!
VBA-ohjelmoijille erikseen...
'luokkamoduuliin... '(Class1) Private Declare Function GetDC Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32" _ (ByVal hdc As Long, ByVal nIndex As Long) As Long Private Declare Function ReleaseDC Lib "user32" _ (ByVal hwnd As Long, ByVal hdc As Long) As Long Private Const LOGPIXELSX = 88 Private Const LOGPIXELSY = 90 Public Property Get TwipsPerPixelX() As Integer Dim nDC As Long: nDC = GetDC(0) TwipsPerPixelX = 1440 / GetDeviceCaps(nDC, LOGPIXELSX) ReleaseDC 0, nDC End Property Public Property Get TwipsPerPixelY() As Integer Dim nDC As Long: nDC = GetDC(0) TwipsPerPixelY = 1440 / GetDeviceCaps(nDC, LOGPIXELSY) ReleaseDC 0, nDC End Property 'formin General-osioon... Private c1 As New Class1, _ TwipsPerPixelX As Integer, _ TwipsPerPixelY As Integer 'käyttö... Private Sub UserForm_Activate() TwipsPerPixelX = c1.TwipsPerPixelX TwipsPerPixelY = c1.TwipsPerPixelY End Sub
Heippa taas!
Kun nyt kerran lipsahti VBA-puolelle niin...mitäs jos rakennettaisiin VB6:lla aivan ikioma Screen-objekti VBE:a varten...Elikä tehdään VB6:lla ActiveX DLL...
Ekakas annetaan Project:lle nimeksi VBAScreen ja nimetään luokkamoduuli nimellä Screen ...
luokkamuduuliin:
Private Declare Function GetDC Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32" _ (ByVal hdc As Long, ByVal nIndex As Long) As Long Private Declare Function ReleaseDC Lib "user32" _ (ByVal hwnd As Long, ByVal hdc As Long) As Long Private Declare Function GetSystemMetrics32 Lib "user32" _ Alias "GetSystemMetrics" (ByVal nIndex As Long) As Long Private Const LOGPIXELSX = 88 Private Const LOGPIXELSY = 90 Private Const SM_CXSCREEN = 0 Private Const SM_CYSCREEN = 1 Public Property Get TwipsPerPixelX() As Integer Dim nDC As Long: nDC = GetDC(0) TwipsPerPixelX = 1440 / GetDeviceCaps(nDC, LOGPIXELSX) ReleaseDC 0, nDC End Property Public Property Get TwipsPerPixelY() As Integer Dim nDC As Long: nDC = GetDC(0) TwipsPerPixelY = 1440 / GetDeviceCaps(nDC, LOGPIXELSY) ReleaseDC 0, nDC End Property Public Property Get Width() As String Width = GetSystemMetrics32(SM_CXSCREEN) End Property Public Property Get Height() As String Height = GetSystemMetrics32(SM_CYSCREEN) End Property
...valitaan File valikosta Make_VBAScreen.dll, tallennetaan Windows\System32 -hakemistoon ja suljetaan VB6. Klikataan: Käynnistä - Suorita - kirjoitetaan laatikkoon: regsvr32 C:\windows\system32\VBAScreen.dll ja klikataan OK
Avataan Excel - VBE - valitaan Tools-valikosta References, ruksataan laatikosta VBAScreen, klikataan OK ja lisätään projektiin lomake (UserForm)
'lomakkeen General-osioon: Public Screen As Object Private Sub UserForm_Activate() Set Screen = New VBAScreen.Screen End Sub 'käyttö esim. Private Sub UserForm_Click() MsgBox "Näyttöresoluutio: " & Screen.Width _ & " x " & Screen.Height & vbCrlf _ & "TwipsPerPixelX = " & Screen.TwipsPerPixelX _ & " TwipsPerPixelY = " & Screen.TwipsPerPixelX End Sub Private Sub UserForm_QueryClose( _ Cancel As Integer, CloseMode As Integer) Set Screen = Nothing End Sub
ThisWorkbook:
Private Sub Workbook_SheetBeforeDoubleClick( _
ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
If Not UserForm1.Visible Then
UserForm1.Show: SendKeys "{ESC}"
End If
End SubHei, teepä tuosta koodivinkki! En minä tarvitse, mutta joillekin saattaisi olla hyödyllinen!
Aihe on jo aika vanha, joten et voi enää vastata siihen.