November 28, 2020, 11:08:27 AM

Author Topic: [bmx] automax.mod by plash [ 1+ years ago ]  (Read 1252 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] automax.mod by plash [ 1+ years ago ]
« on: June 29, 2017, 12:28:43 AM »
Title : automax.mod
Author : plash
Posted : 1+ years ago

Description : Updated 4/27/08 2:47PM EST

Contains functions for grabbing pixels from the screen, global hotkeys (can be detected outside of program), setting windows always on-top, pressing keys and mouse buttons/movements virtually.

Zip (v0.21): http://files.filefront.com/automax+v0+21zip/;10090541;/fileinfo.html


Code :
Code: BlitzMax
  1. 'It consists of multiple files, they will be posted in the
  2. 'comments or you can download them from the link above.


Comments :


plash(Posted 1+ years ago)

 Module interface is 'psh.modautomax.mod'.automax.bmx
Code: [Select]
SuperStrict

Import BRL.linkedlist
Import maxgui.Win32MaxGui 'users of the old maxgui can recompile the mod with BRL.Win32MaxGui

Rem
bbdoc: AutoMax
about: Extended Win32 (only) features module
End Rem
Module psh.automax

ModuleInfo "Version: 0.21"
ModuleInfo "Author: Tim Howard"

ModuleInfo "History: v0.21"
ModuleInfo "History: Improved documentation"
ModuleInfo "History: Changed THHotkey type to TGHotkey, changed to be more OO"
ModuleInfo "History: Fixed module for newer maxgui"
ModuleInfo "History: Added extern 'GetDC'"

ModuleInfo "History: v0.1"
ModuleInfo "History: Initial release, basic functionality"


Include "incVInput.bmx"
Include "incGHotkey.bmx"

Include "inc opmost.bmx"

Include "incgetpixel.bmx"

incgetpixel.bmx
Code: [Select]
Extern "Win32"
Function apiGetPixel:Int(hdc:Int, X:Int, Y:Int) = "GetPixel@12"
Function GetDC:Int(hWnd:Int)

End Extern

Private
Global HDC_DESKTOP:Int = GetDC(0)

Rem example
Local p:Int = dGetPixel(931, 709), r:Int, g:Int, b:Int
ApiRGB(p, r, g, b)

DebugLog p + "|" + r + ", " + g + ", " + b

p = PrepRGB(r, g, b)

DebugLog p + "|" + r + ", " + g + ", " + b
EndRem

Public
Rem
bbdoc: GetPixel Function
about: Gets the color of a pixel on the screen.
returns: A single integer value containing R, G and B color values. See #ApiRGB
EndRem
Function GetPixel:Int(X:Int, Y:Int)
  Return apiGetPixel(HDC_DESKTOP, X, Y)
 
End Function

Rem 'Removed silly function
Function CompareColors:Int(Col1:Int, Col2:Int)
If Col1 = Col2 Then Return 1 Else Return 0
End Function
EndRem

Rem
bbdoc: PrepRGB Function
about: Creates an APIRGB color variable and returns it.
returns: A single integer value containing R, G and B color values. See #ApiRGB
EndRem
Function PrepRGB:Int(Red:Int, Green:Int, Blue:Int)
   Return (RED | GREEN Shl 8 | BLUE Shl 16)

End Function

Rem
bbdoc: ApiRGB Function
about: Takes in a single integer value, and sets individual RGB variables (from functions #PrepRGB and #GetPixel)
returns: Nothing, sets values Red, Green and Blue
EndRem
Function ApiRGB(Pixel:Int, Red:Int Var, Green:Int Var, Blue:Int Var)
Red = (Pixel Shr 0) & 255
Green = (Pixel Shr  8) & 255
Blue = (Pixel Shr 16) & 255

End Function
incGHotkey.bmx
Code: [Select]
Extern "Win32"
Function GetAsyncKeyState:Int(vKey:Int)

EndExtern

Rem
bbdoc: TGHotkey Type
End Rem
Type TGHotkey
  Global _list:TList = New TList
 
Rem
bbdoc: Shift modifier
End Rem
Field m_shift:Int

Rem
bbdoc: Ctrl modifier
End Rem
Field m_ctrl:Int

Rem
bbdoc: Alt modifier
End Rem
Field m_alt:Int

Rem
bbdoc: Key to be checked
End Rem
Field key:Int

Rem
bbdoc: Internal
End Rem
Field khit:Int

Rem
bbdoc: Function to be called when hotkey (& modifiers) pressed
End Rem
Field _callback(Obj:TGHotkey)

Method New()
  _list.AddLast(Self)

End Method

Method remove()
  _list.remove(Self)

End Method

Rem
bbdoc: CheckHotkeys Function
about: Checks all global hotkeys, if key pressed executes callback function
End Rem
Function CheckHotkeys()
 Local th:TGHotkey
 
For th = EachIn TGHotkey._list

 Local GKD_CTRL:Int = GKeyDown(VK_CONTROL)
 Local GKD_MENU:Int = GKeyDown(VK_MENU)
 Local GKD_SHIFT:Int = GKeyDown(VK_SHIFT)

 Local totkeys:Int = 1

totkeys:+th.m_shift + th.m_ctrl + th.m_alt

 Local Keys:Int = GKeyDown(th.key)
If th.m_shift = 1 Then Keys:+GKD_SHIFT
If th.m_ctrl = 1 Then Keys:+GKD_CTRL
If th.m_alt = 1 Then Keys:+GKD_MENU

'DebugLog keys

If keys = totkeys
'DebugLog keys + ", " + th.khit
If th.khit = 0
 th.khit = 1
th._callback(th)

EndIf

Else
 th.khit = 0

EndIf
Next

End Function

Rem
bbdoc: CreateHotkey Function- Internal, see #CreateGlobalHotkey
about: @m_shift @m_ctrl and @m_alt are boolean variables to specify the modifiers for the key, @key is any KEY_ variable.
returns: The new hotkey
End Rem
Function Create:TGHotkey(key:Int, m_shift:Int, m_ctrl:Int, m_alt:Int, callback(Obj:TGHotkey))
 Local th:TGHotkey = New TGHotkey

th.key = key
th.m_shift = m_shift
th.m_ctrl = m_ctrl
th.m_alt = m_alt
th._callback = callback

  Return th
 
End Function

End Type

Rem
bbdoc: CreateGlobalHotkey Function
about: @m_shift @m_ctrl and @m_alt are boolean variables to specify the modifiers for the key
returns: The new hotkey
End Rem
Function CreateGlobalHotkey:TGHotkey(key:Int, m_shift:Int, m_ctrl:Int, m_alt:Int, callback(Obj:TGHotkey))
   Return TGHotkey.Create(key, m_shift, m_ctrl, m_alt, callback)

End Function

Rem
bbdoc: GKeyDown Function
returns: The state of the virtual key sent to the function.
End Rem
Function GKeyDown:Int(VirtualKey:Int)
 'If (IgnoreFocus = True) And (GetActiveWindow() = 0) Then Return
 
   Return (GetAsyncKeyState:Int(VirtualKey) And %1000000000000000) > 0

End Function
inc   opmost.bmx
Code: [Select]
Extern "win32"
Function SetWindowPos:Int(hWnd:Int, hAfter:Int, X:Int, Y:Int, cx:Int, cy:Int, flags:Int)

End Extern

Private
Global HWND_TOPMOST:Int = -1

Rem example
Wnd_Main:TGadget = CreateWindow("A WINDOW", 0, 0, 800, 600, Desktop(), WINDOW_TOOL)

SetWindowPos QueryGadget(Wnd_Main, QUERY_HWND), HWND_TOPMOST, 0, 0, 800, 600, 0
End Rem

Public

Rem
bbdoc: SetWindowTopMost Function
about: Sets the window to always on top.
returns: nothing
EndRem
Function SetWindowTopMost(Gadget:TGadget)

SetWindowPos QueryGadget(Gadget, QUERY_HWND), HWND_TOPMOST, GadgetX(Gadget), GadgetY(Gadget), GadgetWidth(Gadget), GadgetHeight(Gadget), 0

End Function
incVInput.bmx
Code: [Select]
'SuperStrict

'#Region Mouse Variables
Const MOUSEEVENTF_ABSOLUTE:Int   = -32768 ' // Use absolute coords
Const MOUSEEVENTF_MOVE:Int       = 1      ' // Trigger move event

Const MOUSEEVENTF_LEFTDOWN:Int   = 2      ' // LMB Down
Const MOUSEEVENTF_LEFTUP:Int     = 4      ' // LMB Up
Const MOUSEEVENTF_RIGHTDOWN:Int  = 8      ' // RMB Down
Const MOUSEEVENTF_RIGHTUP:Int    = 16     ' // RMB Up
Const MOUSEEVENTF_MIDDLEDOWN:Int = 32     ' // MMB Down
Const MOUSEEVENTF_MIDDLEUP:Int   = 64     ' // MMB Up
Const MOUSEEVENTF_WHEEL:Int      = 128    ' // NT Only: Mouse wheel moved
'#End Region


'#Region Virtual Keys

Const VK_ADD:Byte = $6B
Const VK_ATTN:Byte = $F6
Const VK_BACK:Byte = $8
Const VK_CANCEL:Byte = $3
Const VK_CAPITAL:Byte = $14
Const VK_CLEAR:Byte = $C
Const VK_CONTROL_:Byte = $11
Const VK_CRSEL:Byte = $F7
Const VK_DECIMAL:Byte = $6E
Const VK_DELETE:Byte = $2E
Const VK_DIVIDE:Byte = $6F
Const VK_DOWN:Byte = $28
Const VK_END:Byte = $23
Const VK_EREOF:Byte = $F9
Const VK_ESCAPE:Byte = $1B
Const VK_EXECUTE:Byte = $2B
Const VK_EXSEL:Byte = $F8

Const VK_HELP:Byte = $2F
Const VK_HOME:Byte = $24
Const VK_INSERT:Byte = $2D
Const VK_LBUTTON:Byte = $1
Const VK_LCONTROL:Byte = $A2
Const VK_LEFT:Byte = $25
Const VK_LMENU:Byte = $A4
Const VK_LSHIFT:Byte = $A0
Const VK_MBUTTON:Byte = $4
Const VK_MENU:Byte = $12
Const VK_MULTIPLY:Byte = $6A
Const VK_NEXT:Byte = $22
Const VK_NONAME:Byte = $FC

Const VK_NUMLOCK:Byte = $90
Const VK_NUMPAD0:Byte = $60
Const VK_NUMPAD1:Byte = $61
Const VK_NUMPAD2:Byte = $62
Const VK_NUMPAD3:Byte = $63
Const VK_NUMPAD4:Byte = $64
Const VK_NUMPAD5:Byte = $65
Const VK_NUMPAD6:Byte = $66
Const VK_NUMPAD7:Byte = $67
Const VK_NUMPAD8:Byte = $68
Const VK_NUMPAD9:Byte = $69

Const VK_OEM_CLEAR:Byte = $FE
Const VK_PA1:Byte = $FD
Const VK_PAUSE:Byte = $13
Const VK_PLAY:Byte = $FA
Const VK_PRINT:Byte = $2A
Const VK_PRIOR:Byte = $21
Const VK_PROCESSKEY:Byte = $E5
Const VK_RBUTTON:Byte = $2
Const VK_RCONTROL:Byte = $A3
Const VK_RETURN:Byte = $D
Const VK_RIGHT:Byte = $27
Const VK_RMENU:Byte = $A5
Const VK_RSHIFT:Byte = $A1
Const VK_SCROLL:Byte = $91
Const VK_SELECT:Byte = $29
Const VK_SEPARATOR:Byte = $6C
Const VK_SHIFT:Byte = $10
Const VK_SNAPSHOT:Byte = $2C
Const VK_SPACE:Byte = $20
Const VK_SUBTRACT:Byte = $6D
Const VK_TAB:Byte = $9
Const VK_UP:Byte = $26
Const VK_ZOOM:Byte = $FB

'Const KEYEVENTF_KEYUP:Byte = $00000002
'#End Region

Extern "win32"
Function GetCursorPos(Point:Byte Ptr)
Function SetCursorPos(x:Int, y:Int)

Function keybd_event(bVk:Byte, bScan:Byte, dwFlags:Byte, dwExtraInfo:Int)
Function mouse_event(dwFlags:Int, dx:Int, dy:Int, cButtons:Int, dwExtraInfo:Int)

End Extern

Rem
MouseAction MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, 0, 0, 0
MouseAction MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, 17, 702, 1
Delay 5000
MouseAction MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, 17, 702, 2
EndRem


Rem
'system_ "notepad.exe"
Delay 2000

FKeyStroke Key_A
FKeyStroke Key_B', 2000

SKeyStroke Key_C, 1
Delay 5000
SKeyStroke Key_C, 2
EndRem

'Example: MouseAction MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, 0, 0
Rem
bbdoc: Sends a mouse click to the computer.
about: @Flags can be any MOUSEEVENTF_ values or a combination (ie, MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP)
@X position to send mouse to
@Y position to send mouse to
@mm is a choice variable, 0=do not move mouse, 1=move mouse 2=move mouse, click, then return to previouse mouse position
returns: nothing
EndRem
Function MouseAction(Flags:Int, X:Int, Y:Int, mm:Int = 1)

Select mm
Case 0
mouse_event Flags:Int, 0, 0, 0, 0

Case 1
SetCursorPos X, Y
mouse_event Flags:Int, 0, 0, 0, 0

Case 2
 Local Point:Int[2]

GetCursorPos Point ; SetCursorPos X, Y
mouse_event Flags:Int, 0, 0, 0, 0
SetCursorPos Point[0], Point[1]

End Select

End Function


'Example: KeyStroke KEY_A
Rem
bbdoc: Sends a full keystroke to the computer.
about: @VK_KEYV key to be pressed, can be any VK_ variable
returns: nothing
EndRem
Function FKeyStroke(VK_KEYV:Byte)
keybd_event(VK_KEYV, 0, 0, 0)

'Delay dly

keybd_event(VK_KEYV, 0, 2, 0)

End Function

'Example: KeyStroke KEY_A, 0 ; KeyStroke KEY_A, 2
Rem
bbdoc: Sends a single keystroke to the computer.
about: @VK_KEYV: key to be pressed, can be any VK_ variable
@updn: 1=down 2=up
returns: nothing
EndRem
Function SKeyStroke(VK_KEYV:Byte, updn:Byte = 0)
keybd_event(VK_KEYV, 0, updn, 0)
End Function



TaskMaster(Posted 1+ years ago)

 Any plans to make it cross platform?


plash(Posted 1+ years ago)

 Examples:Grabbing Pixels
Code: [Select]
Import psh.automax

'Get a pixel and init rgb values.
Local p:Int = dGetPixel(2, 2), r:Int, g:Int, b:Int

'Send rgb values to function to be set from pixel single integer color.
ApiRGB(p, r, g, b)

DebugLog p + "|" + r + ", " + g + ", " + b

'Basically does the opposite of ApiRGB, puts it back into a single value,
'p should be exactly same as it was in the first place.
p = PrepRGB(r, g, b)

DebugLog p + "|" + r + ", " + g + ", " + b
Global Hotkeys
Code: [Select]
'Global hotkeys example, keys to test are Ctrl+Alt+O, Alt+Shift+B and Alt+Ctrl+Shift+Z
SuperStrict

Framework brl.eventqueue
Import brl.timer
Import psh.automax

Global testhotkey:TGHotkey = CreateGlobalHotkey(KEY_O, False, True, True, OnTestHotkeyPressed)
CreateGlobalHotkey(KEY_B, True, False, True, HKHandler)
CreateGlobalHotkey(KEY_Z, True, True, True, HKHandler)

Local Tmr_CheckKeys:TTimer = CreateTimer(60)
Repeat
Select WaitEvent()
Case EVENT_TIMERTICK
Select EventSource()
Case Tmr_CheckKeys
TGHotkey.CheckHotkeys()

End Select

End Select

Forever

Function HKHandler(th:TGHotkey)
  Local report:String = Chr(th.key)

If th.m_shift Then report:+ "+Shift"
If th.m_ctrl Then report:+ "+Ctrl"
If th.m_alt Then report:+ "+Alt"

   Print report + " Global Hotkey Pressed"

End Function


Function OnTestHotkeyPressed(th:TGHotkey)
Print "Test Hotkey Pressed!"

End Function
Virtual Input
Code: [Select]
Import psh.automax

'you should see 'abc' show up in the output tab if successful

'Execute full pressed/released key
FKeyStroke Key_A
FKeyStroke Key_B', 2000

'Send key_c pressed
SKeyStroke Key_C, 1
Delay 500
'Send key_c released
SKeyStroke Key_C, 2

'This should move the mouse to the middle of the screen and click there.
'If you just need to move the mouse see SetCursorPos(X:Int, Y:Int).
MouseAction MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, GadgetWidth(Desktop()) / 2, GadgetHeight(Desktop()) / 2
Topmost window
Code: [Select]
'Topmost window example
SuperStrict

Framework maxgui.win32maxgui
Import brl.eventqueue

Import psh.automax

Global Wnd_Main:TGadget = CreateWindow("Test Window", 400, 400, 300, 375, Null, WINDOW_TITLEBAR)
SetWindowTopMost Wnd_Main

Repeat
Select WaitEvent()
Case EVENT_WINDOWCLOSE
Select EventSource()
Case Wnd_Main
End

End Select

End Select

Forever



plash(Posted 1+ years ago)

 <div class="quote"> Any plans to make it cross platform?  </div>I can play around with it on Linux once the other issues I'm having are resolved. I don't own a mac so no luck there, unless someone else wants to take a whack at it! :)


xlsior(Posted 1+ years ago)

 <div class="quote"> Compile Error: Identifier 'GetDC' not found   </div>??


xlsior(Posted 1+ years ago)

 Hm... I couldn't get the module to compile unless I added the following to the automax.bmx file, per framework assistant's suggestion:<div class="quote"> Import Pub.Win32 </div>Then it compiled OK, but I am still unable to run your samples...  for example, the hotkey sample gives me the following error when trying to run:<div class="quote"> Unhandled Exception: Attempt to access field or method of Null object </div>I must be missing something, but your module + samples don't appear to work at all out of the box...


plash(Posted 1+ years ago)

 Do it in debug, what line is causing the error?I'll flip over to my winxp machine, remove the mod and try the code from this page.


plash(Posted 1+ years ago)

 Yup, works fine here, copied code from page without any modifications. (bmax 1.28)


xlsior(Posted 1+ years ago)

 OK, got it to work.Turns out that there were two issues, when using the latest MaxGUI version.1) It's missing the declaration of the win32 function GetDC().I needed to either import Pub.win32 in automax.bmx, or add the following:
Code: [Select]
Extern "Win32"
Function GetDC( hWnd )
End Extern
Looks like that one might have been linked by the older MaxGUI, but not any more. furthermore, the GUI code was generating an error in your sample:<div class="quote"> "Unhandled Exception: Attempt to access field or methof of Null object" </div>on the following line:<div class="quote"> Global Wnd_Main:TGadget = CreateWindow("", 75, 75, 260, 340, Desktop(), WINDOW_TITLEBAR) </div>That one went away after I changed the import line in the sample file to either one of these:Import MaxGUI.Win32MaxGUI orImport MaxGUI.Win32MaxGUIexinstead of MaxGui.MaxGuiSo... It seems to be working now, both in the latest MaxGUI SVN as with your original code in an older 1.28 backup copy of Blitzmax that I still had laying around.so, I do have some other question and observation:- Is it possible to capture any non-alphanumerical keys with your 'keylogger' routine?  I don't really care about keyloggers per-se, but am interested in global shortcuts. Specifically, it it possible to see control/alt/shift modifiers, and things like the cursor keys?I did notice that the 'keylogger' doesn't capture all keystrokes, and receives data out of order, especially if you type moderately fast. (Core 2 Duo, @2.4 Ghz)For example:"The Quick fox jumped over the lazy old dog" got logged as "HTEQCIUKFOXJUEMPDOEVHTLAZYLODDGO"


SebHoll(Posted 1+ years ago)

 <div class="quote"> That one went away after I changed the import line in the sample file to either one of these:Import MaxGUI.Win32MaxGUI orImport MaxGUI.Win32MaxGUIexinstead of MaxGui.MaxGui </div>Just thought I'd point out that for MaxGUI programs to compile with the new namespace, you need to Import at least one compatible driver for your platform.MaxGUI.MaxGUI - this simply provides functions and a framework for the platform specific drivers to override and handle. Importing this by itself won't actually mean any gadget is created.MaxGUI.Drivers - this is a new module which will selectively Import the platform's official MaxGUI driver. This should be the only Import you require to get MaxGUI working.MaxGUI.Win32MaxGUI, MaxGUI.Win32MaxGUIEx, MaxGUI.CocoaMaxGUI, MaxGUI.FLTKMaxGUI - these are the official MaxGUI drivers that actually undertake the creation and handling of gadgets for the corresponding GUI framework. Although you can Import these directly, MaxGUI.Drivers does all this for you, so you should just use that.<div class="quote"> I did notice that the 'keylogger' doesn't capture all keystrokes, and receives data out of order, especially if you type moderately fast. (Core 2 Duo, @2.4 Ghz)"The Quick fox jumped over the lazy old dog" got logged as "HTEQCIUKFOXJUEMPDOEVHTLAZYLODDGO"  </div>Try increasing the frequency of the timer to 20/50 Hz, e.g.
Code: [Select]
Local ticktime:TTimer = CreateTimer(4)...to...
Code: [Select]
Local ticktime:TTimer = CreateTimer(20)If you look at the way it outputs keystrokes, it should become clear why it is doing that. ;-)


plash(Posted 1+ years ago)

 Honest mistake, I never used the newer maxgui module on my win32 machine.It is possible to do global hotkeys - thats the reason I wrote it. You can create hotkeys using the THHotkey type and use, or write your own, CheckHotkeys() function.The modi variables in the THHotkey type are for detecting key modifiers.
Code: [Select]
'modi1=Shift modi2=Ctrl modi3=Alt
Field modi1:Int, modi2:Int, modi3:Int
I will post an example using global hotkeys, include the fixes for maxgui.maxgui and make things more clear with THHotkey (ie. changing the modi vars to m_shift, m_ctrl, m_alt etc), including more object oriented and documented code. Soon.


plash(Posted 1+ years ago)

 Done. See the examples post for a Global Hotkeys Example.Changes:
Code: [Select]
Improved documentation
Changed THHotkey type to TGHotkey, changed to be more OO
Fixed module for newer maxgui
Added extern 'GetDC'



xlsior(Posted 1+ years ago)

 Excellent!Very nice.


SebHoll(Posted 1+ years ago)

 Global hotkeys? Can you not just use SetHotKeyEvent()?


xlsior(Posted 1+ years ago)

 <div class="quote"> Global hotkeys? Can you not just use SetHotKeyEvent()?  </div>Plash's Global Hotkeys work when the blitz application does not have focus -- does SetHotKeyEvent() does that at well?(This is one of those cases where the Blitz user manual could really, really use some more info and/or examples)


plash(Posted 1+ years ago)

 There is another solution that will work over multiple virtual desktops, if you know my program dapp ( <a href="../Community/posts71c4.html?topic=77865" target="_blank">http://www.blitzbasic.com/Community/posts.php?topic=77865[/url] ) that should make sense..<a href="http://msdn.microsoft.com/en-us/library/ms646309.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms646309.aspx[/url]Its literally just a simple
Code: [Select]
RegisterHotKey(hWnd, _ID, MODKEY, KEY)but it blocks any other application from using the same hotkey. [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal