WinAPI Tutorial #2 (HookIncludeFile)

Share your advanced PureBasic knowledge/code with the community.
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.

============
============
============


oooOO HookIncludeFile Tutorial in 10 EASY Steps OOooo

.

============
Introduction
============

When I was just a young child, my grandfather used to sit me on his knee and narrate the elaborated
stories of his life and all the 4 foot long trout he had caught with just his bare hands while
standing shoeless in a wilderness stream in the middle of a raging Winter blizzard. And while it
seemed slightly odd to me that the raging Winter blizzard had always managed to coincide
with his annual Mid-Summer fishing trip, I was nonetheless impressed by his lively cantor. And there
I sat silently still, dazzled by his words as if they were spun from gold thread itself.

It was just an ordinary morning when my Grandfather had called me over to him. He was sitting on the
porch as usual in his heavy oak chair, which overlooked the backyard. He sat there often like a
steadfast sentinel ever on watch for the fascinating backyard things that may suddenly spring forth
at anytime. With the corner of his eyes still observant of the grassy acre he glanced my direction
and said, "Son, come here. I have something very important I'd like to tell you.."

I approached him curiously. I was eager to hear another exciting chapter in his life as a professional
grizzly bear wrangler. But as I came to stand next to him, I could see by his solemn expression that
this was going to be something far more important than just a story.

"Son, what I have to say is something you must never forget."

The curiosity in my eyes burned even brighter as I quickly nodded my head and promised to remember
everything he was about to confide in me.

"Someday you will discover an amazing new tool," he said, "and this tool will change yours and many
other people's lives."

As he wet his throat with sips of his lemonade, I wondered what type of tool this may be. A hammer?
A saw? A new type of shovel perhaps??

Seeing my confusion, he chuckled and spoke once again. "You will know this tool when you see it. Just
remember this.. There is nothing 'basic' about this tool. And don't let anyone tell you otherwise! The
secret to wielding its full power lies in the API.. The API is where you will find the key..." Then
my grandfather stood up, patted me on the head, grabbed a newspaper, and walked inside to the
bathroom to do whatever grandfathers do in the bathroom for 45 minutes.

His words have puzzled me throughout my entire life until just recently when I discovered PureBasic.
This is, without a doubt, the amazing new tool my grandfather had mentioned! And like his venerable
advice, the WinAPI really is the key to overcoming most of the programming hurdles you will encounter
along the way. Nothing about PureBasic is 'basic'. And whatever you do, don't let anyone tell you
otherwise!

;)

My grandfather also mentioned that when I found this mysterious tool, people would flock from all
over the Earth just to hand me money and rare jewelry and other objects of wealth...

Hmmm.. [waiting] ... OK, so when does everyone start flocking? Hahahaha..

.

Anyhow, it seems that at least a couple people were grateful for the last WinAPI Tutorial post
of mine. I'm very happy I was able to help someone. :) Well, now that you have had the chance to check
it out, I decided to help out even more by writing my own PB_API tutorial from scratch.
This one is a bit more advanced than the other, but not too much so. Although, if you are prone to sudden
involuntary (and messy) cerebral explosions, I would recommend you keep a box of Handy Wipes
nearby just in case...


Dare I say that accessing the WinAPI through your PB code is easier and more enjoyable than using any
other worthy development tool? :wink:

.

==============
Tutorial Start
==============

Note: I am not going to explain how to program in the PureBasic language. This tutorial is aimed
at those who have already read the PureBasic documentation and did a few tests to familiarize themselves
with the general keywords and functions. There is no point in me explaining such things since many
generous and skilled people on this forum already have covered those issues in detail. Use the 'Search'
feature on the forum (top right of the window) and all your PB questions will be answered." :)

.

OK, clear out the mental cobwebs. This time around I am going to demonstrate how to set a system hook
using the API. Before I start though, I like you to send El_Choni an email thanking him for his priceless
and kind guidance, and the inspiration he installed within me to seek further enlightenment from the
learning all I can about the WinAPI functions. Without him, I would still be thinking that the 'amazing
tool' my grandfather mentioned was the gas powered WeedWacker in my garage. (I hooked a Briggs and Stratton
24 HP engine to it. Now it can cut down small trees faster than a lumberjack on steroids!) [lol]

Multimedia Design is a HUGE business. There is lots of money to be made in this field--so I heard. :wink: With
the advent of the webgadget, PureBasic is starting to finally turn some multimedia-minded heads.
Using the pack and cipher functions, PB gives E-Book authors a multitude of power to design their next
great literary creation. Someone asked me, "If PureBasic is so great for E-Book design, then where is the
command to disable the Right-Click so that embedded webpages appear more professional, and Flash
animations do not show their 'About Macromedia' menus?"

It is already there..

No, this isn't a joke. You see, Fred is a wise designer. He has already acknowledged the immense
potential behind harnessing the WinAPI to work with your PB projects. In his brilliant forethought, he
has taken steps to make using the API no more difficult than using the built in PB commands. This is powerful
stuff! (Can you see the tiny sparks of luminous energy crackling from my fingertips as I type these
words?) So you see, the command to disable the right click, the left click, the mouse wheel, the exit button,
or practically any other Windows event is already there! You only have to know where to find it, and how to
make it do what you desire. This is what I hope to help you with right now..

.

Important Tips to Remember

- Never cross the road without looking both ways first.

- Learn how to use the Win32.hlp file. This will quickly become as valuable to you as the PureBasic
HTML help itself. One thing you may not yet have noticed are the three unassuming links at the top
of each API description page" QuickInfo Overview Group. Oftentimes when you are confused and pressed for
time, these buttons will be a lifesaver.

- When you are unsure as what parameter types to use in your API code, reread the documentation for
that call. It will explicitly say what is expected. Simply convert those guidelines into PB_Speak.

- Many times you will see something like this: CALLWNDPROC, or MouseProc, or MOUSEHOOKSTRUCT. Similar
arguments are added to the format of many of the API calls. Don't assume that they are just mysterious
remnants from some long forgotten, highly advanced ancient civilization. Press the 'Index' button at the
top of the window, type in the XXXproc or XXXSTRUCT you do not understand, and learn. All the information is
there (well most of it anyhow).

- NULL means NULL. There is actually a keyword in PureBasic called NULL.

- You do not have to use the same names for the API function parameters as the help file suggests. These
are only there to give slightly cryptic ideas as to what type the variables are and whether they are pointers
or direct values. I would however recommend you stick with the common names. They will help you immensely
down the road when you forget what a procedure you have written is supposed to do.

.

Step One

Open two instances of PureBasic. (PB does not support multiple documents yet, but this method is
almost as good.) Open a new project in each. Name and save each in the same directory, the first one
"HookIncludeFile.pb" and the second "HookIncludeFile.pbi" Note: You may need to open Explorer to set the
correct name if PureBasic decides to use the name 'HookIncludeFile.pbi.pb' instead.)

Done that? Good! Now you will start the fun stuff..

Step Two

In the HookIncludeFile.pb file you will add the code to open a window, place a button gadget in the
center of that window, and then add a main loop that repeats until you choose to exit the app, or you click
on the button gadget.

Step Three

Set up your application so that if the user clicks the button, its text will toggle back and forth
between the words "UnHooked" to "Hooked!" with each click. This is merely to be used a visual aid to yourself
to signify when the system hook is enabled and when it is not.

Step Four

At the very beginning of your code, include the HookIncludeFile.pbi file you already saved. This
included file will contain your API functions and add the easy to use feature of disabling (or processing)
the right mouse button click to your application. Remember this: To disable a right mouse click, just do
nothing with the event. To add your own right click menus, etc, simply take the #WM_RBUTTONDOWN event and
process it anyway you like.

Step Five

At the end of your code, add the single and very simple WinAPI call: UnhookWindowsHookEx_(hhook).
Now ensure that your code redirects any requests to exit to this API function. This call is there to make
certain that upon exiting your application, any hooks you set to the window are cancelled, and your system
resources are freed up to help prevent OS crashes. The 'hhook' part is the handle of the hook procedure
to remove. This variable is set within your HookIncludeFile.pbi. If you exit while the hook is still active
it will disable it. If you exit when there are no hooks, this API function will return the value FALSE and do
nothing. This is your safeguard.

Step Six

Your first file is nearly completed now. Congratulations! You should have a window that opens, and a
button in the middle of its client area that toggles between the words "UnHooked" and "Hooked!". Next
you will add the procedure calls:

HookProc("No")
HookProc("Yes")

In HookIncludeFile.pbi you will be writing a procedure named HookProc(). This procedure will accept one
parameter. (This parameter is case sensitive!) If you specify "Yes" the right-click hook will be activated.
If you set the value to "No" the hook will be deactivated. This is how easy it will be for now on to add right-
click disabling/processing to any application you design (E-Book authors celebrate!). :)

Obviously, you will add the HookProc("Yes") to the section of code that changes the button's text to
"Hooked!" and vice versa for the other procedure call.

.

To make thing easier for you, something Similar to the following is what you should have so far:
If you like to use my code sample, download the bitmap for the ButtonImageGadget from my
server here: http://www.artsentinel.net/images/Smiley.bmp Place it within the same directory
as your .pb and .pbi files. (Do not change the bitmap's name; and do not laugh at the picture of me. I was having
a bad hair day when this image was taken.)

.

.

Code: Select all

;====================
;Hook IncludeFile API Test
;Art Sentinel August, 02, 2002
;For everyone at the PureBasic Forum
;====================
;ILYLCBD


;Declare variables
#Smiley = 1964


;Declare Include
IncludeFile "HookIncludeFile.pbi"


;Delcare procedures
Procedure FixImageBBug (ButtonNumber.l, Bx.l, By.l,Bw.l, Bh.l)
  
  ResizeGadget(ButtonNumber, Bx, By, Bw, Bh)
  
EndProcedure


;Open window
If OpenWindow(0, 150, 150, 300, 300, #PB_Window_SystemMenu, "Hook IncludeFile API Test")
  hWnd = WindowID()
  
  ;Handle gadgets
  If CreateGadgetList(hWnd)
    ;Set text gadgets
    NormalFont.l = LoadFont(0, "Arial", 10) 
    SmallFont.l = LoadFont(1, "Arial", 6) 
    SetGadgetFont(SmallFont) 
    TextGadget(66, 0, 275, 300, 250, "If you can read this you are sitting too close to your monitor.", #PB_Text_Center) 
    SetGadgetFont(NormalFont)
    TextGadget(007, 110, 85, 80, 30, "UnHooked", #PB_Text_Center)
    
    ;Set button gadget
    If LoadImage(#Smiley, "Smiley.bmp") 
      Smiley.l = ImageID() 
      ButtonImageGadget(14, 110, 108, 80, 84, Smiley) 
    
      Else
        MessageRequester(":(", "I think you forgot to add the 'Smiley.bmp' to the folder this .pb file is in?", #PB_MessageRequester_OK)
        End
    
    EndIf
      
    Else
      MessageRequester("Error", "Cannot Create Gadget List", #PB_MessageRequester_OK)
      End
  
  EndIf
  
  Else
    MessageRequester("We're Sorry..", "The window you tried opening is not currently available. Please hang up and try back later.", #PB_MessageRequester_Ok)
    End
    
EndIf


;Main loop
  Repeat
    
    Select WaitWindowEvent()
      
      Case #PB_EventGadget

        Select EventGadgetID()
          
          Case 14
            If Hooked$ = "Yes"
              HookProc("No")
              Hooked$ = "No"
              SetGadgetText(007, "UnHooked") 
              FixImageBBug(14, 110, 108, 80, 84); The ButtonImageGadget seems to have a bug refreshing when clicked (win98 SE)?
                          
             Else
              HookProc("Yes")
              Hooked$ = "Yes"
              SetGadgetText(007, "Hooked!") 
              FixImageBBug(14, 110, 108, 80, 84); Fred, please tell me if this is a bug? :)        
            
            EndIf
            
           EndSelect
      
      Case #WM_CLOSE
        Quit = 1
        
    EndSelect
            
  Until Quit = 1
  

;Finish up
UnhookWindowsHookEx_(hhook)
MessageRequester("Words of Wisdom:", "If it hurts, then stop slamming it in the car door.", #PB_MessageRequester_OK)
End
.

.

Step Seven

Save your first file. Work now on the second.

At the top, add the following variable declarations to your file:

Global hhook
Global AlreadyPop
AlreadyPop = 0
Hooked$ = "No"
#MenuPopR = 44
#MenuPopL = 45

Step Eight

This file will consist of two short procedures you will write. One will turn your right-click hook on
and off, and the other will process the right click event signified by the #WM_RBUTTONDOWN API constant.
You should be aware that there are many possible #WM_XXX constants you can use in place of the one I have
chosen to use. For example, if you prefer to process the right click once a person lets go of the button,
use #WM_RBUTTONUP instead.

WARNING: If you hook the left click event, I would highly recommend that you use
CallNextHookEx_() to pass the event down the chain to the other window processes after you are done
with it. If you do not, you severely risk crashing your computer. Think about it.. You capture the left
click, then you try to turn off the application which captures the left click again, and then an error appears,
and while you are trying to click 'OK' your left click is capture again, and again, and again.. and
AARRGGHhhh!! Use CallNextHookEx_() and you will have only half the nosebleeds. :wink:

This is the first procedure you will use:

.

.

Code: Select all

Procedure MouseProc(nCode, wParam, lParam)
  DefType.b Result
  
  ;Check which button was clicked
  Select wParam
  
    Case #WM_RBUTTONDOWN
      Result = 1
      DisplayPopupMenu(#MenuPopR, WindowID())
            
    Default
    Result = 0
  
  EndSelect  
  
  ProcedureReturn Result

EndProcedure
.

.

Once the system mouse hook is set, all mouse events will be directed continuously to this procedure.
(It runs the entire time it is needed, even though you may not be aware of this.) nCode,
wParam, and lParam are the three values your OS will pass to this procedure.

nCode: Specifies a code the hook procedure uses to determine how to process the message.
(You will not use this value directly for this tutorial.)

wParam: Specifies the identifier of the mouse message.
(This is where you determine what mouse event was just sent--such as, #WM_RBUTTONDOWN)

lParam: Points to a MOUSEHOOKSTRUCT structure.
(Cool things happen in this structure! You can access it contents the same way you access any PureBasic
structure. Some of the information available for you to use in your application is the x and y coordinates
of the mouse pointer within the window. This is a great thing if you want to design your own graphical
roll-over buttons.)

The mouse system events filter through this procedure like a pasta strainer. If you placed a
piece of code to process a particular mouse event this procedure will capture ('hook' it) and do with it
what you want done. If you add the CallNextHookEx_() function then that event will drain through your mouse
pasta strainer and go on to be processed by any other waiting system functions such as buttons, etc. If you
do not add CallNextHookEx_(), the processed event will end right there with your procedure (a great method
for disabling a system event). All non-processed events will pour through your MouseProc() and continue on
their way down the drain to wherever they are headed.

Do be warned though, when you activate a system hook, you are in essence running that type of event
through your application code. Do not hook more than what you absolutely need, and free up hooks that are
no longer required. If you try hooking the window events, the mouse events, the keyboard events, and the
message events, you are likely to end up with a clogged up pasta strainer that will take forever to allow
the events to flow through it.

Mmmmm.. Suddenly I am hungry for spaghetti and meatballs! Anyone else hungry? Haha..

Special Note: Did it just dawn on you that a similar procedure to the one above could be use to process
almost any system event--not just mouse clicks? The possibilities are staggering, huh!

Step Nine

Now add this second and final procedure:

.

.

Code: Select all

Procedure HookProc(Hooked$)
  Shared hhook
  
  ;Set Popup Menu
  If AlreadyPop
    ;Do nothing..

    Else
     CreatePopupMenu(#MenuPopR)
     MenuItem(0, "Right Click Event Hooked!") 
     AlreadyPop = 1
           
  EndIf
      
  Select Hooked$
  
    Case "Yes"
      hInstance = GetModuleHandle_(0)
      lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0)
      hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)
    
    Case "No"
      UnhookWindowsHookEx_(hhook)
      
  EndSelect
  
EndProcedure
.

.

Here you see the HookProc() we spoke of earlier. This is also where the 'hhook' variable is given
its value. In the case of my code sample, I have added a popup menu that acknowledges when the right
click event hook has been set. After that first portion, you will see the part of the code that defines the
SetWindowsHookEx_(idHook, hkprc, hInstance, lpdwProcessId) API call.

idHook: Specifies the type of hook procedure to be installed.
(In our tutorial we are using the #WM_MOUSE constant so that we can processed the mouse events
that are captured by the window of our application.)

hkprc: Points to the hook procedure.
(The MousePro that we
wrote in the previous step. Notice it is a POINTER, and being such we add a '@' to the start of the
parameter: @MouseProc(). Always be careful of this distinction. An argument like this one wants the
pointer to the memory location of your MouseProc(). If you forget the '@' your application will turn your
screen red and write, "Redrum! Redrum!" repeatedly until your monitor explodes! ..Or maybe or program will
just not work right. Either scenario is just as frightening.) :wink:

hInstance: Identifies the DLL containing the hook procedure pointed to by the hkprc parameter.
The hMod parameter must be set to NULL if the dwThreadID parameter specifies a thread created by the
current process and if the hook procedure is within the code associated with the current process.

(hInstance = GetModuleHandle_(0))

lpdwProcessId: Specifies the identifier of the thread with which the hook procedure is to be associated.
(lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0))

Step Ten

Your code for the .pbi file should look similar to this:

.

.

Code: Select all

;====================
;Hook IncludeFile API Test (IncludeFile)
;Art Sentinel August, 02, 2002
;For everyone at the PureBasic Forum
;====================
;ILYLCBD


;Declare variables
Global hhook
Global AlreadyPop
AlreadyPop = 0
Hooked$ = "No"
#MenuPopR = 44
#MenuPopL = 45


;Declare Procedures
Procedure MouseProc(nCode, wParam, lParam)
  DefType.b Result
  
  ;Check which button was clicked
  Select wParam
  
    Case #WM_RBUTTONDOWN
      Result = 1
      DisplayPopupMenu(#MenuPopR, WindowID())
            
    Default
    Result = 0
  
  EndSelect  
  
  ProcedureReturn Result

EndProcedure

;============
;============
;============

Procedure HookProc(Hooked$)
  Shared hhook
  
  ;Set Popup Menu
  If AlreadyPop
    ;Do nothing..

    Else
     CreatePopupMenu(#MenuPopR)
     MenuItem(0, "Right Click Event Hooked!") 
     AlreadyPop = 1
           
  EndIf
      
  Select Hooked$
  
    Case "Yes"
      hInstance = GetModuleHandle_(0)
      lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0)
      hhook = SetWindowsHookEx_(#WH_MOUSE, @MouseProc(), hInstance, lpdwProcessId)
    
    Case "No"
      UnhookWindowsHookEx_(hhook)
      
  EndSelect
  
EndProcedure
.

.

Save your .pbi file, cross your fingers for good luck, and compile and run you .pb file. If all
works, then Congratulations! You have just taken a sizable step forward to harnessing the true power
of PureBasic.

If your application fails.. Oops! Just read this tutorial and check your spelling, or
copy and paste the sample code I designed for you. I will walk to the bathroom now to do whatever PB
programmers do in the bathroom for 45 minutes.



;)


.

.

Have fun!


- Art Sentinel

.


If you do not feel as if your head is already about to violently implode, you will find the WinAPI
information concerning this tutorial below. Armed with this, and the above lessons, I am sure you
will be producing topnotch E-Books in no time at all! Let's see any other multimedia developer
tools on the market produce such tiny optimized executables without bloated runtime DLL's and slow
buggy interpreters. For Multimedia work, for fun or for profit, there is nothing quite like
PureBasic. :)

.

===================
Related WinAPI Docs
===================

SetWindowsHookEx QuickInfo Overview Group

The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. An application installs a hook procedure to monitor the system for certain types of events. A hook procedure can monitor events associated either with a specific thread or with all threads in the system. This function supersedes the SetWindowsHook function.

HHOOK SetWindowsHookEx(

int idHook, // type of hook to install
HOOKPROC hkprc, // address of hook procedure
HINSTANCE hMod, // handle of application instance
DWORD dwThreadID // identity of thread to install hook for
);


Parameters

idHook

Specifies the type of hook procedure to be installed. This parameter can be one of the following values:

Value Description
WH_CALLWNDPROC Installs a hook procedure that monitors messages before the system sends them to the destination window procedure. For more information, the CallWndProc hook procedure.
WH_CALLWNDPROCRET Windows 95 only: Installs a hook procedure that monitors messages after they have been processed by the destination window procedure. For more information, see the CallWndRetProc hook procedure.
WH_CBT Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application. For more information, see the CBTProc hook procedure.
WH_DEBUG Installs a hook procedure useful for debugging other hook procedures. For more information, see the DebugProc hook procedure.
WH_GETMESSAGE Installs a hook procedure that monitors messages posted to a message queue. For more information, see the GetMsgProc hook procedure.
WH_JOURNALPLAYBACK Installs a hook procedure that posts messages previously recorded by a WH_JOURNALRECORD hook procedure. For more information, see the JournalPlaybackProc hook procedure.
WH_JOURNALRECORD Installs a hook procedure that records input messages posted to the system message queue. This hook is useful for recording macros. For more information, see the JournalRecordProc hook procedure.
WH_KEYBOARD Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook procedure.
WH_MOUSE Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure.
WH_MSGFILTER Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. For more information, see the MessageProc hook procedure.
WH_SHELL Installs a hook procedure that receives notifications useful to shell applications. For more information, see the ShellProc hook procedure.
WH_SYSMSGFILTER Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. The hook procedure monitors these messages for all applications in the system. For more information, see the SysMsgProc hook procedure.


hkprc

Points to the hook procedure. If the dwThreadID parameter is zero or specifies the identifier of a thread created by a different process, the hkprc parameter must point to a hook procedure in a dynamic-link library (DLL). Otherwise, hkprc can point to a hook procedure in the code associated with the current process.

hMod

Identifies the DLL containing the hook procedure pointed to by the hkprc parameter. The hMod parameter must be set to NULL if the dwThreadID parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

dwThreadID

Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads.



Return Value

If the function succeeds, the return value is the handle of the hook procedure.
If the function fails, the return value is NULL.

Remarks

An error may occur if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process.
Chaining to the next hook procedure (that is, calling the CallNextHookEx function) is optional. An application or library can call the next hook procedure either before or after any processing in its own hook procedure.
Before terminating, an application must call the UnhookWindowsHookEx function to free system resources associated with the hook.

The scope of a hook depends on the hook type. Some hooks can be set only with system scope; others can also be set for only a specific thread, as shown in the following list:

Hook Scope
WH_CALLWNDPROC Thread or system
WH_CBT Thread or system
WH_DEBUG Thread or system
WH_GETMESSAGE Thread or system
WH_JOURNALPLAYBACK System only
WH_JOURNALRECORD System only
WH_KEYBOARD Thread or system
WH_MOUSE Thread or system
WH_MSGFILTER Thread or system
WH_SHELL Thread or system
WH_SYSMSGFILTER System only


For a specified hook type, thread hooks are called first, then system hooks.
The system hooks are a shared resource, and installing one affects all applications. All system hook functions must be in libraries. System hooks should be restricted to special-purpose applications or to use as a development aid during application debugging. Libraries that no longer need a hook should remove the hook procedure.

See Also

CallNextHookEx, CallWndProc, CBTProc, DebugProc, GetMsgProc, JournalPlaybackProc, JournalRecordProc, KeyboardProc, MouseProc, MessageProc, ShellProc, SysMsgProc, UnhookWindowsHookEx



========================



MouseProc QuickInfo Overview Group

The MouseProc hook procedure is an application-defined or library-defined callback function the system calls whenever an application calls the GetMessage or PeekMessage function and there is a mouse message to be processed.

LRESULT CALLBACK MouseProc(

int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
);


Parameters

nCode

Specifies a code the hook procedure uses to determine how to process the message. This parameter can be one of the following values:

Value Meaning
HC_ACTION The wParam and lParam parameters contain information about a mouse message.
HC_NOREMOVE The wParam and lParam parameters contain information about a mouse message, and the mouse message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)


If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx.

wParam

Specifies the identifier of the mouse message.

lParam

Points to a MOUSEHOOKSTRUCT structure.



Return Value

To enable the system to process the message, the return value must be zero. To discard the message, the return value must be a nonzero value.

Remarks

The hook procedure must not install a JournalPlaybackProc callback function.
An application installs the hook procedure by specifying the WH_MOUSE hook type and the address of the hook procedure in a call to the SetWindowsHookEx function.
MouseProc is a placeholder for the application-defined or library-defined function name.

See Also

CallNextHookEx, GetMessage, JournalPlaybackProc, MOUSEHOOKSTRUCT, PeekMessage, SetWindowsHookEx



=============================



UnhookWindowsHookEx QuickInfo Overview Group

The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.

BOOL UnhookWindowsHookEx(

HHOOK hhook // handle of hook procedure to remove
);


Parameters

hhook

Identifies the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.



Return Value

If the function succeeds, the return value is TRUE.
If the function fails, the return value is FALSE.

Remarks

The hook procedure can be in the state of being called by another thread even after UnhookWindowsHookEx returns. If the hook procedure is not being called concurrently, the hook procedure is removed immediately before UnhookWindowsHookEx returns.

See Also

SetWindowsHookEx, UnhookWindowsHook



===============================


MOUSEHOOKSTRUCT QuickInfo

typedef struct tagMOUSEHOOKSTRUCT { // ms

POINT pt;
HWND hwnd;
UINT wHitTestCode;
DWORD dwExtraInfo;
} MOUSEHOOKSTRUCT;


The MOUSEHOOKSTRUCT structure contains information about a mouse event.

Members

pt

Specifies a POINT structure that contains the x- and y-coordinates of the cursor, in screen coordinates.

hwnd

Identifies the window that will receive the mouse message corresponding to the mouse event.

wHitTestCode

Specifies the hit-test value. For a list of hit-test values, see the description of the WM_NCHITTEST message.

dwExtraInfo

Specifies extra information associated with the message.



See Also

GetMessageExtraInfo, POINT, SetWindowsHook, SetWindowsHookEx, WM_NCHITTEST


===============================


CallNextHookEx QuickInfo Overview Group

The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. This function supersedes the DefHookProc function.

LRESULT CallNextHookEx(

HHOOK hhk, // handle of current hook
int nCode, // hook code passed to hook procedure
WPARAM wParam, // value passed to hook procedure
LPARAM lParam // value passed to hook procedure
);


Parameters

hhk

Identifies the current hook. An application receives this handle as a result of a previous call to the SetWindowsHookEx function.

nCode

Specifies the hook code passed to the current hook procedure. The next hook procedure uses this code to determine how to process the hook information.

wParam

Specifies the wParam value passed to the current hook procedure. The meaning of this parameter depends on the type of hook associated with the current hook chain.

lParam

Specifies the lParam value passed to the current hook procedure. The meaning of this parameter depends on the type of hook associated with the current hook chain.



Return Value

If the function succeeds, the return value is the value returned by the next hook procedure in the chain. The current hook procedure must also return this value. The meaning of the return value depends on the hook type. For more information, see the descriptions of the individual hook procedures.

Remarks

Hook procedures are installed in chains for particular hook types. CallNextHookEx calls the next hook in the chain.
Calling CallNextHookEx is optional. A hook procedure can call this function either before or after processing the hook information. If a hook procedure does not call CallNextHookEx, Windows does not call the hook procedures installed before the current hook procedure was installed.

See Also

SetWindowsHook, SetWindowsHookEx, UnhookWindowsHook, UnhookWindowsHookEx


===============
End (for now..)
===============

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

Top Ten Reasons Not To Procrastinate:


Coming Soon...


Edited by - art sentinel on 06 August 2002 08:12:43
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.

Art Sentinel: it must be raining sooo heavily in your town. Where did you got the time to write this very fine doc? You've done a great job! Keep on with it! I would help you, but it doesn't rain too much here. In fact, it's light-years far from raining...

Good job

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.

[lol] Well actually, El_Choni, it is raining here. But that is only after two months of dry weather and crunchy brown grass.

I'm glad you like my tutorial. I want to see PureBasic succeed. I think the only major thing holding it back from becoming extremely popular is the lack of documentation for those who are not already seasoned programmers. I am only lucky that I have such strong knowledge of JavaScript and Actionscript along with a tiny bit of Visual Basic and BlitzBasic. If not for that, I may not have been able to relate to the concepts needed to produce fun and functional PB applications.

However, now that I am learning it better each day, I am more and more realizing how closely bonded PB is with the WinAPI and WinASM. And to my utter surprise, using the API in PureBasic is not hard or scary at all! (It is even exciting?) :wink: I just want to help more people be able to realize that almost anything you can think of can be done in PB, faster, better, and without so many headaches. Your clients will thank you; your boss will thank you; and your wallet will certainly thank you too.

You hear this Fred? [hint] If you ever need a three-eyed smiley mascot, you know where to find one. Haha..

Really, I just hope this will help someone in some small way.

Take care.


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


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

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 fweil.

Be sure it definitely helps to have such documentation. Your Hook Tutorial is better to me than any other thing I red elsewhere.

Congratulations and thanks again.

Francois Weil
14, rue Douer
F64100 Bayonne
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post by newbie »

When in the "CallWndProc" hook procedure, how can i read lParam information ?

when declared as a parameter, lParam is a "long" variable.
But from what i read, it is also a structure "CWPSTRUCT", how can i access it ?

typedef struct {
LPARAM lParam;
WPARAM wParam;
UINT message;
HWND hwnd;
} CWPSTRUCT, *PCWPSTRUCT;
my code:
Procedure Hook(nCode, wParam, lParam)

If nCode < 0 : ProcedureReturn CallNextHookEx_(hHook, nCode, wParam, lParam) : EndIf

Info.CWPSTRUCT

Info = lParam.CWPSTRUCT


Debug info\lparam


UnhookWindowsHookEx_(hHook)

; 0 = system can process the message
ProcedureReturn 0
;MessageRequester("ok :", "ok.", #PB_MessageRequester_Ok)

EndProcedure
I can't compile this code if i try to read the CWPSTRUCT ( i don't do Mouse hooking but System Hooking).
If i don't try to read all "works" fine, but if i can't know what i'm hooking it's useless...[/quote]
- Registered PB user -

Using PB 4.00
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

use a pointer if lparam is an address to the structure..

Code: Select all

*info.CWPSTRUCT = lparam
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post by newbie »

apparently,
*info.CWPSTRUCT = lparam

Debug *info\message
seems to work, thanks you :)
- Registered PB user -

Using PB 4.00
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post by newbie »

i try to view all access to a particular API (let's say "GetCurrentDirectory") and with the method provided in this thread i fail to do it.

I thought that with the SetWindowsHookEx API i would be able to accomplished my purpose, am i wrong on this point ?
- Registered PB user -

Using PB 4.00
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

AHAHAHAHAHAHAHAHAH!

I slept for the first part of your story, but i caught the second half ;)

Nice work and intro :mrgreen:
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

I think there may be an error in the tutorial code.

In procedure HookProc() at step 9, I think the line:

Code: Select all

lpdwProcessId = GetWindowThreadProcessId_(WindowID, 0)
should have additional parentheses and be:

Code: Select all

lpdwProcessId = GetWindowThreadProcessId_(WindowID(), 0)
The tutorial program works correctly (on my PC running Windows ME) in both versions.
I would have expected the first version to fail. Am I misunderstanding something?
Anthony Jordan
Post Reply