Solved

SetWindowsHook with GETMESSAGE attribute causes Access to crash

Posted on 2004-09-01
4
371 Views
Last Modified: 2012-06-27
Problem:

When a modal form is displayed, and the user switches to another app, the access window may become minimized.  This is not possible manualy but done through some other apps code.  By clicking on the access button on the toolbar, the app cannot be restored or maxmized except through taskmanager.

Proposed Solution:

Set a windows hook into access to intercept any message that tells access to minimize when ever the modal window is displayed.  Or try to capture the mouse click on the button in the toolbar after it hs been minimized to then send a message to access to to restore the window.

My code:

Below is the code that I have written to set the hook.  This code works when the SetWindowsHook HookID value is set to WH_CBT.  The callback function is called and every thing is fine.    I can't use the CBT message as the window has already begun to minimize and I cant cancel the action.  The problem occurs when I set the HookID to WH_GETMESSAGE.  The call back is called the first time when a message is received, but then Access will crash.

Private Declare Function SetWindowsHookEx Lib "user32" _
    Alias "SetWindowsHookExA" (ByVal idHook As Long, _
                               ByVal lpfn As Long, _
                               ByVal hmod As Long, _
                               ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function GetCurrentThreadId Lib "KERNEL32" () As Long
Private Declare Function GetModuleHandle Lib "KERNEL32" Alias _
    "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long

Private Const WH_CALLWNDPROC = 4
Private Const WH_CALLWNDPROCRET = 12
Private Const WH_CBT = 5
Private Const WH_DEBUG = 9
Private Const WH_FOREGROUNDIDLE = 11
Private Const WH_GETMESSAGE = 3
Private Const WH_HARDWARE = 8
Private Const WH_JOURNALPLAYBACK = 1
Private Const WH_JOURNALRECORD = 0
Private Const WH_KEYBOARD = 2
Private Const WH_KEYBOARD_LL = 13
Private Const WH_MAX = 11
Private Const WH_MAXHOOK = WH_MAX
Private Const WH_MIN = (-1)
Private Const WH_MINHOOK = WH_MIN
Private Const WH_MOUSE = 7
Private Const WH_MOUSE_LL = 14
Private Const WH_MSGFILTER = (-1)
Private Const WH_SHELL = 10
Private Const WH_SYSMSGFILTER = 6

Dim hHook As Long
Dim lngThreadId As Long
Dim lngModHWnd As Long

Public Function SetHook() As Boolean
On Error GoTo Err_SetHook
    If hHook = 0 Then
        lngThreadId = GetCurrentThreadId
        lngModHWnd = GetModuleHandle(vbNullString)
        hHook = SetWindowsHookEx(WH_CBT, AddressOf HookCallback, lngModHWnd, lngThreadId)
        If hHook <> 0 Then
            SetHook = True
            Debug.Print "Hook Set"
            Exit Function
        End If
    End If
    SetHook = False
    Debug.Print "Hook NOT Set"
Exit_SetHook:
Exit Function
Err_SetHook:
End Function

Public Function RemoveHook() As Boolean
On Error GoTo Err_RemoveHook
    If hHook <> 0 Then
        UnhookWindowsHookEx (hHook)
        hHook = 0
        RemoveHook = True
        Debug.Print "Hook Removed"
    End If
Exit_RemoveHook:
Exit Function
Err_RemoveHook:
    GoTo Exit_RemoveHook
End Function

Private Function HookCallback(ByVal Code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Debug.Print "Code: " & Code & "   cParam: " & wParam & "   lParam: " & lParam
    HookCallback = CallNextHookEx(hHook, Code, wParam, lParam)
End Function

Any ideas anyone?
0
Comment
Question by:mmurphy1005
  • 2
4 Comments
 
LVL 17

Accepted Solution

by:
zzzzzooc earned 500 total points
Comment Utility
If you're just after the window-messages and don't require low-level access to them, you may be better of with subclassing the window instead of setting a hook. I'm not sure how well that'll go with Access but here's an example...

Form1:
-----------
Option Explicit
Private Sub Form_Load()
    Call WindowHook(True, Me.hwnd)
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call WindowHook(False, Me.hwnd)
End Sub

Module1:
-------------
Option Explicit

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long

Private Const GWL_WNDPROC As Long = (-4)
Private Const WM_WINDOWPOSCHANGED = &H47

Private lngPrevProc As Long
Public Function WindowHook(ByVal blnInit As Boolean, ByVal lngHandle As Long) As Boolean
    If blnInit = True Then
        lngPrevProc = SetWindowLong(lngHandle, GWL_WNDPROC, AddressOf WindowProc)
        If lngPrevProc <> 0 Then
            WindowHook = True
        End If
    Else
        Call SetWindowLong(lngHandle, GWL_WNDPROC, lngPrevProc)
    End If
End Function
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    If uMsg = WM_WINDOWPOSCHANGED Then
        If IsIconic(hwnd) = 1 Then
            Debug.Print "Minimized: True"
        Else
            Debug.Print "Minimized: False"
        End If
    End If
    WindowProc = CallWindowProc(lngPrevProc, hwnd, uMsg, wParam, lParam)
End Function
0
 
LVL 17

Expert Comment

by:zzzzzooc
Comment Utility
ping
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now