ms-access - 使用 SetParent 使 Access 表单从 Access 中转义

标签 ms-access winapi ms-access-2013 setparent

我一直在尝试让 Microsoft Access 从主 Access 窗口中“退出”,以便我可以隐藏 Access 窗口并仅在桌面上显示表单,以便可以轻松地将其放置在其他应用程序旁边。

起初我发现了一些使用 Access 自己的 Form.PopUp 属性的代码示例,但这不能在运行时设置,只能在设计 View 中设置。尽管这似乎实现了我想要做的事情,但有两个缺点:

  • 在设计 View 和普通 View 之间切换需要“关闭”两者之间的窗口 - 我宁愿保持打开状态以保留当前状态,特别是因为它用于创建必须未保存的新记录。
  • 我想从主表单打开其他表单,除非它们也设置为“弹出”,否则这些表单似乎也不适用于这种方法。但这很麻烦,因为这些也需要放入设计 View 等,我不确定在两个弹出窗口之间切换是否容易。

  • 然后我找到了一个名为 SetParent 的 API 函数,它似乎可以满足我的需要。我使用了以下命令(VBA 语法):
    SetParent ShowForm.hWnd
    ShowWindow hWndAccessApp, SW_HIDE
    ShowWindow ShowForm.hWnd, SW_SHOWNORMAL
    

    但我遇到了两个问题(可能相关:
  • 该窗口似乎 react 迟钝(例如,我无法输入它,并且单击按钮似乎也不起作用)。
  • 当我执行 ALT+TAB 时,我得到了一个 BSOD:
    BugCheck 1000008E, {c0000005, 9e3573f5, 88d9da10, 0}
    Probably caused by : win32k.sys ( win32k!xxxNextWindow+3a6 )
    at win32k!EngLineTo+1a641
    

  • 有没有其他方法可以做到这一点,以便我可以拥有一个没有 Access 窗口的表单,该 Access 窗口能够在主 Access 窗口之外调用和显示其他 Access 表单?

    我注意到 SetParent API Documentation还有一些其他的事情需要完成 - 更改 UI 状态和更改窗口样式,但我找不到正确的方法来完成它们。这样做会解决 BSOD 和无响应问题吗?

    感谢您的任何想法!

    最佳答案

    问题的核心问题可以用下面的代码来解决。 – 但是,有一些限制(见下文)。

    我建议您将此代码粘贴到新的 VBA 模块中,但您也可以将其放入表单的模块中。

    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
    

    此代码会将任何 Access 表单转换为类似 PopUp 的表单,该表单可以移动到 Access 主窗口之外。它将窗体的父窗口设置为桌面窗口,并将删除 WS_CHILD 窗口样式并添加 WS_POPUP 样式。

    该代码可以随时调用,不需要任何特定的设计时设置。要在任何窗体上调用代码,只需调用 MakePopupWindow 方法并将目标窗体的 hWnd 传递给它。

    当前的实现有一些限制:

    1.) 当前数据库的文档窗口选项必须设置为重叠窗口。我想应该也可以使用选项卡式文档进行这项工作,但这需要对目标窗口的窗口样式进行额外的更改。

    2.) 形式的转换是单向的。我无法找到将表单重新集成回 Access 主窗口的方法。只是颠倒代码,没有用。

    关于ms-access - 使用 SetParent 使 Access 表单从 Access 中转义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16885383/

    相关文章:

    sql-server - 现有的 DAO 代码可以在 SQL Server 上运行吗?

    ms-access - 存在 32 位 Office 时手动安装 64 位 MS Access ODBC 驱动程序

    ms-access - 将 Microsoft Access 作为计划任务运行

    mysql - 卡在访问查询上

    mysql - 具有来自 Microsoft Access 中另一个表的值的计算字段

    ms-access - VBA中的等效 curl ?

    c++ - 处理 GetSidIdentifierAuthority 函数的返回值

    c++ - 当我想发送 "num8"时,SendInput 发送 "vk_up"?怎么会?

    python - 删除Python中的INI部分

    mysql - 从 SQL 导出的 View 更新 MS Access 中的表