win32api and getting hotkeys problem? ideas? soja, james, tracer?

Blitz3D Forums/Blitz3D Programming/win32api and getting hotkeys problem? ideas? soja, james, tracer?

Mike Yurgalavage(Posted 2004) [#1]
the previous coding with win32api where we accessed another program's data addresses (memory) worked like a charm. thanks to those who helped me learn the process and get to the successful conclusion. currently i am trying to find a way with blitz3d that i can monitor "hotkeys". specifically, i want to be able to have the blitz program detect when certain keys (or key combinations) are being pressed, even if i a am in another window or other program. for instance, with the trainers i hope to create, i want to be able to be playing the game and then press a certain key on the keyboard which will activate the trainer or features of the trainer. of course the trainer is the blitz3d program which is also running at the same time. i dont think that the normal blitz3d commands will let me do it this way. i am assuming that win32api calls will be needed again (perhaps the getasynchkeystate and a timer event or something or another that ensures blitz3d is working and checking things even in the background?) anyways, looking for ideas and of course code is always welcome, especially if it involves win32api calls which i am still learning. i hope someone can help!

best,
mike


soja(Posted 2004) [#2]
Hi Mike,

Yes as far as I know you would normally use the WinAPI by calling SetWindowsHookEx (User32.dll), but it requires a callback function, and since Blitz doesn't have function pointers, you can't specify a callback function, so you can't use it. =(

So essentially you'd have to write your own DLL wrapper (in another language) for SetWindowsHookEx (and all the other Keyboard/Mouse Hook functions you wanted) which you could call with Blitz. Or, you could find one that someone else wrote, perhaps. I remember seeing a file called "nhook.dll" in one of the programs I use which I assume was something like this (I examined the exported functions), but I can't remember what program that came from, and whether it was freely distributable, etc.

Perhaps someone else knows some other tips.


Mike Yurgalavage(Posted 2004) [#3]
soja, thanks for the reply. i am curious if this type of thing would be easy to do and would work with blitzplus (instead of blitz3d)? also are there any others reading this thread with ideas or with info to the .dll soja mentioned?

best,
mike


soja(Posted 2004) [#4]
BlitzPlus has a built-in hotkey event handler, but it only works when the program is active, so you're in the same boat there.

I looked around and found this article:
The Code Project - KeyBoard Hooks
There a whole section of articles to read on hooks. This particular one is about creating a DLL in C for hooking the keyboard.

You might also check this out:
NASM Keyboard hook DLL example
I've never used NASM, but if I remember right, it's a free assembler. I figure with minimal fuss you could probably replace the MessageBox function (from within HookProc:) with SendMessage, so that everytim a key is pressed on the keyboard, it sends a message to your Blitz program.


Difference(Posted 2004) [#5]
There are/where examples on this forum to set a keyboard hook.

http://www.google.com/search?q=keyboard+hook+site%3Awww.blitzbasic.com&ie=UTF-8&oe=UTF-8&hl=da&btnG=Google-s%C3%B8gning&meta=

In the code archives: http://www.blitzbasic.com/codearcs/codearcs.php?code=366


Mike Yurgalavage(Posted 2004) [#6]
peter i have looked and didn't see any examples for that using those links. i am hoping that someone reading this can provide an example or maybe point me to where some example code would be. i have very little win32api experience and even less c++ experience so i don't see me writing my own dll.... there's got to be a way to do this!
also, if tracer or anyone with purebasic is reading this, i am curious if purebasic can do this sort of thing?

lastly, i found this link about hooks. anyone know how to do these hooks with blitz3d?

http://help.madshi.net/madCodeHook.htm

thanks,
mike


Difference(Posted 2004) [#7]
Sorry, you are right. That code archive entry is not what I thought it was, and the keyboard hook functions seems to have been deleted from this forum.

This is what I've done (following a tip in these forums) to install a keyboard hook, to use normal windows controls in a Blitz3D window.

In the KeyboardHookProc, I guess you could put your code, to get custom keypresses. You have to add the code to copy to the bank passed.

Powerbasic dll:

#Compile Dll "C:\blitz3d\userlibs\bbhook.dll"


#Include "WIN32API.INC"

Global gKBHook As Long


Function LibMain(ByVal hInstance As Long, _
                 ByVal Reason    As Long, _
                 ByVal Reserved  As Long) _
                 Export As Long

  Select Case Reason
    Case %DLL_PROCESS_ATTACH
      LibMain = 1
      Exit Function
    Case %DLL_PROCESS_DETACH
      Exit Function
    Case %DLL_THREAD_ATTACH
      Exit Function
    Case %DLL_THREAD_DETACH
'
      Exit Function
  End Select

  LibMain = 0   'failure!
End Function

Function KeyboardHookProc(ByVal code As Long,ByVal wParam As Dword ,lParam As tagmsg) As  Dword
    'Static Msg As tagMsg

    If code<0 Then
           Function= CallNextHookEx(gKBHook,code,wParam,lParam)
           Exit Function
    Else


       '    Call getMessage( lParam, %NULL, 0, 0 ) '= %FALSE 'Then
        If lParam.message=%WM_KEYDOWN Then

        TranslateMessage lParam
        DispatchMessage lParam

        End If


    End If

End Function

Function hook  Alias "hook" (bank1 As Dword) Export As Long
     MsgBox "Hooked " & Str$(gKBHook)
    gKBHook=SetWindowsHookEx(%WH_GETMESSAGE,CodePtr(KeyboardHookProc),0,GetCurrentThreadID())

End Function

Function unhook  Alias "unhook" (bank1 As Dword) Export As Long
    UnhookWindowsHookEx gKBHook
    MsgBox "unhooked"
End Function


Blitz hookdll userlib:

.lib "bbhook.dll"
 
hook%(bank*):"hook" 
unhook%(bank*):"unhook"



Blitz3D code and User32.decls:

;-User32.decls Begin -------------------------------------------------------

;.lib "User32.dll"


;User32_CreateWindowEx%(dwExStyle,lpClassName$,lpWindowName$,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam):"CreateWindowExA"

;User32_GetWindowLong%(hWnd,nIndex):"GetWindowLongA"

;User32_SetWindowLong%(hWnd,nIndex,dwNewLong):"SetWindowLongA"

;User32_FindWindow%(lpClassName$,lpWindowName$):"FindWindowA"


;-User32.decls End -------------------------------------------------------


Const WS_CHILD = $40000000
Const WS_MINIMIZE = $20000000
Const WS_VISIBLE = $10000000
Const WS_CLIPCHILDREN = $2000000
Const WS_BORDER = $800000
Const WS_TABSTOP = $10000
Const GWL_STYLE = -16
Const WS_EX_CLIENTEDGE = $200
Const WS_EX_LEFT = $00000000
Const ES_LEFT = 0
Const ES_CENTER = 1
Const ES_RIGHT = 2
Graphics3D 800,600,0,2

title$="My title"


AppTitle title$


; find blitz window handle

bbHwnd= User32_FindWindow("Blitz Runtime Class",title$)


; get blitz window style
style=User32_GetWindowLong(bbHwnd,GWL_STYLE)

; add clip children style, so that controls are not blitted over
ret= User32_SetWindowLong(bbHwnd,GWL_STYLE,style Or WS_CLIPCHILDREN)


; Create a button:
ret=User32_CreateWindowEx(0,"Button","I am a button",WS_CHILD Or WS_VISIBLE,10,10,100,20,bbHwnd,101,0,0)



style=WS_BORDER Or ES_LEFT Or WS_CHILD Or WS_TABSTOP Or WS_VISIBLE
exStyle=WS_EX_CLIENTEDGE Or WS_EX_LEFT


; Create a edit box:
ret=User32_CreateWindowEx(exStyle,"Edit","The edit box",WS_CHILD Or WS_VISIBLE,10,40,400,20,bbHwnd,101,0,0)

cam=CreateCamera()
CameraViewport cam ,100,100,400,400
Viewport 100,100,400,400
PositionEntity cam ,0,0,-4 
light=CreateLight()
RotateEntity light,10,30,0
cube =CreateCube()
mybank=CreateBank(40)
hook mybank

While Not KeyHit(1)


	TurnEntity cube,1,2,3


	UpdateWorld()

	RenderWorld()
	Text 100,100,"hello "
	Flip

Wend


unhook mybank

End



Mike Yurgalavage(Posted 2004) [#8]
wow! thanks peter. i appreciate your time and effort on this. this forum is an awesome place because of people like you and some of the others who have helped people like myself. unfortunately i don't have powerbasic. is there a copy of the .dll that i can download or something that is freeware that will compile .dll's with powerbasic code? if i do download it, where do i put it so that things compile (do .dlls also go into userlibs dir with the .decls?) also, i suppose that the .dll has to have all of the keypress decisions in it or something or at least the checks for the specific keys you are using or does that go into the .bb program itself? what does the blitz3d program do specifically, does it draw a spinning cube in a windowed mode window and then end when you press ESC? can you have another program running as the focus and hitting the ESC ends the program with the spinning cube even though it doesn't have the focus? or is it simply turning the cube when you press the key down only (even if the focus is in another program)(or is WM_KEYDOWN literally any key pressed down)? What if i needed 6 or 10 different keypresses to do 10 different things when pressed? would the code for checking that go into the code in the blitz3d .bb which is between the hook and unhook calls? explain why the bank has to have a size of 40. would that number have to increase? where would i put the actual keypress checks, do i put it within the hook and unhook area? will the blitz program (the .exe generated) then check for keypresses even if that program is not the focus? like i said, i don't have powerbasic so i can't create the actual hookbb.dll and would have no way to test this in action. plus, then i need to learn the syntax for powerbasic which may or may not be like blitz3d and costs another $199.00 for a licensed version. i almost feel guilty that you put this time into this and yet i can't even try to use it. i apologize and hope that we can try this again somehow and also i am still looking for other methods as well. also, i am wondering if someone else has put together a blitz3d hook .dll like peter that is already compiled and ready for download. this has been quite the learning experience the last couple weeks.

best,
mike


Difference(Posted 2004) [#9]
Yes, WM_KEYDOWN is any key. You'll have to take it from here yourself. The above dll is does not copy the keystrokes to a bank. Copying the keystokes the bank(buffer), passed in the hook function would be an easy way to do it. If you want to make your dll safe to use with multiple Blitz3D apps running at a time, you should look into SetWindows long, and store a pointer to your apps buffer. Using global or static variables in a dll, will not make it thread safe. Good luck. I see that some people are using Purebasic for this kind of stuff. It's a lot cheaper than PowerBasic, but you can do the same thing with a free C compiler like lcc or similar.


Mike Yurgalavage(Posted 2004) [#10]
thanks again peter. any more ideas from others? bump for more viewers and ideas.

best,
mike


Tracer(Posted 2004) [#11]
Uh, why use a DLL if you just need the GetAsyncKeyState winapi command to catch any keys no matter what window they're from?

Tracer


soja(Posted 2004) [#12]
I hadn't thought of that, Tracer.

Two disadvantages I can see right off:
1) You use (possibly much) more CPU time (depending on what keys and how often you check)
2) It won't work with some applications or on other desktops

But it works generally, and might be exactly what Mike needs.

...I tried it, it works dandily.
;.lib "user32.dll"
;GetAsyncKeyState%(vKey%):"GetAsyncKeyState"

Repeat
	Print GetAsyncKeyState(1)
Forever

(Just go clicking the left mouse button and see what happens.)

For a complete list of the Virtual Key values, look the function up on MSDN.


Difference(Posted 2004) [#13]
GetAsyncKeyState might work, but make sure you have some heavy rendering going on at the same time you test this stuff. Due to it's messagepump setup, Blitz3D does not behave exactly like a normal Windows app with mouse and keyboard input. The hook posted above, is the only way I have found to get keystrokes through in a stable manner.


Mike Yurgalavage(Posted 2004) [#14]
thanks for all of the info guys! this forum is the best i have ever experienced with any software. tracer, the getasynckeystate was elegant and simple. however, peter is right and it only works in the "windowed" environment. unfortunately, when i try this in my trainer (test it with an actual game which is rendering 80 fps) the blitz3d program does not register the keystrokes. it's very easy to test and i did test it with "windowed" apps (changing the focus to another windowed program and the keystrokes were registered, but with a full blown game running in fullscreen mode with directx or whatever, it doesn't work, darn it...) i was so excited and thought we had found a simple answer to this! creating some sort of hook seems to be an answer but i cannot even test it. also, i have no way of making the .dll's necessary. it seems i am going to have to move to another language to do this. arghh.... i have EVERYTHING in place to do the programs i want except the ability to detect system-wide keypresses while utilizing blitz. any more ideas or help?

best,
mike


Mike Yurgalavage(Posted 2004) [#15]
bump for more readers and ideas-


Mike Yurgalavage(Posted 2004) [#16]
bump for more ideas on how to hook this or a different approach to gather system wide hotkeys-