5

I have been trying to get a Microsoft Access for to 'escape' from the main Access window so that I can hide the Access window and just show the form on the desktop so that it can be placed alongside other applications easily.

At first I found some code samples that use Access' own Form.PopUp property but this cannot be set at runtime, only when in design view. Although this seems to achieve what I'm trying to do, there are two drawbacks:

  1. Switching between design view and normal view requires 'closing' the window in between - I'd rather keep it open to preserve the current state especially as it's used for creating new records which are necessarily unsaved.

  2. I want to open other forms from the main one which also doesn't seem to work well with this approach unless they too are set as 'pop-up'. But this is a hassle as these would also need to be put into design view, etc and I'm not sure if it would be easy to switch between the two pop-up windows.

I then found an API function called SetParent that seemed to do what I need. I used the following commands (VBA syntax):

SetParent ShowForm.hWnd
ShowWindow hWndAccessApp, SW_HIDE
ShowWindow ShowForm.hWnd, SW_SHOWNORMAL

But I ran into two problems (probably related:

  1. The window seemed to be rather unresponsive (I couldn't type into it, for example and clicking the buttons didn't seem to work either).

  2. When I did ALT+TAB, I got a BSOD:

    BugCheck 1000008E, {c0000005, 9e3573f5, 88d9da10, 0}
    Probably caused by : win32k.sys ( win32k!xxxNextWindow+3a6 )
    at win32k!EngLineTo+1a641
    

Is there any other way to do this so that I can have a form without the access window that is able to call and display other access forms outside of the main access window?

I have noticed in the SetParent API Documentation that there are a couple of other things that need to be done - changing the UI state and changing the window style but I can't find the right methods to do them. Would doing this fix the BSOD and non-responsiveness problem?

Thanks for any ideas!

Scott
  • 4,458
  • 1
  • 19
  • 27
ec2011
  • 570
  • 6
  • 20
  • @JanW: I'm not sure your problem has much to do with this question (which is about a single form and being able to use design view). Note: see http://stackoverflow.com/a/24638829/3820271 for how to remove most of Access's UI elements. – Andre Mar 04 '16 at 08:26
  • @JanW: My answer addresses the original question. I don’t know if this will help you achieve your goal. If not, I suggest you ask a new question specifically dealing with your requirements, as they are somewhat different from what was asked here. – PhilS Mar 07 '16 at 15:39

3 Answers3

1

The core problem of the question can be solved with the following code. – However, there are some limitations (see below).

I would suggest you paste this code into a new VBA module, but you can put it inside a form’s module as well.

Private Const GWL_STYLE As Long = -16

Private Const WS_CHILD As Long = &H40000000
Private Const WS_POPUP As Long = &H80000000

Private Const SW_HIDE As Long = 0
Private Const SW_SHOW As Long = 5
Private Const SW_MINIMIZE As Long = 6

Private Declare PtrSafe Function SetParent Lib "User32.dll" (ByVal hWndChild As LongPtr, ByVal hWndNewParent As LongPtr) As LongPtr
Private Declare PtrSafe Function SetWindowLong Lib "User32.dll" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "User32.dll" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function ShowWindow Lib "User32.dll" (ByVal hWnd As LongPtr, ByVal nCmdShow As Long) As Boolean

Public Sub MakePopupWindow(ByVal hWnd As LongPtr)

    Dim windowStyle As LongPtr

    Call SetParent(hWnd, 0)

    windowStyle = GetWindowLong(hWnd, GWL_STYLE)
    windowStyle = windowStyle Xor WS_CHILD
    windowStyle = windowStyle Or WS_POPUP

    Call SetWindowLong(hWnd, GWL_STYLE, windowStyle)

    Call ShowWindow(Application.hWndAccessApp, SW_HIDE)
    Call ShowWindow(hWnd, SW_SHOW)

End Sub

This code will transform any Access form to a PopUp-like form that can be moved outside of the Access main window. It will set the parent window of the form to the desktop window and will remove the WS_CHILD window style and add the WS_POPUP style instead.

The code can be invoked any time and does not require any specific design time settings. To invoke the code on any form just call the MakePopupWindow method and pass the hWnd of the target form to it.

The current implementation has some limitations:

1.) The Document Window Option of the current database has to be set to Overlapping Windows. I guess it should be possible to make this work with Tabbed Documents as well, but that requires additional changes to the window styles of the target window.

2.) The transformation of the forms is one-way. I wasn’t able to find a way to reintegrate the forms back into the Access main window. Just reversing the code, did not work.

PhilS
  • 1,634
  • 14
  • 23
  • Dang, and I'm looking to do the opposite. Make a form loaded from a DLL act like a proper MDI child of Access. I can see the "MdiClient" sub window exists in Access, so Access seems to be following the "rules", but I just can't seem to manage it. – Roger Willcocks Apr 12 '18 at 10:30
  • @RogerWillcocks: If you find a solution to that problem, please ping me. I would be interested too. – PhilS Apr 13 '18 at 18:13
  • I can get it to load inside Access as the parent window. and I can make it maximize within the frame space, but not integrate with the main window/menu. But doing that requires you to use the MDIClient handle instead of the main window handle. @Phils – Roger Willcocks Apr 14 '18 at 23:35
0

I am doing the same thing but from C#, basically i have a tab panel where i put my MS Access windows inside, i can click on buttons but im still working on typing into textboxes, for some reason that doesnt work, i can check checkboxes and do other stuff with no problems..

Anyways, if you can leave me your email or some way i can contact you we can work this out together, 2 people have better chances of figuring it out, for now what ive done is the following:

        SetParent([Access window handle], [current handle from my tab page]);
        SetWindowPos([Access window handle], 0, 0, 0, this.Width, this.Height, 0x0001);
        SetWindowLong([Access window handle], -16, 4194304);
Rick
  • 1
  • This is not an answer but a post by someone else with the same question. I assume it was added as an answer due to stack overflow's limitations on new users writing comments. @Rick I haven't looked at this problem for several months now. I think in the end I decided to stick with option 1 of my question since I don't really know the Windows API. It looks like StackOverflow don't really have a way to send direct messages which makes it difficult - I'm not really sure how the best way for me to give you contact details securely is. Any ideas? – ec2011 Oct 12 '13 at 21:34
0

You can achieve this without any API code. Just a few easy settings.

Use regular forms, turn off tabs, and use tabbed interface.

The result is this:

enter image description here

You can add one line of VBA at startup to hide the ribbon if you wish.

DoCmd.ShowToolbar "Ribbon", acToolbarNo

I much recommend the above since no API code etc. is required. In fact only one line of code is required. If you need to launch an additional form that can be moved outside of the UI, then you can launch a popup form.

Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51