Если у вас есть ссылка на Workbook
, для которого вы хотите установить родительский элемент формы, вам нужно всего лишь два дескриптора окна, чтобы перейти к SetParent
.Для Workbook
вы можете просто использовать переменную g_workbook
, чтобы получить ее Window
, которая предоставляет свойство Hwnd
.
Для UserForm
вам потребуется использовать вторуюВызов API (FindWindow
).Просто передайте ему заголовок вашего окна (и, необязательно, класс, если вы беспокоитесь, что он не уникален), и он возвращает дескриптор окна.Поместите это в объявления в верхней части модуля:
#If VBA7 Then
Private Declare PtrSafe Function SetParent Lib "user32" ( _
ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
#Else
Private Declare Function SetParent Lib "user32" ( _
ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
#End If
Затем сделайте вызов SetParent
, прежде чем показать форму:
Private Sub CommandButton1_Click()
With New UserForm2
.StartUpPosition = 0
Dim host As Window
Set host = g_workbook.Windows(1)
'You can also calculate these on the host position if you want.
.Left = Application.Left + (0.5 * Application.Width) - (0.5 * .Width)
.Top = Application.Top + (0.5 * Application.Height) - (0.5 * .Height)
Dim handle As Long
handle = FindWindow(vbNullString, .Caption)
SetParent handle, host.Hwnd
.Show vbModeless
End With
End Sub
Как вы и предполагали ввопрос, это похоже на работу по сортировке фокуса.Является ли он стабильным , это другой вопрос - вполне возможно, что если вы установите для родительского объекта неправильную рабочую книгу, закрытие новой родительской рабочей книги может вызвать непреднамеренное поведение.