Solved

SetWindowsHook with GETMESSAGE attribute causes Access to crash

Posted on 2004-09-01
12
899 Views
Last Modified: 2011-10-03
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
  • 6
  • 4
  • 2
12 Comments
 
LVL 4

Expert Comment

by:Colonel32
ID: 11951540
I think it's possible you're using a sledgehammer on a nut in this case. If I create a simple modal form, open it, then switch to another application window, I can still use the windows taskbar to switch back to Access and thus immediately, the modal form. Is this the process you are following? It seems to me that something else is causing the problems you are experiencing.

Could you provide some more detail on your comment
>>This is not possible manualy but done through some other apps code.
please?

Here's a solution which may workaround your current situation although it's not guaranteed!
http://www.mvps.org/access/api/api0019.htm

:)
0
 

Author Comment

by:mmurphy1005
ID: 11952478
To reproduce the problem, open a std form.  Launch a dialog form with popup and modal properties set to true.  Try to minimize access via the min max button in the top right.  You should not be able to do it.  Right click on the access tab in the task bar.  No context menu should pop up.

Ok now go to task manger and in the applications tab right click on the access instance and select minmize.  This simulates the cause of the problem I am having.

Access should now be minimized.  Now click on the access button in the task bar.  Nothing should happen.  Right click on the the button and no context menu will pop up.  The only way to restore the window is through task manager.

The question is how is access getting minimized in the first place.  The user is not doing it through taskmanager, that is just a way i found to reproduce the problem easily.  

To further explain my situation, in my app the modal window is lauching a process that takes a long time to complete.  The user switches to other apps to continue work while the process is running in the background.  Some how access is getting minimized.  The only way for the user to rstore the access window is through task manager.

with my code I am trying to intercept the minimze msg to access and throw it out when the modal window is displayed.  This will hopefully prevent access from getting minmized at all while the modal dialog window is displayed.
0
 
LVL 12

Expert Comment

by:fulscher
ID: 11953672
What happens if you remove the DEBUG messages? They might interfere.

Otherwise, I don't see anything obvious...

Jan
0
 

Author Comment

by:mmurphy1005
ID: 11956877
Tried that.  Same problem.  I was able to get the same problem from Access 2000 and 2003.  On the box with 2003 I launched the VS 2003 debugger.  The error was a message stating...

Unhandled exception as 0x65071ff2 in MSACCESS.EXE: 0x0000005: Access violation reading location 0xff17e0ca
0
 
LVL 12

Expert Comment

by:fulscher
ID: 11957339
We're missing something. Obviously, there's some memory corruption going on - but where?

Can you explain a bit how you use your code? Is this is a module? How is the code invoked?

Jan
0
 
LVL 4

Expert Comment

by:Colonel32
ID: 11961405
I still can't reproduce the problem, selecting the Access task (although the context menu is disabled) still maximizes the db container and the form with it. I'm thinking that something else is preventing the window from being repainted when the user selects the taskbar item.

What happens when the long process comes to an end? Does the window behaviour return to normal? At the very least, you should be able to use 'AppActivate' to force the window to maximize.
0
Free Gift Card with Acronis Backup Purchase!

Backup any data in any location: local and remote systems, physical and virtual servers, private and public clouds, Macs and PCs, tablets and mobile devices, & more! For limited time only, buy any Acronis backup products and get a FREE Amazon/Best Buy gift card worth up to $200!

 
LVL 12

Expert Comment

by:fulscher
ID: 11992730
mmurphy1005,

I finally came around to look at this problem a bit closer. I created a database with a module with all your code and a form containing two buttons (SetHook and RemoveHook). SetHook opens a modal form using DoCmd.OpenForm.

1st - If I use the WH_CBT filter, I can see Minimize and Maximize messages. However, I can't minimize Access if the modal form is displayed.

2nd - The DB crashes if I use the WH_GETMESSAGE, but it crashes only after the modal form is closed. I would assume that Access somehow manages to mess up its message stack.

Can you verify that you do not see the WH_CBT minimize message?

Jan
0
 

Author Comment

by:mmurphy1005
ID: 12000770
I can see the WH_CBT messages just fine.  The problem with WH_CBT is that the Access main window is already being minimized when this message is intercepted.  

I was hoping to use WH_GETMESSAGE so that I could intercept the minimize message before access starts to minmize thus preventing access from minimizing at all.
0
 
LVL 12

Expert Comment

by:fulscher
ID: 12001049
mmurphy1005,

An entirely different solution: Write a small VB program which sends the MS Access Window a maximize command once it has been mimized AND the other application is active. You could even watch the other application and pop up Access again after it has been closed. What do you think?

Jan
0
 

Author Comment

by:mmurphy1005
ID: 12001247
fulscher;

I wish it were that easy but this app must be fully encapsulated within an ADP project.  I do not want to write an external entiry that the ADP will have access to.  The ADP is run on multiple boxes and I am not in a position to modify how this is distrbuted.  Also, this ADP runs under Citrix.  I'm not event sure if my windows hook idea willunder that.

I'm confused.  Why would the WH_CBT callback work fine but the WH_GETMESSAGE callback crash access.  Am I inadvertently screwing up the wParam and lParam pointers by doing some sort of VB type conversion.  When I pass the wParam and lParam values along using CallNextHookEx, something down the line is trying to access the wrong memory location and causeing Access to crash.

The first call back works fine the first time.  As soon as this first call of the callback method ends Access crashes.
0
 
LVL 12

Accepted Solution

by:
fulscher earned 500 total points
ID: 12001289
mmurphy1005,

I'm not sure whether the parameters are incorrect. I checked them several times and I had the feeling that they were right. I think Access messes up the window handling and I'm not sure whether you can't do much against it. As I said, for me, all callbacks worked fine until the modal form was closed - then it crashed. So, I think that Access has its own window handling which the code somehow interferes with (API magic). Sorry - I don't see a way around this problem.

You couldn't even distribute a DLL to those machines? Or - another option: Don't use modal windows??

Jan
0
 
LVL 12

Expert Comment

by:fulscher
ID: 12490637
Thanks for the points. -- Did you find a solution?
Jan
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Regardless of which version on MS Access you are using, one of the harder data-entry forms to create is one where most data from previous entries needs to be appended to new records, especially when there are numerous fields and records involved.  W…
In a multiple monitor setup, if you don't want to use AutoCenter to position your popup forms, you have a problem: where will they appear?  Sometimes you may have an additional problem: where the devil did they go?  If you last had a popup form open…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
In Microsoft Access, learn the trick to repeating sub-report headings at the top of each page. The problem with sub-reports and headings: Add a dummy group to the sub report using the expression =1: Set the “Repeat Section” property of the dummy…

706 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

20 Experts available now in Live!

Get 1:1 Help Now