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 lukemisen
Kysymys 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 Sub
Heippa 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 Sub
EDIT:
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 Sub
Hei, teepä tuosta koodivinkki! En minä tarvitse, mutta joillekin saattaisi olla hyödyllinen!
Aihe on jo aika vanha, joten et voi enää vastata siihen.