Akemi Spy Library

Akemi Spy Library v1.0.4

Akemi Spy Library is an ActiveX DLL which encapsulates some of the functionality of Windows Hooks.

Developer's Guide

Class Reference

Event Index

Method and Functions Index

Properties Index

Licensing and Redistribution

Akemi VB Home Page

Copyright and Disclaimer


Copyright and Disclaimer

Akemi Spy Library, including this documentation, is copyright 2001 Akemi.

Microsoft, Visual Basic, and Windows are trademarks of Microsoft.

In explaining how to use Akemi Spy Library, parts of this documentation refer to more general issues relating to Windows and Visual Basic. Any advice given here should be taken in the context of the full documentation of these two products as supplied by Microsoft.

All information here is provided "as is". No warranty is intended.

Akemi is owned and operated by Adelle Hartley.

email: adelle@akemivb.com

Ph: +61 4 04 04 6245

Snail Mail:
15 Culloden Ave
Lutana Tasmania 7009
Australia

See also: Licensing and Redistribution

Home


Licensing and Redistribution

The "Demonstration" version of Akemi Spy Library will display a pop-up nag screen when used in debug-mode.

A "Licensed" version of Akemi Spy Library can be purchased through the AkemiVB web site, which will:

  • Eliminate the nag screen.
  • Entitle you to distribute AkemiSpyLibrary.DLL and CbHelper.DLL with your software which uses the Akemi Spy Library.

The redistributed version of Akemi Spy Library will have the same limitations as the Demonstration version. That is, if Akemi Spy Library is used to build an ActiveX control, then developers who use that control will see a nag screen when debugging applications which use that control.

Addin developers:

In most cases, Akemi Spy Library can be redistributed with VB6 add-ins, without it displaying the nag screen. Contact sales@akemivb.com to discuss your specific requirements.

Home


Akemi Spy Library Guide

Guide

Contents

Introduction (Windows 101)
Displaying a list of open windows
Trapping keyboard events (global or specific thread)
CBT Events
Receiving events when the user changes windows
 Control Highlighting
Trapping mouse events (or which button did the user click?)

See also: Licensing and Redistribution


Introduction (Windows 101)

Akemi Window Spy

Our philosophy at Akemi is that "Windows is meant to be easy, and Visual Basic is meant to be easy". This is not intended to belittle the efforts of the millions of Visual Basic programmers who are producing serious professional code. It merely a statement of one of the key reasons for the widespread success of Visual Basic.

By making the "hard" parts of Windows programming easier, we hope to give you the programmer, more time to concentrate on what you do best - writing applications that do stuff.

Akemi Spy Library is an ActiveX DLL which encapsulates some of the functionality of Windows Hooks.

Windows Hooks are used to monitor the system for certain types of events. These events are associated with a specific thread or with all threads in the same desktop as the calling thread.

This is slightly different from the usual way of Visual Basic programming, where events are associated with a form or a visual control placed on a form.

What counts as a window?

Under Microsoft Windows, a window is a (usually rectangular) area managed by the operating system and assigned a window handle (also known as an hWnd).

A window can be a top-level or Mdi child window. This is what end-users are usually referring to when they say "window". In Win32 programming, a window can also be an ActiveX control, or an invisible window used to process a Message Queue.

Messages

The operating system sends messages to individual windows in response to user actions. For example, whenever you move your mouse pointer, the system is dispatching a series of WM_MOUSEMOVE messages to whichever window the mouse is over.

Every window which processes messages must have a Window Procedure. When you design a form in Visual Basic, Visual Basic creates a window procedure which raises events that you can handle through Visual Basic code.

To handle messages which are not implemented as Visual Basic events requires the use of a technique known as subclassing. Subclassing can only be used to process messages received by windows owned by the thread which processes them. Subclassing is not a part of Akemi Spy Library.

Hooks (more information than you need to know, if you are using Akemi Spy Library)

Under Win32, hooks are the only way of trapping events in processes other than your own.

Hooks can be set by calling the Windows API function SetWindowsHookEx, specifying the type of hook you want to set, and the address of a hook procedure for Windows to call when the hook is triggered.

The catch is, that if you are setting a global hook, or a single thread hook for a thread in a different process to your application, then the hook procedure supplied to SetWindowsHookEx must reside in a DLL, and a new instance of that DLL will be attached to each thread which triggers the hook.

That means that the DLL will be in a different address space from the application which set the hook. Therefore there needs to be some form of cross-process communication in order for your application to receive information from hooks.

Akemi Spy Library accomplishes this by installing hook procedures which send messages to an invisible window which gets attached to your application. The window procedure for this invisible window passes these messages to your application as COM events, much the same way that Visual Basic raises standard events in response to messages sent to standard Visual Basic forms.

Limitations of Akemi Spy Library

At this time, there are certain types of Windows hooks which cannot be obtained using Akemi Spy Library. In particular, the Journalling hooks which allow recording and playback of mouse and keyboard events.

These features may be added to a future version of the Spy Library if there is sufficient demand. In the meantime, consider using one of the following techniques for manipulating applications.

(i) The SendMessage API. It is possible to invoke the menu commands of other applications by sending a WM_COMMAND message. This may be preferable to sending keystrokes which will visually bring up the application's menu.

(ii) SendKeys. This is a built-in VB/VBA procedure which can be used to simulate keystrokes.

Also, Akemi Spy Library is currently limited to 10 simultaneous hooks. I have not yet run into a situation where this is not sufficient. If you do, then contact support@akemivb.com


Displaying a list of open windows

The following example demonstrates how to use Akemi Spy Library to loop through all the open windows on the system.

To create this example from scratch, create a standard exe project with one form. Open zip file

The form has the following controls (not including the various labels):

lstmWindows | ListBox. Used to display the captions of all the open windows on the system.
txtmClassName | TextBox. Used to display the Class Name of a selected window.
btnmRefresh | CommandButton. Clicking on this button refreshes the displayed list.
btnmClose | Closes the dialog.

Screen shot of example, showing list of open windows

The code for this form is below:

Option Explicit

Private Sub btnmClose_Click()
    Unload Me
End Sub

Private Sub btnmRefresh_Click()
    FillListBox
End Sub

Private Sub Form_Load()
    FillListBox
End Sub

Private Sub FillListBox()
    'Fill lstmWindows with the captions of all the windows
    'in objmWindows which are visible and have a caption.

    Dim objWindow As Window

    'Clear any entries from previous calls to FillListBox
    lstmWindows.Clear

    'Iterate through each window in the collection
    For Each objWindow In GetTopLevelWindows
        'Check whether the window is even visible
        If objWindow.Visible Then
            'Check whether the window even has a caption
            If objWindow.Caption <> "" Then
                lstmWindows.AddItem objWindow.Caption

                'Set the item data for the newly added item to be the
                'window's hWnd.
                lstmWindows.ItemData(lstmWindows.NewIndex) = objWindow.hWnd
            End If
        End If
    Next objWindow
End Sub

Private Sub lstmWindows_Click()
    'Update txtmClassName with the class name of the currently
    'selected window.

    Dim objWindow As Window
    Dim lFindHwnd As Long

    'Get the hWnd of the selected window from the
    'List Box's item data
    lFindHwnd = lstmWindows.ItemData(lstmWindows.ListIndex)

    Set objWindow = GetTopLevelWindows.FindWindowByHwnd(lFindHwnd)

    'If the window wasn't found, then it must have been closed,
    'since the last call to FillListBox.
    If objWindow Is Nothing Then
        txtmClassName.Text = "* Window was closed. *"
    Else
        'We have a winner.
        txtmClassName.Text = objWindow.ClassName
    End If
End Sub

See also: GetTopLevelWindows, GetChildWindows, Windows Property


Trapping Keyboard Events

The following example demonstrates how to use Akemi Spy Library to trap keyboard events on either a system-wide basis or just within a given thread.

To create this example from scratch, create a standard exe project with one form. Open zip file

The form has the following controls (not including the various labels):

txtmEverything | TextBox. Used to display everything you type in other applications. The Locked property is set to True so that you cannot type directly into the TextBox.
btnmStartNotepad | CommandButton. Starts Notepad.
chkmBlockW | CheckBox. Indicates whether the W key is to be blocked from all applications.
optmMonitorAllThreads | OptionButton. When selected, the application will monitor keyboard events from all threads.
optmOnlyMonitorNotepad | OptionButton. When selected, the application will search for an instance of Notepad, and then monitor keyboard events from that instance of Notepad.

The code for this form is below:

Option Explicit

'ShellExecute API is used to launch Notepad.
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
'Constant used in call to ShellExecute
Private Const SW_SHOWNORMAL = 1

'Object to receive keyboard events must be declared at
'class or form level.
Private WithEvents objmKeyboardEvents As KeyboardEvents

Private Sub btnmStartNotepad_Click()
    If ShellExecute(Me.hwnd, "Open", "Notepad.exe", "", "", SW_SHOWNORMAL) <= 32 Then
        MsgBox "Unable to start Notepad."
    End If
End Sub

Private Sub Form_Load()
    'Default option is to trap keyboard events from all threads.
    Set objmKeyboardEvents = GetAllThreads.KeyboardEvents
End Sub

Private Sub objmKeyboardEvents_KeyDown(Window As AkemiSpyLibrary.Window, ByVal KeyCode As Integer, ByVal AutoRepeat As Boolean, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal Alt As Boolean, Cancel As Boolean)
     'Add the key that was pressed to the text box.
    txtmEverything.Text = txtmEverything.Text & Chr$(KeyCode)

    'Ensure that the last piece of text added to the text box
    'is visible by setting the selection to start at the end of the text.
    txtmEverything.SelStart = Len(txtmEverything.Text)

    'If the W key is being blocked, then cancel the keystroke
    'so that other applications don't receive it.
    '(This technique is shown here for educational purposes only.
    'Use of this program to play practical jokes on newly elected
    'heads of state is not in any way condoned by Akemi).
    If chkmBlockW.Value And UCase$(Chr$(KeyCode)) = "W" Then
        Cancel = True
    End If
End Sub

Private Sub optmMonitorAllThreads_Click()
    Set objmKeyboardEvents = GetAllThreads.KeyboardEvents
End Sub

Private Sub optmOnlyMonitorNotepad_Click()
    Dim objNotepadWindow As Window

    'Find the first instance of Notepad to come to hand.
    'This example does not account for the possibility of multiple
    'instances of Notepad being open - only the first one to be
    'found will be monitored.
    Set objNotepadWindow = GetTopLevelWindows.FindWindow("* Notepad", "Notepad")

    'Check whether an instance of Notepad was found, and
    'display a message if Notepad is not already open.
    If objNotepadWindow Is Nothing Then
        MsgBox "No instances of Notepad currently open."
        optmMonitorAllThreads.Value = True
    Else
        'What we have found is a Window. The Keyboard events we
        'are going to trap, belong to the Thread of that window.
        Set objmKeyboardEvents = objNotepadWindow.Thread.KeyboardEvents
    End If
End Sub

See also: KeyboardEvents Property, KeyboardEvents Object


CBT Events

CBT

CBT stands for Computer Based Training, and the CBT hook on which the CbtEvents class is based, was originally intended for Computer Based Training applications, although it has a lot of other possible uses.

The following examples demonstrate the CbtEvents class:

When the User Changes Windows

Control Highlighting


When the user changes windows

This example demonstrates two methods of preventing users from playing Solitaire. An alternative method would be to remove Solitaire.exe from the hard drive, but the methods presented here will work even if the user attempts to run Solitaire from a copy stored on a floppy disk.

To create this example from scratch, create a standard exe project with one form. Open zip file

The form has the following controls (not including the various labels):

txtmLog | TextBox. Used to display a log of CBT events as they are trapped. Newest events are shown at the top.
chkmDisableSolitaire1 | CheckBox. Disables Solitaire using method 1, which is to prevent creation of the Solitaire window.
chkmDisableSolitaire2 | CheckBox. Disable Solitaire using method 2, which is to prevent activation of the Solitaire window after it has been created.
btnmClose | CommandButton. Closes the dialog.

The code for this form is below:

Option Explicit

'SendMessage API is used to disable Solitaire (method 2).
 Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_CLOSE = &H10

'Object to receive CBT events must be declared at
'class or form level.
Private WithEvents objmCbtEvents As CbtEvents

Private Sub btnmClose_Click()
    Unload Me
End Sub

Private Sub Form_Load()
    'Start monitoring the system for CBT Events.
    Set objmCbtEvents = GetAllThreads.CbtEvents
End Sub

Private Sub LogAction(ByVal sAction As String)
    'Append the latest action to the first line of the TextBox,
    'so that newest actions appear first, oldest last.
    txtmLog.Text = sAction & vbCrLf & txtmLog.Text
End Sub

Private Sub Form_Unload(Cancel As Integer)
    'Need to set our object for receiving CBT events to Nothing
    'otherwise it will receive a DestroyWindow event for this
    'dialog - after it has been unloaded (which will result in an
    'error when the handler for the DestroyWindow event tries
    'to update a TextBox on the form).
    Set objmCbtEvents = Nothing
End Sub

Private Sub objmCbtEvents_DestroyWindow(Window As AkemiSpyLibrary.Window, Cancel As Boolean)
    LogAction "DestroyWindow" & Window.Caption
End Sub

Private Sub objmCbtEvents_MinMaxWindow(Window As AkemiSpyLibrary.Window, ByVal State As AkemiSpyLibrary.WindowStateConstants, Cancel As Boolean)
    Select Case State
        Case SW_MAXIMIZE
            LogAction "Maximize " & Window.Caption
        Case SW_MINIMIZE
            LogAction "Minimize " & Window.Caption
        Case SW_RESTORE
            LogAction "Restore " & Window.Caption
    End Select
End Sub

Private Sub objmCbtEvents_MoveSizeWindow(ByVal Window As AkemiSpyLibrary.Window, ByVal Left As Long, ByVal Top As Long, ByVal Width As Long, ByVal Height As Long)
    LogAction "Move/Size " & Window.Caption
End Sub

Private Sub objmCbtEvents_SetFocus(Window As AkemiSpyLibrary.Window, PreviousWindow As AkemiSpyLibrary.Window, Cancel As Boolean)
    LogAction "SetFocus " & Window.Caption
End Sub

Private Sub objmCbtEvents_CreateWindow(Window As AkemiSpyLibrary.Window, Style As Long, ExStyle As Long, Cancel As Boolean)
    LogAction "CreateWindow (Class=" & Window.ClassName & ")"
    If chkmDisableSolitaire1.Value And Window.ClassName = "Solitaire" Then
        'Cancel the creation of the Solitaire window.
        'I know that the ClassName of the Solitaire Window is "Solitaire",
        'from running the ListOfOpenWindows example whilst an instance
        'of Solitaire is open. The caption of the window cannot be checked
        'at this stage because the Window has not been created yet.

        'The solitaire application will interpret the failure to create a
        'window, as an "Out of Memory" error.
        Cancel = True
        LogAction "Solitaire Disabled"
        MsgBox "Sorry, you are not allowed to play Solitaire. (1)"
    End If
End Sub

Private Sub objmCbtEvents_ActivateWindow(Window As AkemiSpyLibrary.Window, Cancel As Boolean)
    LogAction "ActivateWindow " & Window.Caption
    If chkmDisableSolitaire2.Value And Window.Caption = "Solitaire" Then
        'This method of disabling Solitaire is better, because
        'it waits until Solitaire has successfully created its window,
        'so the Solitaire application will not be confused.
        'Also, by the time a window is about to be activated, its
        'caption has been set, so it is possible to block a window
        'based on either ClassName or Caption.
        Cancel = True
        SendMessage Window, WM_CLOSE, 0, 0
        MsgBox "Sorry, you are not allowed to play Solitaire (2)"
    End If
End Sub

See also: CbtEvents Property, CbtEvents Object


Control Highlighting

The following example demonstrates how to handle the SetFocus event centrally in an application. Open zip file

This project has two forms: dlgDataEntry and dlgOptions. dlgDataEntry is shown below:

fig1. dlgDataEntry

In this image, the background of the Surname field is yellow. As the user moves about the form using the tab key, or clicking on other fields, the field with the input focus is highlighted.

Most of the work is done in a class module, clsControlHighlighting. The code for this class is below:

Option Explicit

Private WithEvents objmCbtEvents As CbtEvents
Private ctlmPreviousControl As Control

Public Sub SelectText(ByVal ctl As Control)
    ctl.SelStart = 0
    ctl.SelLength = Len(ctl.Text)
End Sub

Private Sub Class_Initialize()
    Set objmCbtEvents = ThisThread.CbtEvents
End Sub

Private Sub Class_Terminate()
    Set objmCbtEvents = Nothing
End Sub

Private Sub objmCbtEvents_SetFocus(Window As AkemiSpyLibrary.Window,
  PreviousWindow As AkemiSpyLibrary.Window, Cancel As Boolean)
    Dim ctlActiveControl As Control

    'Find out which control is active.
    'Note that Screen.ActiveControl will return the previously
    'active control (which corresponds to PreviousWindow).  This is
    'because the SetFocus event handler is called prior to the event
    'being processed by VB.
    Set ctlActiveControl = FindControlFromWindow(Screen.ActiveForm, Window)

    If TypeName(ctlmPreviousControl) = "TextBox" Then
        ctlmPreviousControl.BackColor = vbWindowBackground
    End If

    If TypeName(ctlActiveControl) = "TextBox" Then
        ctlActiveControl.BackColor = &HC0FFFF
        SelectText ctlActiveControl
    End If

    Set ctlmPreviousControl = ctlActiveControl
End Sub

Private Function FindControlFromWindow(ByRef frm As Form,
ByRef Window As AkemiSpyLibrary.Window) As Control
    'Return a reference to the control which corresponds to
    'the Window.
    Dim ctl As Control

    On Error Resume Next

    For Each ctl In frm.Controls
        'The following line will raise an error if the control does not
        'have an hWnd property.
        If ctl.hWnd = Window.hWnd Then
            Set FindControlFromWindow = ctl
            Exit Function
        End If
    Next ctl

    Set FindControlFromWindow = Nothing
End Function

The application only ever creates one instance of clsControlHighlighting. This object in turn retrieves a CbtEvents object during its Initialize event. objmCbtEvents triggers a SetFocus event whenever the input focus moves from one control to another.

In this example, the CbtEvents object is retrieved using ThisThread.CbtEvents which means that it will only raise events triggered from within the application.

The project's main form is dlgDataEntry. An instance of clsControlHighlighting is created during the form's load event. The highlighting object remains active for the life-time of dlgDataEntry, even when another form is opened.

Option Explicit

'There is only one objmControlHighlighting object.
'Since dlgDataEntry is the main form for the project,
'the instance of clsControlHighlighting which
'is created in the form's load event will have the same
'life-time as the application.
Private objmControlHighlighting As clsControlHighlighting

Private Sub btnmCancel_Click()
   Unload Me
End Sub

Private Sub btnmOK_Click()
   Unload Me
End Sub

Private Sub btnmOptions_Click()
   dlgOptions.ShowvbModal
End Sub

Private Sub Form_Activate()
    'The following two lines force a SetFocus event when
    'the form is first opened so that txtmSurname will be
    'highlighted before the user has interacted with the
    'form.
    txtmGivenNames.SetFocus
    txtmSurname.SetFocus
End Sub

Private Sub Form_Load()
    Set objmControlHighlighting = New clsControlHighlighting
End Sub

Clicking on the "Options" button will bring up a second form, dlgOptions:

dlgOptions

The code for dlgOptions is below:

Option Explicit

Private Sub btnmCancel_Click()
   Unload Me
End Sub

Private Sub btnmOK_Click()
   Unload Me
End Sub

Private Sub Form_Activate()
    'The following two lines force a SetFocus event when
    'the form is first opened so that txtmOption1 will be
    'highlighted before the user has interacted with the
    'form.
    txtmOption2.SetFocus
    txtmOption1.SetFocus
End Sub

See also: CbtEvents Class Reference


Trapping mouse events

The following example demonstrates how to use Akemi Spy Library to trap Mouse events in another application.

To create this example from scratch, create a standard exe project with one form. Open zip file

The form has the following controls:

lblmDescription | Label. Displays a description of the application.
lblmMousePositionLabel | Label. Displays the words "Mouse Position"
lblmMousePosition | Label. Displays the coordinates of the mouse whenever it is over a Notepad window (or Notepad generated dialog). Coordinates are relative to the top-left corner of the window or control that the mouse is over.
lblmControlTextLabel | Label. Displays the words "Control Text"
lblmControlText | Label. Displays the caption of any control that the mouse is over, as long as it is a control owned by the instance of Notepad being monitored.
lblmButtonClickedLabel | Label. Displays the words "Button Clicked"
lblmButtonClicked | Label. Displays the caption of the last button to be clicked (the last button owned by the instance of Notepad being monitored, that is.
btnmStartNotepad | CommandButton. Starts an instance of Notepad.exe or switches to an already open instance.

The code for this form is below:

Option Explicit

'ShellExecute API is used to launch Notepad.
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
'Constant used in call to ShellExecute
Private Const SW_SHOWNORMAL = 1

'SetActiveWindow API is used to activate an already opened
'instance of Notepad.
Private Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Long) As Long

'AttachThreadInput API is necessary in order for
'SetActiveWindow API to work.
Private Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Long, ByVal idAttachTo As Long, ByVal fAttach As Long) As Long

'Object to receive mouse events must be declared at
'class or form level.
Private WithEvents objmMouseEvents As MouseEvents

'Number of seconds to wait before giving up
'in Function WaitForWindow
Private lmSeconds As Long

Private Sub btnmStartNotepad_Click()
    Dim objNotepadWindow As Window

    'Find the first instance of Notepad to come to hand.
    'This example does not account for the possibility of multiple
    'instances of Notepad being open - only the first one to be
    'found will be monitored.
    Set objNotepadWindow = GetTopLevelWindows.FindWindow("* Notepad", "Notepad")

    'If there is no instance of Notepad already running, then
    'start one.
    If objNotepadWindow Is Nothing Then
        If ShellExecute(Me.hwnd, "Open", "Notepad.exe", "", "", SW_SHOWNORMAL) <= 32 Then
            MsgBox "Unable to start Notepad."
            Exit Sub
        Else
            Set objNotepadWindow = WaitForWindow("* Notepad", "Notepad")
            If objNotepadWindow Is Nothing Then
                MsgBox "Timeout expired, waiting for Notepad to open."
            Exit Sub
            End If
        End If
    Else
        'There is already an instance of Notepad running,
        'so switch to that instance.
        AttachThreadInput App.ThreadID, objNotepadWindow.Thread, True
        SetActiveWindow objNotepadWindow
    End If

    'Start monitoring Mouse Events
    Set objmMouseEvents = objNotepadWindow.Thread.MouseEvents
End Sub

Private Function WaitForWindow(ByVal sCaption As String, ByVal sClassName As String) As Window
    Dim objWindow As Window

    'Wait up to 5 seconds for the specified window to be opened.
    lmSeconds = 5
    While objWindow Is Nothing And lmSeconds > 0
        'DoEvents gives Timer chance to fire its event.
        DoEvents
        Set objWindow = GetTopLevelWindows.FindWindow(sCaption, sClassName)
    Wend

    'If the specified window was not opened, then the return
    'value will be Nothing.
    Set WaitForWindow = objWindow
End Function

Private Sub tmrm_Timer()
    lmSeconds = lmSeconds - 1
End Sub

Private Sub objmMouseEvents_MouseEnter(Window As AkemiSpyLibrary.Window)
    'As the mouse pointer enters a window, display
    'the window's caption.
    lblmControlText.Caption = Window.Caption
End Sub

Private Sub objmMouseEvents_MouseLeave(Window As AkemiSpyLibrary.Window)
    'As the mouse pointer leaves a window, clear the
    'control text label.
    lblmControlText.Caption = ""
End Sub

Private Sub objmMouseEvents_MouseMove(Window As AkemiSpyLibrary.Window, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long)
    'Display the mouse position. Coordinates are relative
    'to the top-left corner of the window in which the mouse is moving.
    lblmMousePosition.Caption = Format$(x) & ", " & Format$(y)
End Sub

Private Sub objmMouseEvents_Click(Window As AkemiSpyLibrary.Window, ByVal Button As MouseButtonConstants, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long)
    'If the user clicks on a control, display the caption of that control.
    'Note that if the caption contains an ampersand (&), the letter
    'after the ampersand will be underlined to indicate a keyboard
    'accelerator.
    lblmButtonClicked.Caption = Window.Caption
End Sub

See also: KeyboardEvents Object, MouseEvents Property


Appendix 1: WithEvents

Appendix: WithEvents

To handle the events raised by an event source (such as a KeyboardEvents object), declare a variable using the keyword WithEvents.

Private WithEvents objmKeyboardEvents As KeyboardEvents

This will put objmKeyboardEvents in the left drop-down list of your code window, and events raised by objmKeyboardEvents can be selected from the right drop-down list, just like a visual control placed on the form's designer window.

For objmKeyboardEvents to actually raise any events, it must be explicity created at run-time.

Eg:

Private Sub Form_Load()
    'Trap keyboard events from all threads.
    Set objmKeyboardEvents = GetAllThreads.KeyboardEvents
End Sub


Glossary

class name | Name of a window class. Window classes are used by Microsoft Windows when creating windows with similar appearance and functionality. Applications can also define their own window classes.
hWnd | A handle assigned to each window by the operating system.
child window | A window that has the WS_CHILD style. MDI child windows and ActiveX controls are examples of child windows.
top-level window | A window that has no parent window. Typical VB forms, (with MDIChild=false) are top-level windows.
window A (usually rectangular) area managed by the operating system. A window can be a top-level window, an ActiveX control, or other type of visual component.

In addition, invisible windows are used to queue and process messages. Akemi Spy Library uses an invisible window to receive window messages before turning them into events.


Akemi Spy Library Classes

Classes

See also: Event Index, Method and Functions Index, Properties Index

Akemi Spy Library includes the following classes:

AkemiSpyLibrary.dll
CbtEvents
IdleEvents
KeyboardEvents
MouseEvents
Thread
Window
Windows
WindowSpy


CbtEvents Object

See also: CbtEvents property

A CbtEvents object encapsulates the functionality of a Cbt Hook.

Events:

ActivateWindow
CreateWindow
DestroyWindow
MinMaxWindow
MoveSizeWindow
SetFocus

Examples:

When the user changes windows

Control Highlighting


IdleEvents Object

See also: IdleEvents property

An IdleEvents object encapsulates the functionality of a FOREGROUNDIDLE Hook.

Events:

Idle


KeyboardEvents Object

See also: KeyboardEvents property

An KeyboardEvents object encapsulates the functionality of a KEYBOARD Hook.

Events:

KeyDown
KeyUp

Example:

Trapping keyboard events


MouseEvents Object

See also: MouseEvents property

A MouseEvents object encapsulates the functionality of a MOUSE Hook.

Events:

Click
DoubleClick
MouseDown
MouseEnter
MouseLeave
MouseMove
MouseUp

Example:

Trapping mouse events


Thread Object

See also: Thread property, ThisThread function, GetAllThreads function, WrapThread function

A Thread object encapsulates a Windows thread.

Properties:

CbtEvents
IdleEvents
KeyboardEvents
MouseEvents
ThreadID
Windows

Home Copyright and Disclaimer


Window Object

See also: Windows collection object

A Window object encapsulates a Window Handle (or hWnd).

Properties:

Caption
ChildWindows
ClassName
ClientHeight
ClientWidth
hWnd
Parent
Text
Thread
TopLevelParent
Visible
WindowHeight
WindowLeft
WindowTop
WindowWidth

Home Copyright and Disclaimer


Windows Collection Object

Windows Collection

See also: Window object, GetTopLevelWindows function, Windows property, ChildWindows property

A Windows collection is a collection of Window objects obtained by calling the global function GetTopLevelWindows, or by getting the Windows property of a Thread object, or by getting the ChildWindows property of a Window object, or by calling the global function GetChildWindows.

Properties:

Count
Item

Methods:

FindNextWindow
FindWindow
FindWindowByHwnd
Refresh

Home Copyright and Disclaimer


WindowSpy Object

See also:

A global object which can be used to get other useful objects.

Methods:

GetAllThreads
GetChildWindows
GetTopLevelWindows
ThisThread
WrapThread
WrapWindow

Remarks:

Because WindowSpy is a global object, each of the methods above can be called without reference to a specific WindowSpy object. Akemi Spy Library creates an instance of the WindowSpy object on initialization.

Example:

To retrieve all the keyboard events triggered by all applications running on the system, declare a class or form level variable to hold the KeyboardEvents object, and retrieve the KeyboardEvents object from GetAllThreads:

Option Explicit

Private WithEvents objmKeyboardEvents As KeyboardEvents

Private Sub Form_Load()
    Set objmKeyboardEvents = GetAllThreads.KeyboardEvents
End Sub


Event Index

See also: Method and Functions Index, Properties Index, Classes

ActivateWindow
 Click
 CreateWindow
 DestroyWindow
 DoubleClick
 Idle
 KeyDown
 KeyUp
 MinMaxWindow
 MouseDown
 MouseEnter
 MouseLeave
 MouseMove
 MouseUp
 MoveSizeWindow
 SetFocus


ActivateWindow Event

Applies to: CbtEvents object
See also: Window object

Occurs when a top-level window is about to become active.

Syntax:

Private Sub object_ActivateWindow(ByRef Window As Window, ByRef Cancel As Boolean)

The ActivateWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to become active.
Cancel | A boolean value that determines whether Window will become active. Setting Cancel to True prevents the window from becoming active.

Example:

When the user changes windows


Click Event

Applies to: MouseEvents
See also: Window object, MouseDown event, MouseUp event

Occurs when the user presses and releases a mouse button within the same window.

Syntax:

Public Event Click(ByRef Window As Window, ByVal Button As MouseButtonConstants, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long)

The Click event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window in which the mouse button was clicked.
Button | A value indicating which button was clicked. Can be one of vbLeftButton, vbMiddleButton, vbRightButton.
Shift | A boolean value indicating the state of the shift button. A vale of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl button. A vale of True indicates that the ctrl key is down.
x | The x coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
y | The y coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.

Remarks:

The Click event cannot be cancelled directly, because it is not a low-level event. To prevent a Click event, process and cancel the MouseDown event

Example:

Trapping mouse events


CreateWindow Event

Applies to: CbtEvents object
See also: Window object

Occurs when a window is about to be created.

Syntax:

Public Event CreateWindow(ByRef Window As Window, ByRef Style As Long, ByRef ExStyle As Long, ByRef Cancel As Boolean)

The CreateWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to be created.
Style | The window's style. Consult the Windows Platform SDK documentation for acceptable values for Style.
ExStyle | The window's extended style. Consult the Windows Platform SDK documentation for acceptable values for ExStyle.
Cancel | A boolean value that determines whether Window will be created. Setting Cancel to True prevents the window from being created.

Remarks:

Cancelling the creation of a window, will be interpreted by most applications as an "Out of Memory" error, including applications created using Visual Basic.

Example:

When the user changes windows


DestroyWindow Event

Applies to: CbtEvents object
See also: Window object

Occurs when a window is about to be destroyed.

Syntax:

Public Event DestroyWindow(ByRef Window As Window, ByRef Cancel As Boolean)

The DestroyWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to be created.
Cancel | A boolean value that determines whether Window will be destroyed. Setting Cancel to True prevents the window from being destroyed. This may produce unpredictable behaviour.


DoubleClick Event

Applies to: MouseEvents
See also: Window object

Occurs when a window is about to receive a DoubleClick event.

Syntax:

Public Event DoubleClick(ByRef Window As Window, ByVal Button As MouseButtonConstants, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long, Byref Cancel As Boolean)

The DoubleClick event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window in which the mouse button was double clicked.
Button | A value indicating which button was double clicked. Can be one of vbLeftButton, vbMiddleButton, vbRightButton.
Shift | A boolean value indicating the state of the shift button. A vale of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl button. A vale of True indicates that the ctrl key is down.
x | The x coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
y | The y coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
Cancel | A boolean value that determines whether Window will receive the DoubleClick event. Setting Cancel to True prevents the event from being passed on.


Idle Event

Applies to: IdleEvents object
See also: Window object

Occurs when a thread becomes idle, or when the system becomes idle, depending on how the IdleEvents object was obtained.

Syntax:

Private Sub object_Idle()

The Idle event syntax has these parts:

Part | Description
object | The name of an IdleEvents object. NB: object must be declared using WithEvents.

Remarks:

Use the idle event to perform background processing. The event handler for this event should be written in such a way as to return control to the system as soon as possible.

For example, if 1000 records need to be processed, then process one record in response to each Idle event. If the system is still idle (or becomes idle again), then the event will be triggered again.


KeyDown Event

Applies to: KeyboardEvents object
See also: KeyUp event

Occurs when a key is pressed. The key press may be the result of the user physically pressing the key, or may result from the keyboard's auto-repeat feature.

Syntax:

Public Event KeyDown(ByRef Window As Window, ByVal KeyCode As Integer, ByVal AutoRepeat As Boolean, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal Alt As Boolean, ByRef Cancel As Boolean)

The KeyDown event syntax has these parts:

Part | Description
object | The name of a KeyboardEvents object. NB: object must be declared using WithEvents.
Window | A Window object representing the window which has the input focus.
KeyCode | An integer value representing the ASCII code of the key being pressed, or a virtual key code if the key does not represent an ASCII character.
AutoRepeat | A boolean value indicating whether the event is the result of the keyboard's auto-repeat feature.
Shift | A boolean value indicating the state of the shift key. A value of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl key. A value of True indicates that the ctrl key is down.
Alt | A boolean value indicating the state of the alt key. A value of True indicates that the alt key is down.
Cancel | A boolean value that determines whether the window which currently has keyboard focus will receive this event. Setting Cancel to True prevents the key press from being processed.

Remarks:

The KeyDown event is triggered prior to processing by the application in which the key was pressed.

Example:

Trapping keyboard events


KeyUp Event

Applies to: KeyboardEvents object
See also: KeyDown event

Occurs when a key is released.

Syntax:

Public Event KeyUp(ByVal KeyCode As Integer, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal Alt As Boolean, ByRef Cancel As Boolean)

The KeyUp event syntax has these parts:

Part | Description
object | The name of a KeyboardEvents object. NB: object must be declared using WithEvents.
Window | A Window object representing the window which has the input focus.
KeyCode | An integer value representing the ASCII code of the key being pressed, or a virtual key code if the key does not represent an ASCII character.
Shift | A boolean value indicating the state of the shift key. A value of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl key. A value of True indicates that the ctrl key is down.
Alt | A boolean value indicating the state of the alt key. A value of True indicates that the alt key is down.
Cancel | A boolean value that determines whether the window which currently has keyboard focus will receive this event. Setting Cancel to True prevents the key press from being processed.

Remarks:

The KeyUp event occurs after the KeyDown event. Although setting Cancel = True will prevent the KeyUp event from being processed, it is better to do this in the KeyDown event, as cancelling the KeyDown event will cancel both the KeyDown and KeyUp events.

Example:

Trapping Keyboard Events


MinMaxWindow Event

Applies to: CbtEvents object
See also: Window object

Occurs when a window is about to be minimized or maximized.

Syntax:

Public Event CreateWindow(ByRef Window As Window, ByVal State As WindowStateConstants, ByRef Cancel As Boolean)

The CreateWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to be minimized or maximized.
State | The operation which is about to occur. Can be any one of the following values: SW_MAXIMIZE - the window is about to be maximized. SW_MINIMIZE - the window is about to be minimized.
Cancel | A boolean value that determines whether the minimize or maximize will proceed. Setting Cancel to True prevents the minimization or maximization from occurring.


MouseDown Event

Applies to: MouseEvents
See also: Window object

Occurs when a window is about to receive a MouseDown event.

Syntax:

Public Event MouseDown(ByRef Window As Window, ByVal Button As MouseButtonConstants, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long, Byref Cancel As Boolean)

The MouseDown event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window in which the mouse button was pressed.
Button | A value indicating which button was pressed. Can be one of vbLeftButton, vbMiddleButton, vbRightButton.
Shift | A boolean value indicating the state of the shift button. A vale of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl button. A vale of True indicates that the ctrl key is down.
x | The x coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
y | The y coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
Cancel | A boolean value that determines whether Window will receive the MouseDown event. Setting Cancel to True prevents the event from being passed on.

Remarks:

Note that a Click event is the result of a MouseDown event followed by a MouseUp event within the same window. Cancelling the MouseDown event will cancel the Click event.

Example:

Trapping mouse events


MouseEnter Event

Applies to: MouseEvents
See also: MouseLeave event, Window object

Occurs when the mouse pointer is about to move into the visible region of a window.

Syntax:

Public Event MouseEnter(ByRef Window As Window)

The MouseEnter event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window into which the mouse pointer is about to move.

Example:

Trapping mouse events


MouseLeave Event

Applies to: MouseEvents
See also: MouseEnter event, Window object

Occurs when the mouse pointer is about to leave the visible region of a window.

Syntax:

Public Event MouseLeave(ByRef Window As Window)

The MouseLeave event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window from which the mouse pointer is about to leave.

Example:

Trapping mouse events


MouseMove Event

Applies to: MouseEvents
See also: Window object

Occurs when a window is about to receive a MouseMove event.

Syntax:

Public Event MouseMove(ByRef Window As Window, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long)

The MouseMove event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window in which the mouse is moving.
Shift | A boolean value indicating the state of the shift button. A vale of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl button. A vale of True indicates that the ctrl key is down.
x | The x coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
y | The y coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.

Example:

Trapping mouse events


MouseUp Event

Applies to: MouseEvents
See also: Window object

Occurs when a window is about to receive a MouseUp event.

Syntax:

Public Event MouseUp(ByRef Window As Window, ByVal Button As MouseButtonConstants, ByVal Shift As Boolean, ByVal Control As Boolean, ByVal x As Long, ByVal y As Long, Byref Cancel As Boolean)

The MouseUp event syntax has these parts:

Part | Description
object | The name of a MouseEvents object. NB: object must be declared using WithEvents.
Window | The window in which the mouse button was released.
Button | A value indicating which button was released. Can be one of vbLeftButton, vbMiddleButton, vbRightButton.
Shift | A boolean value indicating the state of the shift button. A vale of True indicates that the shift key is down.
Control | A boolean value indicating the state of the ctrl button. A vale of True indicates that the ctrl key is down.
x | The x coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
y | The y coordinate of the mouse pointer, in client coordinates (pixels). May be negative, if the mouse is over the border or caption of a top-level or mdi child window.
Cancel | A boolean value that determines whether Window will receive the MouseUp event. Setting Cancel to True prevents the event from being passed on. This parameter is only included for the sake of completeness. It is more useful to cancel a MouseDown event.

Example:

Trapping mouse events


MoveSizeWindow Event

Applies to: CbtEvents object
See also: Window object

Occurs after a window has been moved or resized.

Syntax:

Public Event MoveSizeWindow(ByVal Window As Window, ByVal Left As Long, ByVal Top As Long, ByVal Width As Long, ByVal Height As Long)

The CreateWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to be created.
Left | The distance (in pixels) from the left edge of the screen to the window.
Top | The distance (in pixels) from the top of the screen to the window.
Width | The width (in pixels) of the window.
Height | The height (in pixels) of the window.


SetFocus Event

Applies to: CbtEvents object
See also: Window object

Occurs when the keyboard focus is about to move from one window to another.

Syntax:

Public Event SetFocus(ByRef Window As Window, ByRef PreviousWindow As Window, ByRef Cancel As Boolean)

The CreateWindow event syntax has these parts:

Part | Description
object | The name of a CbtEvents object. NB: object must be declared using WithEvents.
Window | The window about to receive focus.
PreviousWindow | The window about to lose focus.
Cancel | A boolean value that determines whether Window will receive the keyboard focus. Setting Cancel to True will prevent Window from receiving the keyboard focus.

Remarks:

If the keyboard focus is within a Visual Basic application, then the SetFocus event will be triggered prior to the VB defined GotFocus event of the control gaining the focus.

Consequently, Screen.ActiveControl will contain a reference to the previously active control.

Example:

Control Highlighting


Properties Index

See also: Event Index, Method and Functions Index, Classes

Caption
 CbtEvents
 ChildWindows
 ClassName
 ClientHeight
 ClientWidth
 CbtEvents
 hWnd
 IdleEvents
 Item
 KeyboardEvents
 MouseEvents
 Parent
 Text
 Thread
 ThreadID
 TopLevelParent
 Visible
 WindowHeight
 WindowLeft
 Windows
 WindowTop
 WindowWidth


Caption Property

Applies to: Window object
See also: Text Property

Returns or sets the caption associated with a window.

Syntax:

object.Caption

The Caption syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

Under MicrosoftWindows, any window can have an associated text string. For top-level windows or MdiChild windows, this string contains the caption displayed in the window's title bar. For other windows, such as command buttons and other controls, the associated text is the text displayed in the control.

The Caption property and Text property are linked to the same underlying window property, so that setting the Caption property is equivalent to setting the Text property, and vice versa.

Example:

Displaying a list of open windows
When the user changes windows
 Trapping mouse events

Home Copyright and Disclaimer


CbtEvents Property

Applies to: Thread object
See also: CbtEvents object

read-only

Returns a CbtEvents object for the thread.

Syntax:

object.CbtEvents

The CbtEvents syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the object returned by the CbtEvents property will receive events relating to all threads on the system (equivalent to setting a global hook).

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the object returned by the CbtEvents property will receive events relating only to a single thread.

Example:

When the user changes windows


ChildWindows Property

Applies to: Window object
See also: Parent property, TopLevelParent property, Windows collection

read-only

Returns a collection containing all of the child windows of a given window.

Syntax:

object.ChildWindows

The ChildWindows syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

For MDI windows, the collection returned by the ChildWindows property will include all of the window's MDI child windows. However the collection may also contain additional windows - if the MDI window contains controls of its own.


ClassName Property

Applies to: Window object
See also:

read-only

Returns the window's class name.

Syntax:

object.ClassName

The ClassName syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

Microsoft Windows uses class names when creating windows, to create windows with similar features and behaviour. Visual Basic forms are created with the class name "ThunderFormDC" in debug mode, and with the class name "ThunderRT6FormDC" when compiled.

Example:

Displaying a list of open windows
When the user changes windows

Home Copyright and Disclaimer


ClientHeight Property

Applies to: Window object
See also: ClientWidth property, WindowHeight property, WindowWidth property

read-only

Returns the height (in pixels) of a window's client area.

Syntax:

object.ClientHeight

The ClientHeight syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

For top-level windows, and Mdi Child windows, the client area is the main workspace of a window excluding the title bar and border. For most other windows, the client area is the whole window.

The ClientHeight property cannot be changed directly. To change the size of the client area, change the size of the whole window using WindowWidth and WindowHeight.

To make the client area a specific height, subtract the height of the client area from the height of the window to get the total height of the non-client area (height of the title bar and menu plus 2 times the border width). Then set the height of the window to that value plus the desired client height.


ClientWidth Property

Applies to: Window object
See also: ClientHeight property, WindowHeight property, WindowWidth property

read-only

Returns the height (in pixels) of a window's client area.

Syntax:

object.ClientWidth

The ClientWidth syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

For top-level windows, and Mdi Child windows, the client area is the main workspace of a window excluding the title bar and border. For most other windows, the client area is the whole window.

The ClientWidth property cannot be changed directly. To change the size of the client area, change the size of the whole window using WindowWidth and WindowHeight.

To make the client area a specific width, subtract the width of the client area from the width of the window to get the total width of the non-client area (2 times the border width). Then set the width of the window to that value plus the desired client width.


Count Property

Applies to: Windows collection
See also: Refresh method

read-only

Returns the number of windows in the collection.

Syntax:

object.Count

The Count syntax has these parts:

Part | Description
object | The name of a Windows collection.

Remarks:

The Count property returns the number of windows in the collection at the time it was created or last refreshed. To get an up to date count of the number of windows in the system, first call Refresh.


hWnd Property

Applies to: Window object
See also:

read-only

Returns the window's handle, as assigned by the operating system.

Syntax:

object.hWnd

The hWnd syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

If a window is closed, a Window object attached to that window is not automatically destroyed. It is possible to check whether a Window has been closed by checking its hWnd property. This property is set to zero when the window is closed.

The hWnd property can be used when calling Win32 API functions which take an hWnd as a parameter. As this is the default property for a Window object, it is not necessary to reference the hWnd property explicitly.

Therefore, the following to lines of code (which use the Win32 API SetActiveWindow) are equivalent:

SetActiveWindow objMyWindow
SetActiveWindow objMyWindow.hWnd

It is possible for more than one Window object to share the same hWnd. For example, each call to WrapWindow will return a distinct Window object instance, even though each instance will be attached to the same hWnd. Therefore, to check whether two Window objects relate to the same actual window - check whether the hWnd property is the same for both objects.

Therefore, the following code is inadvisable

If MyWindow Is MyOtherWindow Then
  'Perform some action
End If

The following is preferable:

If MyWindow.hWnd = MyOtherWindow.hWnd Then
  'Perform some action
End If

Example:

The FindControlFromWindow function, in the "Control Highlighting" example, iterates through all of the controls on a form, to find which one corresponds to a Window object.


IdleEvents Property

Applies to: Thread object
See also: IdleEvents object

read-only

Returns an IdleEvents object for the thread.

Syntax:

object.IdleEvents

The IdleEvents syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the object returned by the IdleEvents property will receive events relating to all threads on the system (equivalent to setting a global hook).

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the object returned by the IdleEvents property will receive events relating only to a single thread.


Item Property

Applies to: Windows collection
See also: Count property

read-only

Returns a specific window in the collection.

Syntax:

object.Item(index)

The Count syntax has these parts:

Part | Description
object | The name of a Windows collection.
index | An integer indicating which element of the collection is to be returned. index must be greater or equal to 1, and less than or equal to the Count property of the collection.

Remarks:

The item property is the default property for a Windows collection. Therefore, the following two lines of code are equivalent:

Set objWindow = GetTopLevelWindows.Item(1)
Set objWindow = GetTopLevelWindows(1)


KeyboardEvents Property

Applies to: Thread object
See also: KeyboardEvents object

read-only

Returns a KeyboardEvents object for the thread.

Syntax:

object.KeyboardEvents

The KeyboardEvents syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the object returned by the KeyboardEvents property will receive events relating to all threads on the system (equivalent to setting a global hook).

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the object returned by the KeyboardEvents property will receive events relating only to a single thread.

Example:

Trapping keyboard events


MouseEvents Property

Applies to: Thread object
See also: MouseEvents object

read-only

Returns an MouseEvents object for the thread.

Syntax:

object.MouseEvents

The MouseEvents syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the object returned by the MouseEvents property will receive events relating to all threads on the system (equivalent to setting a global hook).

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the object returned by the MouseEvents property will receive events relating only to a single thread.

Example:

Trapping mouse events


Parent Property

Applies to: Window object
See also: Parent property, ChildWindows property

read-only

Returns a Window object corresponding to the parent window of another window.

Syntax:

object.Parent

The Parent syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

For top-level windows the Parent property is nothing. This fact can be used to determine whether a given Window is a top-level window.

The Parent property will not always be a top-level window. For example, in a group of option buttons in a frame, each option button has a window and the frame is also a window. The parent window for each of the option buttons is the frame, and the frame's parent window might be a top-level window, or may be another control container such as a tabbed dialog control.


Text Property

Applies to: Window object
See also: Caption Property

Returns or sets the text associated with a window.

Syntax:

object.Text

The Text syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

Under Microsoft Windows, any window can have an associated text string. For top-level windows or MdiChild windows, this string contains the caption displayed in the window's title bar. For other windows, such as command buttons and other controls, the associated text is the text displayed in the control.

The Caption property and Text property are linked to the same underlying window property, so that setting the Caption property is equivalent to setting the Text property, and vice versa.


Thread Property

Applies to: Window object
See also: Thread object

read-only

Returns a Thread object corresponding to the thread which owns the window.

Syntax:

object.Thread

The Thread syntax has these parts:

Part | Description
object | The name of a Window object.


ThreadID Property

Applies to: Thread object
See also:

Returns the Windows assigned ThreadID for the thread.

Syntax:

object.ThreadID

The ThreadID syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the value returned by the ThreadID property will be 0.

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the value returned by the ThreadID property will be the Windows assigned ThreadID for the thread.

The ThreadID is used by Windows API functions to manipulate threads. There is no need to reference the ThreadID property directly when calling Windows API functions which take a ThreadID as a parameter, as the ThreadID is the default property of the thread object.


TopLevelParent Property

Applies to: Window object
See also: Parent property, ChildWindows property

read-only

Returns a Window object corresponding to the top-level parent window of another window.

Syntax:

object.Parent

The Parent syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

A window's parent will not always be a top-level window. For example, in a group of option buttons in a frame, each option button has a window and the frame is also a window. The parent window for each of the option buttons is the frame, and the frame's parent window might be a top-level window, or may be another control container such as a tabbed dialog control.

A window's top-level parent, is obtained by checking whether it's parent is a top-level window, and if it isn't, checking whether it's parent's parent is a top-level window, and so on, until a top-level window is reached.


Visible Property

Applies to: Window object
See also:

Returns or sets a boolean value indicating whether a window is visible.

Syntax:

object.Visible

The Visible syntax has these parts:

Part | Description
object | The name of a Window object.


WindowHeight Property

Applies to: Window object
See also: WindowWidth, WindowLeft, WindowTop, ClientWidth, ClientHeight

Returns or sets the height (in pixels) of a window.

Syntax:

object.WindowHeight

The WindowHeight syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

A window's height, includes the height of the window's client area, plus 2 times the window's border width (if the window has a border), plus the height of the window's caption bar (if the window has a caption) plus the height of the window's menu (if the window has a menu).


WindowLeft Property

Applies to: Window object
See also: WindowHeight, WindowWidth, WindowTop, ClientWidth, ClientHeight

Returns or sets the distance (in pixels) from the left edge of the screen to the window.

Syntax:

object.WindowLeft

The WindowLeft syntax has these parts:

Part | Description
object | The name of a Window object.


Windows Property

Applies to: Thread object
See also: Windows collection

Returns a collection containing all of the top-level windows which are owned by a thread.

Syntax:

object.Windows

The Windows syntax has these parts:

Part | Description
object | The name of a Thread object.

Remarks:

If the Thread object is the return value of GetAllThreads, then the collection returned by the Windows property will contain the same windows as the collection returned by GetTopLevelWindows.

If the Thread object is the Thread property of a Window object, or the return value of ThisThread or WrapThread, then the collection returned by the Windows property will contain the top-level windows which are owned by the thread.


WindowTop Property

Applies to: Window object
See also: WindowHeight, WindowWidth, WindowLeft, ClientWidth, ClientHeight

Returns or sets the distance (in pixels) from the top edge of the screen to the window.

Syntax:

object.WindowTop

The WindowTop syntax has these parts:

Part | Description
object | The name of a Window object.


WindowWidth Property

Applies to: Window object
See also: WindowHeight, WindowTop, WindowLeft, ClientWidth, ClientHeight

Returns or sets the distance (in pixels) from the top edge of the screen to the window.

Syntax:

object.WindowWidth

The WindowWidth syntax has these parts:

Part | Description
object | The name of a Window object.

Remarks:

A window's width includes the width of the window's client area, plus 2 times the window's border width (if the window has a border).


Method and Functions Index

See also: Event Index, Properties Index, Classes


FindNextWindow Method

Applies to: Windows collection
See also: FindWindow method

Finds the next window in a collection matching the specified criteria, starting from a particular window in the collection.

Syntax:

Set objWindow = object.FindNextWindow(FromWindow, Caption, ClassName)

The FindNextWindow method syntax has these parts:

Part | Description
objWindow | An object variable to hold the window you want to find.
object | The name of a Windows collection.
FromWindow | The window from which the search will begin. FromWindow must be an element of the collection being searched. Typically, FromWindow will have been obtained from a previous call to FindWindow. The window specified by FromWindow is not included in the search.
Caption | A caption to search for. A search can be performed on partial captions using the asterisk * as a wildcard.
ClassName | Optional. A class name to search for.


FindWindow Method

Applies to: Windows collection
See also: FindNextWindow method

Finds the first window in a collection matching the specified criteria.

Syntax:

Set objWindow = object.FindNextWindow(Caption, ClassName)

The FindWindow method syntax has these parts:

Part | Description
objWindow | An object variable to hold the window you want to find.
object | The name of a Windows collection.
Caption | A caption to search for. A search can be performed on partial captions using the asterisk * as a wildcard.
ClassName | Optional. A class name to search for.

Examples:

Trapping keyboard events

Trapping mouse events


FindWindowByHwnd Method

Applies to: Windows collection
See also: FindWindow method

Finds the window in a collection corresponding to a specific window handle.

Syntax:

Set objWindow = object.FindWindowByHwnd(hWnd)

The FindNextWindow method syntax has these parts:

Part | Description
objWindow | An object variable to hold the window you want to find.
object | The name of a Windows collection.
hWnd | The window handle of the window being searched for.

Example:

Displaying a list of open windows


GetAllThreads Method

Applies to: WindowSpy
See also: GetTopLevelWindows method, Thread object

Returns a Thread object which represents all the threads on the system.

Syntax:

Set objAllThreads = GetAllThreads

The GetAllThreads method syntax has these parts:

Part | Description
objAllThreads | A Thread object which will store the value returned by GetAllThreads

Remarks:

The Thread object returned by GetAllThreads is a special case of the Thread object, which is equivalent to calling WrapThread with a ThreadID of 0.

GetAllThreads returns the same object each time it is called, so there is no need to store the return value.

Note that this is a different behaviour from GetTopLevelWindows which returns a collection.

Examples:

Trapping keyboard events

When the user changes windows


GetChildWindows Method

Applies to: WindowSpy
See also: GetTopLevelWindows method, Windows collection object

Returns a collection of child windows given a specified parent window's hWnd.

Syntax:

Set objChildWindows = GetChildWindows

The GetChildWindows method syntax has these parts:

Part | Description
objChildWindows | A Windows collection object which will store the value returned by GetChildWindows


GetTopLevelWindows Method

Applies to: WindowSpy
See also: GetTopLevelWindows method, Windows collection object

Returns a collection of all the currently open top-level windows, including invisible windows.

Syntax:

Set objWindows = GetChildWindows

The GetChildWindows method syntax has these parts:

Part | Description
objWindows | A Windows collection object which will store the value returned by GetTopLevelWindows

Remarks:

The collection returned by GetTopLevelWindows is a "snapshot" of the currently open top-level windows. GetTopLevelWindows actually returns the same object each time it is called, but calls Refresh on that object before returning it.

Example:

Displaying a list of open windows


Refresh Method

Applies to: Windows collection
See also: FindWindow method

Refreshes the elements of a Windows collection.

Syntax:

object.Refresh

The Refresh method syntax has these parts:

Part | Description
object | The name of a Windows collection.

Remarks:

Calling Refresh removes those windows from a collection which have been destroyed since the last call to Refresh, and adds to the collection any windows which have been created which match the criteria used to create the collection.

If the collection was returned from a call to GetTopLevelWindows, calling Refresh will update the collection so that it contains an up to date view of all of the currently open top-level windows.

If the collection was returned by examining the ChildWindows property of a Window object, calling Refresh will update the collection so that it contains an up to date view of all of the child windows of that Window.

If the collection was returned by examining the Windows property of a Thread object, calling Refresh will update the collection so that it contains an up to date view of all of the windows belonging to that Thread.


ThisThread Method

Applies to: WindowSpy
See also: GetAllThreads method, Thread object, WrapThread

Returns a Thread object which represents the application's main thread.

Syntax:

Set objThread = ThisThread

The ThisThread method syntax has these parts:

Part | Description
objThread | A Thread object which will store the value returned by ThisThread

Remarks:

Calling ThisThread is equivalent to calling WrapThread(App.ThreadID)


WrapThread Method

Applies to: WindowSpy
See also: GetAllThreads method, Thread object, WrapThread method

Returns a Thread object which encapsulates a specific ThreadID.

Syntax:

Set objThread = WrapThread(ThreadID)

The WrapThread method syntax has these parts:

Part | Description
objThread | A Thread object which will store the value returned by WrapThread.
ThreadID | The ThreadID to be encapsulated.


WrapWindow Method

Applies to: WindowSpy
See also: GetTopLevelWindows method, Window object

Returns a Window object which encapsulates a specific hWnd.

Syntax:

Set objWindow = WrapWindow(hWnd)

The WrapWindow method syntax has these parts:

Part | Description
objWindow | A Window object which will store the value returned by WrapWindow.
hWnd | The hWnd to be encapsulated.