Setting Hooks? (Request help.)

Just starting out? Need help? Post your questions and find answers here.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Art Sentinel.

Has anyone had any success with setting application hooks using Windows API? I read the API guides, but I think I am still missing some important points. So far, no go.. :(

What I am trying to do is set a hook on a PB app that will capture the right mouse click event before it is passed down the chain to the other processes. After that, I would like to terminate the event. I am trying to work with the WebGadget while effectively 'disabling' the r-click mouse action. It looks so much more professional not having IE's popup windows, or the popups from ActiveX objects, marring the interface of the applications I am designing.

Thank you for helping me! :)


--------------

Top Ten Reasons Not To Procrastinate:


Coming Soon...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Hi, try this (not tested with WebGadget):

Code: Select all

Global hhook
Procedure MouseProc(nCode, wParam, lParam)
  *ms.MOUSEHOOKSTRUCT = lParam
  SetGadgetText(0, "x: "+Str(*ms\pt\x))
  SetGadgetText(1, "y: "+Str(*ms\pt\y))
  If wParam = #WM_RBUTTONUP ; 205h
    result = 1
    MessageRequester("Message", "Right button up hooked", 0)
  Else
    result = 0
  EndIf
  ProcedureReturn result
EndProcedure
hInstance = GetModuleHandle_(0)
If OpenWindow(0, 0, 0, 300, 200, #PB_Window_SystemMenu, "Mouse hook example")
  WindowID = WindowID()
  If CreateGadgetList(WindowID)
    TextGadget(0, 4, 4, 48, 24, "x: ")
    TextGadget(1, 4, 32, 48, 24, "y: ")
  EndIf
  lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0)
  hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)
  Repeat
    EventID = WaitWindowEvent()
  Until EventID = #PB_EventCloseWindow
EndIf
UnhookWindowsHookEx_(hhook)
End
Hope it helps, bye,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Art Sentinel.

Great work, El_Choni! I cannot wait until I teach myself to program in PB using the WinAPI as skillfully as you do. Even half as good as you would allow me to complete this project I am working on. :) Thank you!

I am testing it now with the webgadget. Would it be equally simple to set up a hook to capture most other system events within an application? Something like this would make a suberp hook library, allowing for the easy design of right-click menus, more powerful kiosk environments, and professional level e-books.

I always appreciate any help I kindly receive. Yours is no exception. Thank you once again for lending me a helping hand.

Take care.


--------------

Top Ten Reasons Not To Procrastinate:


Coming Soon...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

No, thank you, AS. I wouldn't know too much about the API if I didn't try to answer questions posted here (a year ago, if someone asked me about the API, I would have answered it was some kind of monkey).

Before you posted your question, I used to think that hooks were only used for fishing :wink:

Have a nice day,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Art Sentinel.

Hi El_Choni, I think you would be interested to know that I have tested your right mouse hook code with the WebGadget. In fact, I tested it with several different ActiveX components. So far it seems to work exactly as I was hoping! :)

I made a tiny change. I set the WM_RBUTTONUP windows constant to WM_RBUTTONDOWN. I think you will see why that is so when you test the following code with the other constant in place. :wink: I made a tiny improvement to your code?? Woo-hoo! Miracles never cease.. Hahaha...

I have been a professional multimedia developer and graphic artist for years, but with PureBasic, I am still at the 'fishing monkey' stage. Would you please explain a couple things to me?

Why is this line important, and what precisely does it do?

*ms.MOUSEHOOKSTRUCT = lParam

Besides, to set the text gadgets:

SetGadgetText(0, "x: "+Str(*ms\pt\x))
SetGadgetText(1, "y: "+Str(*ms\pt\y))

.

Also, I understand this command:

hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)

But I am not clear as to why you added a '@' for the address part. And what exactly GetModuleHandle_(0) does.

.

.

:) All I can say is that I know no one who understands PureBasic. It is great having this forum to connect to generous people who enjoy helping others (and learning new things along the way). Thank you.

Here is my code (It takes you to my website for testing since my site is loaded with ActiveX components):

.

.

Code: Select all

;Browser Gadget With Right-Click Disabler Test
;Art Sentinel, July 29, 2002
;HUGE thanks to El_Choni!
;Using PureBasic 3.20 (current)

;Initialize Environments
;empty for now..

;Set Variables and Constants
Global hhook.l
Global myRightClick.s
#WinW=760
#WinH=500
WinX.w=(GetSystemMetrics_(#SM_CXSCREEN)-#WinW)/2 ; Window centered horizontally.
WinY.w=(GetSystemMetrics_(#SM_CYSCREEN)-#WinH)/2 ; Window centered vertically.

;Declare Procedures
Procedure MouseProc(nCode, wParam, lParam)

  If wParam = #WM_RBUTTONDOWN ;Most ActiveX components are set to process the right-mousedown event.
                              ;If you use #WM_RBUTTONUP, you will see a brief flash of the component's
                              ;r-click menu before PureBasic processes the hooked. By using #WM_RBUTTONDOWN
                              ;you do not allow the web page components to access the click event at all.
    result.b = 1
    myRightClick = "Disabled"  
    
  Else
  
    result.b = 0
    
  EndIf
  
  ProcedureReturn result
  
EndProcedure

;Open Window and center it on screen
hInstance = GetModuleHandle_(0)

If OpenWindow(0, WinX, WinY, 760, 500, #PB_Window_SystemMenu, "Browser Test")
  
  WindowID = WindowID()

  ;Open Browser Gadget
  If CreateGadgetList(WindowID()) 
   
    WebGadget(0, 1, 1, 758, 498, "[url]http://www.artsentinel.net[/url]") 
  
  EndIf

  lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0)
  hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)

EndIf

;Main loop
Repeat
  
  EventID = WaitWindowEvent()

Until EventID = #PB_EventCloseWindow

;Finish up
UnhookWindowsHookEx_(hhook)
End


--------------

Top Ten Reasons Not To Procrastinate:


Coming Soon...

Edited by - Art Sentinel on 29 July 2002 23:08:51
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Hi,
Why is this line important, and what precisely does it do?

*ms.MOUSEHOOKSTRUCT = lParam
Since lParam points to a MOUSEHOOKSTRUCT structure, you make a MOUSEHOOKSTRUCT structure point there to have easy access to its values. I think they call it 'cast pointers' or something alike.
Also, I understand this command:

hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)

But I am not clear as to why you added a '@' for the address part. And what exactly GetModuleHandle_(0) does.
MouseProc() is a procedure, and @MouseProc() is the pointer to that procedure, needed by the function.

GetModuleHandle_(0) retrieves the handle of the instance of the program module. I don't understand it either, it's Windows jargon, but you need that value a lot if you use Windows API functions. You can do a search for 'hInstance' in this forum to find out some funny issues about that.

And thanks for your code, I just didn't find #WM_RBUTTONCLICK, so I thought #WM_RBUTTOUP would do just fine.

Have fun coding,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Is this function also possible for the desktop?
Say, put the own right mouse menue instead of the windows one?


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Art Sentinel.

Hi Franco, I'm still learning the ins and outs of the WinAPI. Actually, I am finding it not as difficult as I would have thought. (And fun!)

- Every non-programmer just shuddered. Haha..

Since the Windows OS is actually a Window itself, I believe that the primary OS window may have its own hInstance. If so, and since the entire show runs off the same WinAPI, I suspect that if you could access the handle of the desktop window, you could place a hook on the system events sent to it. Another method may be to set the SetWindowsHookEx_ so that it captures ALL system events of that type. (This is one of the API options.) The obvious disadvantage of this is that a right click anywhere--even within another window's client area would produce your replacement popup menu.

This may be a great technique though to set up a kiosk environment where you wanted to captured button presses to prevent users from accessing anything except your presentation environment.

What do you think? :) I read the setting too many hooks can greatly diminish the runtime speed of your application. I still do not fully understand the logic behind this statement though.

Take care.

- Art Sentinel
http://www.artsentinel.net


--------------

Top Ten Reasons Not To Procrastinate:


Coming Soon...
Post Reply