首页 文章

Userform在错误的工作簿上打开

提问于
浏览
2

我有一个userform,它有一个命令按钮来打开另一个用户窗体 . 这在大多数情况下运行良好,但有一个特殊情况,它根本不起作用 .

所述用户表单的用户通常在多个监视器上工作并且还打开多个工作簿 . 这些其他工作簿与我的工作簿无关 .

如果用户正在监视器1上的另一个工作簿中工作,然后单击该按钮以在监视器2上打开辅助用户窗体,则辅助用户窗体将在监视器1上打开,其行为类似于其父级是另一个工作簿 . 若要更正此行为,用户需要单击监视器2的工作簿上的单元格,然后单击按钮以打开辅助用户窗体 . 所以它似乎是一个工作簿激活问题,但事实并非如此 .

我已经尝试了不同的方法来激活正确的工作簿之前显示辅助用户窗体与代码无济于事 .

这是我单击按钮时用于启动辅助用户窗体的基本代码:

Private Sub CommandButton1_Click()

    With UserForm2
        .StartUpPosition = 0
        .Left = Application.Left + (0.5 * Application.Width) - (0.5 * .Width)
        .Top = Application.Top + (0.5 * Application.Height) - (0.5 * .Height)
        .Show vbModeless

    End With

End Sub

我发现这个想法我只需要在显示之前显式设置userforms父窗口,但用户窗体根本不会打开这个代码:http://www.cpearson.com/excel/SetParent.aspx

我希望这是有道理的 . 这很难解释 .

1 回答

  • 1

    如果您要将表单的父级设置为 Workbook ,则只需将两个窗口句柄传递给SetParent . 对于 Workbook ,您可以简单地使用 g_workbook 变量来获取 Window ,这会暴露 Hwnd 属性 .

    对于 UserForm ,您需要使用第二个API调用(FindWindow) . 只需将窗口的 Headers 传递给它(如果您担心它不是唯一的,则可选择该类)并返回其窗口句柄 . 把它放在模块顶部的声明中:

    #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
    

    正如你在问题中推测的那样,这似乎可以解决问题 . 它是否稳定是一个不同的问题 - 可以想象,如果您将父项设置为错误的工作簿,则关闭新的父工作簿可能会导致意外行为 .

相关问题