Использование SetParent для выхода формы доступа из Access

Я пытался заставить Microsoft Access "вырваться" из главного окна Access, чтобы я мог скрыть окно Access и просто показать форму на рабочем столе, чтобы ее можно было легко разместить рядом с другими приложениями.

Сначала я нашел несколько примеров кода, в которых используется собственное свойство Access Form.PopUp, но его нельзя установить во время выполнения, только в режиме конструктора. Хотя это, кажется, достигает того, что я пытаюсь сделать, есть два недостатка:

  1. Переключение между представлением конструктора и обычным представлением требует "закрытия" промежуточного окна - я бы предпочел оставить его открытым, чтобы сохранить текущее состояние, особенно потому, что оно используется для создания новых записей, которые обязательно сохраняются.

  2. Я хочу открыть другие формы из основной, которые также, кажется, не работают с этим подходом, если они тоже не установлены как "всплывающие". Но это хлопотно, так как их также необходимо поместить в дизайн, и т. Д., И я не уверен, будет ли легко переключаться между двумя всплывающими окнами.

Затем я нашел API-функцию SetParent, которая, кажется, делает то, что мне нужно. Я использовал следующие команды (синтаксис VBA):

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

Но я столкнулся с двумя проблемами (вероятно, связаны с:

  1. Окно казалось довольно не отвечающим (например, я не мог набрать его, и нажатие кнопок тоже не работало).

  2. Когда я сделал ALT+TAB, я получил BSOD:

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

Есть ли другой способ сделать это так, чтобы я мог иметь форму без окна доступа, которая может вызывать и отображать другие формы доступа за пределами основного окна доступа?

В документации SetParent API я заметил, что нужно сделать еще несколько вещей - изменить состояние пользовательского интерфейса и изменить стиль окна, но я не могу найти правильные методы для их выполнения. Решит ли это проблему с BSOD и отсутствием ответа?

Спасибо за любые идеи!

3 ответа

Основная проблема вопроса может быть решена с помощью следующего кода. - Однако существуют некоторые ограничения (см. Ниже).

Я бы посоветовал вам вставить этот код в новый модуль 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

Этот код преобразует любую форму доступа в всплывающую форму, которую можно переместить за пределы главного окна доступа. Он установит родительское окно формы в окно рабочего стола, удалит стиль окна WS_CHILD и вместо этого добавит стиль WS_POPUP.

Код может быть вызван в любое время и не требует каких-либо конкретных настроек времени разработки. Чтобы вызвать код в любой форме, просто вызовите метод MakePopupWindow и передайте ему hWnd целевой формы.

Текущая реализация имеет некоторые ограничения:

1.) Параметр "Окно документа" текущей базы данных должен иметь значение "Перекрывающиеся окна". Я предполагаю, что должна быть возможность сделать эту работу и с документами с вкладками, но это требует дополнительных изменений в стилях окон целевого окна.

2.) Преобразование форм одностороннее. Я не смог найти способ реинтеграции форм обратно в главное окно Access. Просто поменять код, не получилось.

Я делаю то же самое, но из C#, в основном у меня есть панель вкладок, где я помещаю свои окна MS Access внутрь, я могу нажимать на кнопки, но я все еще работаю над вводом в текстовые поля, по некоторым причинам, которые не работают, я могу установить флажки и делать другие вещи без проблем..

В любом случае, если вы можете оставить мне свой адрес электронной почты или каким-либо образом я могу связаться с вами, мы сможем решить это вместе, у 2 человек больше шансов выяснить это, а сейчас я сделал следующее:

        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);

Вы можете достичь этого без какого-либо кода API. Всего несколько простых настроек.

Используйте обычные формы, отключайте вкладки и используйте интерфейс с вкладками.

Результат таков:

введите описание изображения здесь

Вы можете добавить одну строку VBA при запуске, чтобы скрыть ленту, если хотите.

DoCmd.ShowToolbar "Ribbon", acToolbarNo

Я очень рекомендую выше, так как не требуется API-код и т. Д. На самом деле требуется только одна строка кода. Если вам нужно запустить дополнительную форму, которую можно переместить за пределы пользовательского интерфейса, вы можете запустить всплывающую форму.

Другие вопросы по тегам