locked
SetWindowLong on a MS Access form. What happens if IDE window is open? RRS feed

  • Question

  • Hello,

    What I am doing is by SetWindowLong I change an address of an original window procedure of a window(a form in my case) to an address of my own WindowProc, then I process one of system messages and finally I pass the intercepted message to the original window procedure.

    I tested intercepting messages subclassing:

    • A window of MS Access instance
    • A window of a form in an overlapping interface

    Both of the tests go well only if I run the main Access window without opening an IDE window before or during the test. The trouble happens if at the time of testing not only MS Access main window is open but a window of IDE too.

    The problem doesn’t arise in a first case (intercepting messages of MS Access window). While as the second case is a pain in the neck indeed (intercepting messages of a form in an overlapping interface). What happens is MS Access stops responding to user’s input. It looks like it gets looping and looping endlessly. I’d like to stress once more that such behavior takes place only when MS Access window and window of IDE are open at the same time.

    I made a test file so that you can see it for yourself.

    So, the first case(when there is no problem):

    • Open the file (DO NOT open IDE window till the end of the test)
    • Open Form1(on opening the system messages to MS Access window will start being intercepted)
    • Close Form1(on closing intercepting will be stopped)
    • Open Form 2(on opening the system messages to Form2 window will start being intercepted)
    • Close Form2(on closing intercepting will be stopped)

    So far so good.

    Now the second case (the pain in the neck):

    • Open the file
    • Open IDE window (ALT+F11)
    • Open Form1(on opening the system messages to MS Access window will start being intercepted)
    • Close Form1(on closing intercepting will be stopped)
    • Open Form 2(on opening the system messages to Form2 window are intended to start being intercepted, but you will witness an endless looping and no response from Access)

    And now are my questions:

    1. How come an open window of IDE can interfere in my subclassing of Form2 and does not affect the subclassing of MS Access window.
    2. What can be done so that I was able to subclass Form2 while the window of IDE stayed open

    I will be very grateful for your advice.

    Sergiy Vakshul

    Wednesday, August 23, 2017 11:33 PM

All replies

  • Hello,

    I failed to reproduce the issue. I would get same error when testing in Office 2010-2016:

    What is your Office version? Please update your Office to the latest and test again. Could you reproduce the issue in different Office versions or different computers?

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, August 25, 2017 5:46 AM
  • Hello, Celeste.

    This sample was intended to work on a 32bit Windows and in 32bit MS Access. I tested it on:

    Windows XP Pro + MS Access 2000, the file was converted to mdb

    Windows 7 32bit + MS Access 2010 32bit   accdb

    Windows 10 32bit + MS Access 2016 32bit  accdb

    The result was the same as I described before.

    In order to eliminate a possible influence of my office localization I renamed all the objects name using English, decompiled then compiled the file, did “compact and repare” and uploaded the test sample ones more. Please make a try again. 

    If you use a 32bit environment and still face the message you mentioned, could you be so kind and make a test file from scratch coping the code from my file to a new file created on your PC. Hope it won’t take much time.

    Friday, August 25, 2017 9:57 AM
  • Hello,

    I could reproduce the issue. I have to restart the database if opening form2 when VBE is opened.

    In your database, you set Document Windows into "Overlapping Windows". If you set it into "Tabbed Documents", VBE would not affect the windows.

    I suggest you submit a feedback at File -> Feedback for this issue.

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 28, 2017 9:54 AM
  • Hi, Celeste

    Thank you for the time you spent on me.

    If a form opens as a tabbed document Access does not stop responding immedietly. But it will stop sooner or later. Wait for some time and you’ll see. Whatever the case, I am interested in overlapping windows…

    If someone advised me on how these two windows (main Access window and IDE window) could get along together at the time I use SetWindowLong or SetWindowSubclass I would be very grateful. Till that time I decided to avoid using them while debugging.




    Monday, August 28, 2017 6:37 PM
  • Hello,

    Since this issue is complicated, I'm trying to involve some senior engineers into this issue and it will take some time. Your patience will be greatly appreciated. Sorry for any inconvenience and have a nice day! 

    Regards,

    Celeste


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, August 30, 2017 1:34 AM
  • Hi Celeste,

    I would be glad to hear any news on the subject.

    Wednesday, August 30, 2017 9:46 PM
  • Hello Sergiy,

    I had a look at the sample that you have provided and was able to reproduce the issue. It appears that the VBA editor is also doing something similar(interacting with window procedure). I would say that Sub classing in VBA is not a good idea and limit you code to the events exposed by Form object in Access VBA.

    I believe it would require more effort to find out what exactly is the problem and to find any work-around/alternative. If you would like to pursue it further, it will fall under the paid support category which requires a more in-depth level of support. 

    Please visit the below link to see the various paid support options that are available to better meet your needs.

    http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

    Regards,

    Ajay

    Tuesday, September 12, 2017 7:48 PM
  • Hello Ajay,

    Thank you for paying attention to my question.

    I decided to follow the rule: either do not open an IDE window while forms are running or use a constant blnDebugMode=True that prevents firing SetWindowLong while debugging. It is not very convenient but I do not see any alternative.


    Tuesday, September 12, 2017 8:15 PM
  • Is it feasible to simply close the VBE window in code before doing your subclassing?

    It's not clear to me whether the simple line,

        Application.VBE.MainWindow.Visible = False

    actually closes the window, or just hides it.  If it just hides it, it still might be enough to resolve your problem;  if not, then I expect you could use Windows API calls to locate and close the window.


    Dirk Goldgar, MS Access MVP
    Access tips: www.datagnostics.com/tips.html

    Wednesday, September 13, 2017 4:29 PM
  • Hello Dirk,

    Thanks for trying to help.

    To my disappointment it’s not enough to simply close the IDE window. It won’t get things back right again. It’s not the fact if the IDE window is open or closed that matters but the fact if it was once opened. Once it got opened – that’s it, we have a problem. 

    I thought in a direction to find a way to get to know if VBE window was ever opened. But even a try to refer to VBE in my code by Application.VBE.ActiveVBProject.Type whilst subclassing ended up in the same manner - Access stopped responding. You see, not only opening the VBE window is fatal but referring to VBE is no less deadly.


    Wednesday, September 13, 2017 6:21 PM
  • Dirk,

    >then I expect you could use Windows API calls to locate and close the window.

    Option Compare Database
    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 SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    Private Declare Function GetDesktopWindow Lib "user32" () As Long
    Private Declare Function GetActiveWindow Lib "user32" () As Long
    Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
        
    Private Const WM_CLOSE = &H10&
    Private Const MAX_TEXT_SIZE = 255
    Private Const GW_CHILD = 5
    Private Const GW_HWNDNEXT = 2
        
    Public lngPrevWndProc As Long
    
    
    Public Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        '
        '
        '
        WndProc = CallWindowProc(lngPrevWndProc, hwnd, uMsg, wParam, lParam)
    End Function
    
    
    Public Function FindVBEHwnd() As Long
    Dim sClass As String
    Dim sCaption As String
    Dim hwnd As Long
    
        hwnd = GetWindow(GetDesktopWindow, GW_CHILD)
        Do
            'Class?
            sClass = Space$(MAX_TEXT_SIZE + 1)
            GetClassName hwnd, sClass, MAX_TEXT_SIZE
            'Caption?
            sCaption = Space$(MAX_TEXT_SIZE + 1)
            GetWindowText hwnd, sCaption, MAX_TEXT_SIZE
            If (Trim(sCaption) = Application.VBE.MainWindow.Caption) Then
                FindVBEHwnd = hwnd
                Exit Function
            End If
            hwnd = GetWindow(hwnd, GW_HWNDNEXT)
        Loop While hwnd <> 0
    End Function
    
    Sub CloseVBEWindow_v1()
        Application.VBE.MainWindow.SetFocus
        SendMessage GetActiveWindow, WM_CLOSE, 0&, 0&
    End Sub
    
    Sub CloseVBEWindow_v2()
        SendMessage FindVBEHwnd, WM_CLOSE, 0&, 0&
    End Sub
    

    Both CloseVBEWindow_v1 and CloseVBEWindow_v2 not only close VBE window but they also close MS Access too :(

    Thursday, September 14, 2017 8:28 AM